浏览代码

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

Audrius Butkevicius 5 年之前
父节点
当前提交
71aecc5cd4
共有 2 个文件被更改,包括 45 次插入1 次删除
  1. 34 0
      lib/dialer/internal.go
  2. 11 1
      lib/dialer/public.go

+ 34 - 0
lib/dialer/internal.go

@@ -7,6 +7,7 @@
 package dialer
 
 import (
+	"net"
 	"net/http"
 	"net/url"
 	"os"
@@ -58,3 +59,36 @@ func socksDialerFunction(u *url.URL, forward proxy.Dialer) (proxy.Dialer, error)
 
 	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
+}

+ 11 - 1
lib/dialer/public.go

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