Documentation
¶
Overview ¶
Package viaproxy provides the ability to manage connections that properly understand the Proxy Protocol defined by Willy Tarreau for HAProxy.
Regular net.Conn structures will return the "wrong" RemoteAddr when used behind a proxy: the remote address informed will be the one of the proxy, not the one from the client initiating the connection to the proxy. This package adds a wrapper for regular net.Conn that checks for the existence of the proxy protocol line and if present, return a net.Conn that reports the customer address when calling RemoteAddr. This wrapped connection can be casted to *viaproxy.Conn to add access to an additional ProxyAddr method that will return the proxy's address.
In order to use this extended connection type we can call Wrap on an existing connection:
ln, err := net.Listen("tcp", *addr)
if err != nil {
log.Fatal(err)
}
for {
cn, err := ln.Accept()
if err != nil {
log.Println("ln.Accept():", err)
continue
}
pcn, err := viaproxy.Wrap(cn)
if err != nil {
log.Println("Wrap():", err)
continue
}
log.Printf("remote address is: %v", pcn.RemoteAddr())
log.Printf("local address is: %v", pcn.LocalAddr())
log.Printf("proxy address is: %v", pcn.ProxyAddr())
pcn.Close()
}
Package viaproxy also provides a Listener struct that already returns viaproxy.Conn connections when calling AcceptFromProxy:
ln, err := viaproxy.Listen("tcp", *addr)
if err != nil {
log.Fatal(err)
}
for {
cn, err := ln.AcceptFromProxy()
if err != nil {
log.Println("ln.Accept():", err)
continue
}
log.Printf("remote address is: %v", cn.RemoteAddr())
log.Printf("local address is: %v", cn.LocalAddr())
log.Printf("proxy address is: %v", cn.ProxyAddr())
cn.Close()
}
The Accept method in the Listener struct returns a generic net.Conn which can safely be casted to a viaproxy.Conn:
ln, err := viaproxy.Listen("tcp", *addr)
if err != nil {
log.Fatal(err)
}
for {
cn, err := ln.Accept()
if err != nil {
log.Println("ln.Accept():", err)
continue
}
// The connection should be safe to be converted to a *viaproxy.Conn
// structure.
pcn := conn.(*viaproxy.Conn)
log.Printf("remote address is: %v", pcn.RemoteAddr())
log.Printf("local address is: %v", pcn.LocalAddr())
log.Printf("proxy address is: %v", pcn.ProxyAddr())
pcn.Close()
}
Using viaproxy.Conn objects whenever a net.Conn is expected should be safe in all cases. If you encounter an issue please send a bug report to https://github.com/inkel/viaproxy/issues
Index ¶
- type Conn
- func (c *Conn) Close() error
- func (c *Conn) LocalAddr() net.Addr
- func (c *Conn) ProxyAddr() net.Addr
- func (c *Conn) Read(b []byte) (int, error)
- func (c *Conn) RemoteAddr() net.Addr
- func (c *Conn) SetDeadline(t time.Time) error
- func (c *Conn) SetReadDeadline(t time.Time) error
- func (c *Conn) SetWriteDeadline(t time.Time) error
- func (c *Conn) Write(b []byte) (int, error)
- type Listener
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
Conn is an implementation of net.Conn interface for TCP connections that come from a proxy that users the Proxy Protocol to communicate with the upstream servers.
func Wrap ¶
Wrap takes a net.Conn and returns a pointer to Conn that knows how to properly identify the remote address if it comes via a proxy that supports the Proxy Protocol.
Example ¶
package main
import (
"log"
"net"
"github.com/inkel/viaproxy"
)
func main() {
// Listen on TCP port 8080 for connections coming from a proxy that sends
// the Proxy Protocol header.
l, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
cn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
pcn, err := viaproxy.Wrap(cn)
if err != nil {
log.Fatal(err)
}
log.Printf("remote address is: %v", pcn.RemoteAddr())
log.Printf("local address is: %v", pcn.LocalAddr())
log.Printf("proxy address is: %v", pcn.ProxyAddr())
pcn.Close()
}
}
Output:
func (*Conn) RemoteAddr ¶
RemoteAddr returns the remote network address.
func (*Conn) SetDeadline ¶
SetDeadline implements the Conn SetDeadline method.
func (*Conn) SetReadDeadline ¶
SetReadDeadline implements the Conn SetReadDeadline method.
func (*Conn) SetWriteDeadline ¶
SetWriteDeadline implements the Conn SetWriteDeadline method.
type Listener ¶
type Listener struct {
// contains filtered or unexported fields
}
Listener is a wrap on net.Listener that returns wrapped Conn objects.
func Listen ¶
Listen returns a net.Listener that will wrap Accept so it returns net.Conn that know how to work with Proxy Protocol.
func (*Listener) Accept ¶
Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
Example ¶
package main
import (
"log"
"github.com/inkel/viaproxy"
)
func main() {
// Listen on TCP port 8080 for connections coming from a proxy that sends
// the Proxy Protocol header.
l, err := viaproxy.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
// The connection should be safe to be converted to a *viaproxy.Conn
// structure.
cn := conn.(*viaproxy.Conn)
log.Printf("remote address is: %v", cn.RemoteAddr())
log.Printf("local address is: %v", cn.LocalAddr())
log.Printf("proxy address is: %v", cn.ProxyAddr())
cn.Close()
}
}
Output:
func (*Listener) AcceptFromProxy ¶
AcceptFromProxy accepts the next incoming call and returns the new connection.
Example ¶
package main
import (
"log"
"github.com/inkel/viaproxy"
)
func main() {
// Listen on TCP port 8080 for connections coming from a proxy that sends
// the Proxy Protocol header.
l, err := viaproxy.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
cn, err := l.AcceptFromProxy()
if err != nil {
log.Fatal(err)
}
log.Printf("remote address is: %v", cn.RemoteAddr())
log.Printf("local address is: %v", cn.LocalAddr())
log.Printf("proxy address is: %v", cn.ProxyAddr())
cn.Close()
}
}
Output: