Skip to content

Add proxy protocol support #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [1.13.x, 1.14.x]
go-version: [1.20.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
Expand Down
27 changes: 17 additions & 10 deletions cmd/tcp-proxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ var (
connid = uint64(0)
logger proxy.ColorLogger

localAddr = flag.String("l", ":9999", "local address")
remoteAddr = flag.String("r", "localhost:80", "remote address")
verbose = flag.Bool("v", false, "display server actions")
veryverbose = flag.Bool("vv", false, "display server actions and all tcp data")
nagles = flag.Bool("n", false, "disable nagles algorithm")
hex = flag.Bool("h", false, "output hex")
colors = flag.Bool("c", false, "output ansi colors")
unwrapTLS = flag.Bool("unwrap-tls", false, "remote connection with TLS exposed unencrypted locally")
match = flag.String("match", "", "match regex (in the form 'regex')")
replace = flag.String("replace", "", "replace regex (in the form 'regex~replacer')")
localAddr = flag.String("l", ":9999", "local address")
remoteAddr = flag.String("r", "localhost:80", "remote address")
verbose = flag.Bool("v", false, "display server actions")
veryverbose = flag.Bool("vv", false, "display server actions and all tcp data")
nagles = flag.Bool("n", false, "disable nagles algorithm")
hex = flag.Bool("h", false, "output hex")
colors = flag.Bool("c", false, "output ansi colors")
unwrapTLS = flag.Bool("unwrap-tls", false, "remote connection with TLS exposed unencrypted locally")
match = flag.String("match", "", "match regex (in the form 'regex')")
replace = flag.String("replace", "", "replace regex (in the form 'regex~replacer')")
proxyProtocol = flag.Bool("p", false, "Enable proxy protocol for passthrought the real IP")
proxyProtocolVersion = flag.Int("pv", 2, "Proxy protocol version (1, 2) default: 2")
)

func main() {
Expand Down Expand Up @@ -90,6 +92,11 @@ func main() {
Color: *colors,
}

p.ProxyProtocol = proxy.ProxyProtocol{
Enabled: *proxyProtocol,
Version: byte(*proxyProtocolVersion),
}

go p.Start()
}
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ go 1.13
require (
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
github.com/pires/go-proxyproto v0.7.0 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
29 changes: 25 additions & 4 deletions proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import (
"crypto/tls"
"io"
"net"

proxyproto "github.com/pires/go-proxyproto"
)

// Proxy - Manages a Proxy connection, piping data between local and remote.
type Proxy struct {
sentBytes uint64
receivedBytes uint64
laddr, raddr *net.TCPAddr
lconn, rconn io.ReadWriteCloser
lconn, rconn net.Conn
erred bool
errsig chan bool
tlsUnwrapp bool
Expand All @@ -21,9 +23,15 @@ type Proxy struct {
Replacer func([]byte) []byte

// Settings
Nagles bool
Log Logger
OutputHex bool
Nagles bool
Log Logger
OutputHex bool
ProxyProtocol ProxyProtocol
}

type ProxyProtocol struct {
Version byte
Enabled bool
}

// New - Create a new Proxy instance. Takes over local connection passed in,
Expand Down Expand Up @@ -64,6 +72,7 @@ func (p *Proxy) Start() {
} else {
p.rconn, err = net.DialTCP("tcp", nil, p.raddr)
}

if err != nil {
p.Log.Warn("Remote connection failed: %s", err)
return
Expand All @@ -83,6 +92,18 @@ func (p *Proxy) Start() {
//display both ends
p.Log.Info("Opened %s >>> %s", p.laddr.String(), p.raddr.String())

if p.ProxyProtocol.Enabled {
header := &proxyproto.Header{
Version: p.ProxyProtocol.Version,
Command: proxyproto.PROXY,
TransportProtocol: proxyproto.TCPv4,
SourceAddr: p.lconn.RemoteAddr(),
DestinationAddr: p.rconn.RemoteAddr(),
}
p.Log.Info("Send proxy header from (%s to %s)", header.SourceAddr.String(), header.DestinationAddr.String())
header.WriteTo(p.rconn)
}

//bidirectional copy
go p.pipe(p.lconn, p.rconn)
go p.pipe(p.rconn, p.lconn)
Expand Down