Add go-proxyproto dependencies
This commit is contained in:
parent
de14e2f4f1
commit
590bc0dfc1
5 changed files with 276 additions and 0 deletions
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
|
@ -30,6 +30,10 @@
|
||||||
"ImportPath": "github.com/PuerkitoBio/urlesc",
|
"ImportPath": "github.com/PuerkitoBio/urlesc",
|
||||||
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
|
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/armon/go-proxyproto",
|
||||||
|
"Rev": "3daa90aec0039a806299b9078f4422fee950f33c"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/beorn7/perks/quantile",
|
"ImportPath": "github.com/beorn7/perks/quantile",
|
||||||
"Rev": "3ac7bf7a47d159a033b107610db8a1b6575507a4"
|
"Rev": "3ac7bf7a47d159a033b107610db8a1b6575507a4"
|
||||||
|
|
2
vendor/github.com/armon/go-proxyproto/.gitignore
generated
vendored
Normal file
2
vendor/github.com/armon/go-proxyproto/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
*.test
|
||||||
|
*~
|
21
vendor/github.com/armon/go-proxyproto/LICENSE
generated
vendored
Normal file
21
vendor/github.com/armon/go-proxyproto/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Armon Dadgar
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
36
vendor/github.com/armon/go-proxyproto/README.md
generated
vendored
Normal file
36
vendor/github.com/armon/go-proxyproto/README.md
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# proxyproto
|
||||||
|
|
||||||
|
This library provides the `proxyproto` package which can be used for servers
|
||||||
|
listening behind HAProxy of Amazon ELB load balancers. Those load balancers
|
||||||
|
support the use of a proxy protocol (http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt),
|
||||||
|
which provides a simple mechansim for the server to get the address of the client
|
||||||
|
instead of the load balancer.
|
||||||
|
|
||||||
|
This library provides both a net.Listener and net.Conn implementation that
|
||||||
|
can be used to handle situation in which you may be using the proxy protocol.
|
||||||
|
Only proxy protocol version 1, the human-readable form, is understood.
|
||||||
|
|
||||||
|
The only caveat is that we check for the "PROXY " prefix to determine if the protocol
|
||||||
|
is being used. If that string may occur as part of your input, then it is ambiguous
|
||||||
|
if the protocol is being used and you may have problems.
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
Full documentation can be found [here](http://godoc.org/github.com/armon/go-proxyproto).
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
Using the library is very simple:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
// Create a listener
|
||||||
|
list, err := net.Listen("tcp", "...")
|
||||||
|
|
||||||
|
// Wrap listener in a proxyproto listener
|
||||||
|
proxyList := &proxyproto.Listener{Listener: list}
|
||||||
|
conn, err :=proxyList.Accept()
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
213
vendor/github.com/armon/go-proxyproto/protocol.go
generated
vendored
Normal file
213
vendor/github.com/armon/go-proxyproto/protocol.go
generated
vendored
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
package proxyproto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// prefix is the string we look for at the start of a connection
|
||||||
|
// to check if this connection is using the proxy protocol
|
||||||
|
prefix = []byte("PROXY ")
|
||||||
|
prefixLen = len(prefix)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Listener is used to wrap an underlying listener,
|
||||||
|
// whose connections may be using the HAProxy Proxy Protocol (version 1).
|
||||||
|
// If the connection is using the protocol, the RemoteAddr() will return
|
||||||
|
// the correct client address.
|
||||||
|
//
|
||||||
|
// Optionally define ProxyHeaderTimeout to set a maximum time to
|
||||||
|
// receive the Proxy Protocol Header. Zero means no timeout.
|
||||||
|
type Listener struct {
|
||||||
|
Listener net.Listener
|
||||||
|
ProxyHeaderTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conn is used to wrap and underlying connection which
|
||||||
|
// may be speaking the Proxy Protocol. If it is, the RemoteAddr() will
|
||||||
|
// return the address of the client instead of the proxy address.
|
||||||
|
type Conn struct {
|
||||||
|
bufReader *bufio.Reader
|
||||||
|
conn net.Conn
|
||||||
|
dstAddr *net.TCPAddr
|
||||||
|
srcAddr *net.TCPAddr
|
||||||
|
once sync.Once
|
||||||
|
proxyHeaderTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept waits for and returns the next connection to the listener.
|
||||||
|
func (p *Listener) Accept() (net.Conn, error) {
|
||||||
|
// Get the underlying connection
|
||||||
|
conn, err := p.Listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewConn(conn, p.ProxyHeaderTimeout), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the underlying listener.
|
||||||
|
func (p *Listener) Close() error {
|
||||||
|
return p.Listener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the underlying listener's network address.
|
||||||
|
func (p *Listener) Addr() net.Addr {
|
||||||
|
return p.Listener.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConn is used to wrap a net.Conn that may be speaking
|
||||||
|
// the proxy protocol into a proxyproto.Conn
|
||||||
|
func NewConn(conn net.Conn, timeout time.Duration) *Conn {
|
||||||
|
pConn := &Conn{
|
||||||
|
bufReader: bufio.NewReader(conn),
|
||||||
|
conn: conn,
|
||||||
|
proxyHeaderTimeout: timeout,
|
||||||
|
}
|
||||||
|
return pConn
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read is check for the proxy protocol header when doing
|
||||||
|
// the initial scan. If there is an error parsing the header,
|
||||||
|
// it is returned and the socket is closed.
|
||||||
|
func (p *Conn) Read(b []byte) (int, error) {
|
||||||
|
var err error
|
||||||
|
p.once.Do(func() { err = p.checkPrefix() })
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return p.bufReader.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) Write(b []byte) (int, error) {
|
||||||
|
return p.conn.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) Close() error {
|
||||||
|
return p.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) LocalAddr() net.Addr {
|
||||||
|
return p.conn.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr returns the address of the client if the proxy
|
||||||
|
// protocol is being used, otherwise just returns the address of
|
||||||
|
// the socket peer. If there is an error parsing the header, the
|
||||||
|
// address of the client is not returned, and the socket is closed.
|
||||||
|
// Once implication of this is that the call could block if the
|
||||||
|
// client is slow. Using a Deadline is recommended if this is called
|
||||||
|
// before Read()
|
||||||
|
func (p *Conn) RemoteAddr() net.Addr {
|
||||||
|
p.once.Do(func() {
|
||||||
|
if err := p.checkPrefix(); err != nil && err != io.EOF {
|
||||||
|
log.Printf("[ERR] Failed to read proxy prefix: %v", err)
|
||||||
|
p.Close()
|
||||||
|
p.bufReader = bufio.NewReader(p.conn)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if p.srcAddr != nil {
|
||||||
|
return p.srcAddr
|
||||||
|
}
|
||||||
|
return p.conn.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) SetDeadline(t time.Time) error {
|
||||||
|
return p.conn.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) SetReadDeadline(t time.Time) error {
|
||||||
|
return p.conn.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return p.conn.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Conn) checkPrefix() error {
|
||||||
|
if p.proxyHeaderTimeout != 0 {
|
||||||
|
readDeadLine := time.Now().Add(p.proxyHeaderTimeout)
|
||||||
|
p.conn.SetReadDeadline(readDeadLine)
|
||||||
|
defer p.conn.SetReadDeadline(time.Time{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incrementally check each byte of the prefix
|
||||||
|
for i := 1; i <= prefixLen; i++ {
|
||||||
|
inp, err := p.bufReader.Peek(i)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a prefix mis-match, quit early
|
||||||
|
if !bytes.Equal(inp, prefix[:i]) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the header line
|
||||||
|
header, err := p.bufReader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
p.conn.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip the carriage return and new line
|
||||||
|
header = header[:len(header)-2]
|
||||||
|
|
||||||
|
// Split on spaces, should be (PROXY <type> <src addr> <dst addr> <src port> <dst port>)
|
||||||
|
parts := strings.Split(header, " ")
|
||||||
|
if len(parts) != 6 {
|
||||||
|
p.conn.Close()
|
||||||
|
return fmt.Errorf("Invalid header line: %s", header)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the type is known
|
||||||
|
switch parts[1] {
|
||||||
|
case "TCP4":
|
||||||
|
case "TCP6":
|
||||||
|
default:
|
||||||
|
p.conn.Close()
|
||||||
|
return fmt.Errorf("Unhandled address type: %s", parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse out the source address
|
||||||
|
ip := net.ParseIP(parts[2])
|
||||||
|
if ip == nil {
|
||||||
|
p.conn.Close()
|
||||||
|
return fmt.Errorf("Invalid source ip: %s", parts[2])
|
||||||
|
}
|
||||||
|
port, err := strconv.Atoi(parts[4])
|
||||||
|
if err != nil {
|
||||||
|
p.conn.Close()
|
||||||
|
return fmt.Errorf("Invalid source port: %s", parts[4])
|
||||||
|
}
|
||||||
|
p.srcAddr = &net.TCPAddr{IP: ip, Port: port}
|
||||||
|
|
||||||
|
// Parse out the destination address
|
||||||
|
ip = net.ParseIP(parts[3])
|
||||||
|
if ip == nil {
|
||||||
|
p.conn.Close()
|
||||||
|
return fmt.Errorf("Invalid destination ip: %s", parts[3])
|
||||||
|
}
|
||||||
|
port, err = strconv.Atoi(parts[5])
|
||||||
|
if err != nil {
|
||||||
|
p.conn.Close()
|
||||||
|
return fmt.Errorf("Invalid destination port: %s", parts[5])
|
||||||
|
}
|
||||||
|
p.dstAddr = &net.TCPAddr{IP: ip, Port: port}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue