Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/pires/go-proxyproto
A Go library implementation of the PROXY protocol, versions 1 and 2.
https://github.com/pires/go-proxyproto
golang haproxy proxy-protocol
Last synced: 13 days ago
JSON representation
A Go library implementation of the PROXY protocol, versions 1 and 2.
- Host: GitHub
- URL: https://github.com/pires/go-proxyproto
- Owner: pires
- License: apache-2.0
- Created: 2016-08-26T19:08:54.000Z (about 8 years ago)
- Default Branch: main
- Last Pushed: 2024-07-17T03:08:35.000Z (4 months ago)
- Last Synced: 2024-08-02T15:47:56.944Z (3 months ago)
- Topics: golang, haproxy, proxy-protocol
- Language: Go
- Size: 247 KB
- Stars: 470
- Watchers: 12
- Forks: 106
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# go-proxyproto
[![Actions Status](https://github.com/pires/go-proxyproto/workflows/test/badge.svg)](https://github.com/pires/go-proxyproto/actions)
[![Coverage Status](https://coveralls.io/repos/github/pires/go-proxyproto/badge.svg?branch=master)](https://coveralls.io/github/pires/go-proxyproto?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/pires/go-proxyproto)](https://goreportcard.com/report/github.com/pires/go-proxyproto)
[![](https://godoc.org/github.com/pires/go-proxyproto?status.svg)](https://pkg.go.dev/github.com/pires/go-proxyproto?tab=doc)A Go library implementation of the [PROXY protocol, versions 1 and 2](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt),
which provides, as per specification:
> (...) a convenient way to safely transport connection
> information such as a client's address across multiple layers of NAT or TCP
> proxies. It is designed to require little changes to existing components and
> to limit the performance impact caused by the processing of the transported
> information.This library is to be used in one of or both proxy clients and proxy servers that need to support said protocol.
Both protocol versions, 1 (text-based) and 2 (binary-based) are supported.## Installation
```shell
$ go get -u github.com/pires/go-proxyproto
```## Usage
### Client
```go
package mainimport (
"io"
"log"
"net"proxyproto "github.com/pires/go-proxyproto"
)func chkErr(err error) {
if err != nil {
log.Fatalf("Error: %s", err.Error())
}
}func main() {
// Dial some proxy listener e.g. https://github.com/mailgun/proxyproto
target, err := net.ResolveTCPAddr("tcp", "127.0.0.1:2319")
chkErr(err)conn, err := net.DialTCP("tcp", nil, target)
chkErr(err)defer conn.Close()
// Create a proxyprotocol header or use HeaderProxyFromAddrs() if you
// have two conn's
header := &proxyproto.Header{
Version: 1,
Command: proxyproto.PROXY,
TransportProtocol: proxyproto.TCPv4,
SourceAddr: &net.TCPAddr{
IP: net.ParseIP("10.1.1.1"),
Port: 1000,
},
DestinationAddr: &net.TCPAddr{
IP: net.ParseIP("20.2.2.2"),
Port: 2000,
},
}
// After the connection was created write the proxy headers first
_, err = header.WriteTo(conn)
chkErr(err)
// Then your data... e.g.:
_, err = io.WriteString(conn, "HELO")
chkErr(err)
}
```### Server
```go
package mainimport (
"log"
"net"proxyproto "github.com/pires/go-proxyproto"
)func main() {
// Create a listener
addr := "localhost:9876"
list, err := net.Listen("tcp", addr)
if err != nil {
log.Fatalf("couldn't listen to %q: %q\n", addr, err.Error())
}// Wrap listener in a proxyproto listener
proxyListener := &proxyproto.Listener{Listener: list}
defer proxyListener.Close()// Wait for a connection and accept it
conn, err := proxyListener.Accept()
defer conn.Close()// Print connection details
if conn.LocalAddr() == nil {
log.Fatal("couldn't retrieve local address")
}
log.Printf("local address: %q", conn.LocalAddr().String())if conn.RemoteAddr() == nil {
log.Fatal("couldn't retrieve remote address")
}
log.Printf("remote address: %q", conn.RemoteAddr().String())
}
```### HTTP Server
```go
package mainimport (
"net"
"net/http"
"time""github.com/pires/go-proxyproto"
)func main() {
server := http.Server{
Addr: ":8080",
}ln, err := net.Listen("tcp", server.Addr)
if err != nil {
panic(err)
}proxyListener := &proxyproto.Listener{
Listener: ln,
ReadHeaderTimeout: 10 * time.Second,
}
defer proxyListener.Close()server.Serve(proxyListener)
}
```## Special notes
### AWS
AWS Network Load Balancer (NLB) does not push the PPV2 header until the client starts sending the data. This is a problem if your server speaks first. e.g. SMTP, FTP, SSH etc.
By default, NLB target group attribute `proxy_protocol_v2.client_to_server.header_placement` has the value `on_first_ack_with_payload`. You need to contact AWS support to change it to `on_first_ack`, instead.
Just to be clear, you need this fix only if your server is designed to speak first.