Fix fallbacks xver when original address is not TCP address (#182)

Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
This commit is contained in:
Bohan Yang 2021-01-22 11:26:57 +08:00 committed by GitHub
parent 5aa053a65f
commit 5bc1bf30ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 40 deletions

2
go.mod
View file

@ -11,7 +11,7 @@ require (
github.com/lucas-clemente/quic-go v0.19.3
github.com/miekg/dns v1.1.35
github.com/pelletier/go-toml v1.8.1
github.com/pires/go-proxyproto v0.3.3
github.com/pires/go-proxyproto v0.4.1
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
github.com/stretchr/testify v1.7.0
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499

4
go.sum
View file

@ -127,8 +127,8 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pires/go-proxyproto v0.3.3 h1:jOXGrsAfSQVFiD1hWg1aiHpLYsd6SJw/8cLN594sB7Q=
github.com/pires/go-proxyproto v0.3.3/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pires/go-proxyproto v0.4.1 h1:30QkyOjKU3FcTLiu1359sSQ7ml56wpM4i/uViqODSsI=
github.com/pires/go-proxyproto v0.4.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

View file

@ -500,38 +500,51 @@ func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err erro
postRequest := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
if fb.Xver != 0 {
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
return err
}
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
return err
}
ipv4 := true
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipv4 = false
break
var remoteAddr, remotePort, localAddr, localPort string
ipType, network := 0, connection.RemoteAddr().Network()
if len(network) >= 3 && network[:3] == "tcp" {
var err error
remoteAddr, remotePort, err = net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
return err
}
localAddr, localPort, err = net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
return err
}
ipType = 4
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipType = 6
break
}
}
}
pro := buf.New()
defer pro.Release()
switch fb.Xver {
case 1:
if ipv4 {
if ipType == 0 {
common.Must2(pro.Write([]byte("PROXY UNKNOWN\r\n")))
break
}
if ipType == 4 {
common.Must2(pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
} else {
common.Must2(pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
}
case 2:
common.Must2(pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21"))) // signature + v2 + PROXY
if ipv4 {
common.Must2(pro.Write([]byte("\x11\x00\x0C"))) // AF_INET + STREAM + 12 bytes
common.Must2(pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"))) // signature
if ipType == 0 {
common.Must2(pro.Write([]byte("\x20\x00\x00\x00"))) // v2 + LOCAL + UNSPEC + UNSPEC + 0 bytes
break
}
if ipType == 4 {
common.Must2(pro.Write([]byte("\x21\x11\x00\x0C"))) // v2 + PROXY + AF_INET + STREAM + 12 bytes
common.Must2(pro.Write(net.ParseIP(remoteAddr).To4()))
common.Must2(pro.Write(net.ParseIP(localAddr).To4()))
} else {
common.Must2(pro.Write([]byte("\x21\x00\x24"))) // AF_INET6 + STREAM + 36 bytes
common.Must2(pro.Write([]byte("\x21\x21\x00\x24"))) // v2 + PROXY + AF_INET6 + STREAM + 36 bytes
common.Must2(pro.Write(net.ParseIP(remoteAddr).To16()))
common.Must2(pro.Write(net.ParseIP(localAddr).To16()))
}

View file

@ -335,39 +335,51 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
postRequest := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
if fb.Xver != 0 {
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
return err
}
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
return err
}
ipv4 := true
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipv4 = false
break
var remoteAddr, remotePort, localAddr, localPort string
ipType, network := 0, connection.RemoteAddr().Network()
if len(network) >= 3 && network[:3] == "tcp" {
var err error
remoteAddr, remotePort, err = net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
return err
}
localAddr, localPort, err = net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
return err
}
ipType = 4
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipType = 6
break
}
}
}
pro := buf.New()
defer pro.Release()
switch fb.Xver {
case 1:
if ipv4 {
if ipType == 0 {
pro.Write([]byte("PROXY UNKNOWN\r\n"))
break
}
if ipType == 4 {
pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
} else {
pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
}
case 2:
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21")) // signature + v2 + PROXY
if ipv4 {
pro.Write([]byte("\x11\x00\x0C")) // AF_INET + STREAM + 12 bytes
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A")) // signature
if ipType == 0 {
pro.Write([]byte("\x20\x00\x00\x00")) // v2 + LOCAL + UNSPEC + UNSPEC + 0 bytes
break
}
if ipType == 4 {
pro.Write([]byte("\x21\x11\x00\x0C")) // v2 + PROXY + AF_INET + STREAM + 12 bytes
pro.Write(net.ParseIP(remoteAddr).To4())
pro.Write(net.ParseIP(localAddr).To4())
} else {
pro.Write([]byte("\x21\x00\x24")) // AF_INET6 + STREAM + 36 bytes
pro.Write([]byte("\x21\x21\x00\x24")) // v2 + PROXY + AF_INET6 + STREAM + 36 bytes
pro.Write(net.ParseIP(remoteAddr).To16())
pro.Write(net.ParseIP(localAddr).To16())
}