lib/dialer: Bring back address faking connection (fixes #6289) (#6363)

This commit is contained in:
Audrius Butkevicius 2020-02-26 11:37:23 +00:00 committed by GitHub
parent 10af09e4b4
commit 71aecc5cd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 1 deletions

View File

@ -7,6 +7,7 @@
package dialer package dialer
import ( import (
"net"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -58,3 +59,36 @@ func socksDialerFunction(u *url.URL, forward proxy.Dialer) (proxy.Dialer, error)
return proxy.SOCKS5("tcp", u.Host, auth, forward) return proxy.SOCKS5("tcp", u.Host, auth, forward)
} }
// dialerConn is needed because proxy dialed connections have RemoteAddr() pointing at the proxy,
// which then screws up various things such as IsLAN checks, and "let's populate the relay invitation address from
// existing connection" shenanigans.
type dialerConn struct {
net.Conn
addr net.Addr
}
func (c dialerConn) RemoteAddr() net.Addr {
return c.addr
}
func newDialerAddr(network, addr string) net.Addr {
netAddr, err := net.ResolveIPAddr(network, addr)
if err == nil {
return netAddr
}
return fallbackAddr{network, addr}
}
type fallbackAddr struct {
network string
addr string
}
func (a fallbackAddr) Network() string {
return a.network
}
func (a fallbackAddr) String() string {
return a.addr
}

View File

@ -24,6 +24,8 @@ var errUnexpectedInterfaceType = errors.New("unexpected interface type")
// digging through dialerConn to extract the *net.TCPConn // digging through dialerConn to extract the *net.TCPConn
func SetTCPOptions(conn net.Conn) error { func SetTCPOptions(conn net.Conn) error {
switch conn := conn.(type) { switch conn := conn.(type) {
case dialerConn:
return SetTCPOptions(conn.Conn)
case *net.TCPConn: case *net.TCPConn:
var err error var err error
if err = conn.SetLinger(0); err != nil { if err = conn.SetLinger(0); err != nil {
@ -46,6 +48,8 @@ func SetTCPOptions(conn net.Conn) error {
func SetTrafficClass(conn net.Conn, class int) error { func SetTrafficClass(conn net.Conn, class int) error {
switch conn := conn.(type) { switch conn := conn.(type) {
case dialerConn:
return SetTrafficClass(conn.Conn, class)
case *net.TCPConn: case *net.TCPConn:
e1 := ipv4.NewConn(conn).SetTOS(class) e1 := ipv4.NewConn(conn).SetTOS(class)
e2 := ipv6.NewConn(conn).SetTrafficClass(class) e2 := ipv6.NewConn(conn).SetTrafficClass(class)
@ -72,6 +76,9 @@ func dialContextWithFallback(ctx context.Context, fallback proxy.ContextDialer,
if noFallback { if noFallback {
conn, err := dialer.DialContext(ctx, network, addr) conn, err := dialer.DialContext(ctx, network, addr)
l.Debugf("Dialing no fallback result %s %s: %v %v", network, addr, conn, err) l.Debugf("Dialing no fallback result %s %s: %v %v", network, addr, conn, err)
conn = dialerConn{
conn, newDialerAddr(network, addr),
}
return conn, err return conn, err
} }
@ -84,6 +91,9 @@ func dialContextWithFallback(ctx context.Context, fallback proxy.ContextDialer,
go func() { go func() {
proxyConn, proxyErr = dialer.DialContext(ctx, network, addr) proxyConn, proxyErr = dialer.DialContext(ctx, network, addr)
l.Debugf("Dialing proxy result %s %s: %v %v", network, addr, proxyConn, proxyErr) l.Debugf("Dialing proxy result %s %s: %v %v", network, addr, proxyConn, proxyErr)
proxyConn = dialerConn{
proxyConn, newDialerAddr(network, addr),
}
close(proxyDone) close(proxyDone)
}() }()
go func() { go func() {
@ -96,7 +106,7 @@ func dialContextWithFallback(ctx context.Context, fallback proxy.ContextDialer,
go func() { go func() {
<-fallbackDone <-fallbackDone
if fallbackErr == nil { if fallbackErr == nil {
fallbackConn.Close() _ = fallbackConn.Close()
} }
}() }()
return proxyConn, nil return proxyConn, nil