Browse Source

xtcp: add configuration to disable assisted addresses in NAT traversal (#4951)

fatedier 2 tháng trước cách đây
mục cha
commit
80d3f332e1

+ 1 - 5
Release.md

@@ -1,7 +1,3 @@
 ## Features
 
-* Support tokenSource for loading authentication tokens from files.
-
-## Fixes
-
-* Fix SSH tunnel gateway incorrectly binding to proxyBindAddr instead of bindAddr, which caused external connections to fail when proxyBindAddr was set to 127.0.0.1.
+* Add NAT traversal configuration options for XTCP proxies and visitors. Support disabling assisted addresses to avoid using slow VPN connections during NAT hole punching.

+ 9 - 1
client/proxy/xtcp.go

@@ -64,11 +64,19 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, startWorkConnMsg *msg.StartWorkC
 	}
 
 	xl.Tracef("nathole prepare start")
-	prepareResult, err := nathole.Prepare([]string{pxy.clientCfg.NatHoleSTUNServer})
+
+	// Prepare NAT traversal options
+	var opts nathole.PrepareOptions
+	if pxy.cfg.NatTraversal != nil && pxy.cfg.NatTraversal.DisableAssistedAddrs {
+		opts.DisableAssistedAddrs = true
+	}
+
+	prepareResult, err := nathole.Prepare([]string{pxy.clientCfg.NatHoleSTUNServer}, opts)
 	if err != nil {
 		xl.Warnf("nathole prepare error: %v", err)
 		return
 	}
+
 	xl.Infof("nathole prepare success, nat type: %s, behavior: %s, addresses: %v, assistedAddresses: %v",
 		prepareResult.NatType, prepareResult.Behavior, prepareResult.Addrs, prepareResult.AssistedAddrs)
 	defer prepareResult.ListenConn.Close()

+ 9 - 1
client/visitor/xtcp.go

@@ -276,11 +276,19 @@ func (sv *XTCPVisitor) makeNatHole() {
 	}
 
 	xl.Tracef("nathole prepare start")
-	prepareResult, err := nathole.Prepare([]string{sv.clientCfg.NatHoleSTUNServer})
+
+	// Prepare NAT traversal options
+	var opts nathole.PrepareOptions
+	if sv.cfg.NatTraversal != nil && sv.cfg.NatTraversal.DisableAssistedAddrs {
+		opts.DisableAssistedAddrs = true
+	}
+
+	prepareResult, err := nathole.Prepare([]string{sv.clientCfg.NatHoleSTUNServer}, opts)
 	if err != nil {
 		xl.Warnf("nathole prepare error: %v", err)
 		return
 	}
+
 	xl.Infof("nathole prepare success, nat type: %s, behavior: %s, addresses: %v, assistedAddresses: %v",
 		prepareResult.NatType, prepareResult.Behavior, prepareResult.Addrs, prepareResult.AssistedAddrs)
 

+ 15 - 0
conf/frpc_full_example.toml

@@ -372,6 +372,14 @@ localPort = 22
 # Otherwise, visitors from same user can connect. '*' means allow all users.
 allowUsers = ["user1", "user2"]
 
+# NAT traversal configuration (optional)
+[proxies.natTraversal]
+# Disable the use of local network interfaces (assisted addresses) for NAT traversal.
+# When enabled, only STUN-discovered public addresses will be used.
+# This can improve performance when you have slow VPN connections.
+# Default: false
+disableAssistedAddrs = false
+
 [[proxies]]
 name = "vnet-server"
 type = "stcp"
@@ -411,6 +419,13 @@ minRetryInterval = 90
 # fallbackTo = "stcp_visitor"
 # fallbackTimeoutMs = 500
 
+# NAT traversal configuration (optional)
+[visitors.natTraversal]
+# Disable the use of local network interfaces (assisted addresses) for NAT traversal.
+# When enabled, only STUN-discovered public addresses will be used.
+# Default: false
+disableAssistedAddrs = false
+
 [[visitors]]
 name = "vnet-visitor"
 type = "stcp"

+ 8 - 0
pkg/config/v1/common.go

@@ -96,6 +96,14 @@ type TLSConfig struct {
 	ServerName string `json:"serverName,omitempty"`
 }
 
+// NatTraversalConfig defines configuration options for NAT traversal
+type NatTraversalConfig struct {
+	// DisableAssistedAddrs disables the use of local network interfaces
+	// for assisted connections during NAT traversal. When enabled,
+	// only STUN-discovered public addresses will be used.
+	DisableAssistedAddrs bool `json:"disableAssistedAddrs,omitempty"`
+}
+
 type LogConfig struct {
 	// This is destination where frp should write the logs.
 	// If "console" is used, logs will be printed to stdout, otherwise,

+ 3 - 0
pkg/config/v1/proxy.go

@@ -422,6 +422,9 @@ type XTCPProxyConfig struct {
 
 	Secretkey  string   `json:"secretKey,omitempty"`
 	AllowUsers []string `json:"allowUsers,omitempty"`
+
+	// NatTraversal configuration for NAT traversal
+	NatTraversal *NatTraversalConfig `json:"natTraversal,omitempty"`
 }
 
 func (c *XTCPProxyConfig) MarshalToMsg(m *msg.NewProxy) {

+ 3 - 0
pkg/config/v1/visitor.go

@@ -160,6 +160,9 @@ type XTCPVisitorConfig struct {
 	MinRetryInterval  int    `json:"minRetryInterval,omitempty"`
 	FallbackTo        string `json:"fallbackTo,omitempty"`
 	FallbackTimeoutMs int    `json:"fallbackTimeoutMs,omitempty"`
+
+	// NatTraversal configuration for NAT traversal
+	NatTraversal *NatTraversalConfig `json:"natTraversal,omitempty"`
 }
 
 func (c *XTCPVisitorConfig) Complete(g *ClientCommonConfig) {

+ 15 - 4
pkg/nathole/nathole.go

@@ -68,6 +68,13 @@ var (
 	DetectRoleReceiver = "receiver"
 )
 
+// PrepareOptions defines options for NAT traversal preparation
+type PrepareOptions struct {
+	// DisableAssistedAddrs disables the use of local network interfaces
+	// for assisted connections during NAT traversal
+	DisableAssistedAddrs bool
+}
+
 type PrepareResult struct {
 	Addrs         []string
 	AssistedAddrs []string
@@ -108,7 +115,7 @@ func PreCheck(
 }
 
 // Prepare is used to do some preparation work before penetration.
-func Prepare(stunServers []string) (*PrepareResult, error) {
+func Prepare(stunServers []string, opts PrepareOptions) (*PrepareResult, error) {
 	// discover for Nat type
 	addrs, localAddr, err := Discover(stunServers, "")
 	if err != nil {
@@ -133,9 +140,13 @@ func Prepare(stunServers []string) (*PrepareResult, error) {
 		return nil, fmt.Errorf("listen local udp addr error: %v", err)
 	}
 
-	assistedAddrs := make([]string, 0, len(localIPs))
-	for _, ip := range localIPs {
-		assistedAddrs = append(assistedAddrs, net.JoinHostPort(ip, strconv.Itoa(laddr.Port)))
+	// Apply NAT traversal options
+	var assistedAddrs []string
+	if !opts.DisableAssistedAddrs {
+		assistedAddrs = make([]string, 0, len(localIPs))
+		for _, ip := range localIPs {
+			assistedAddrs = append(assistedAddrs, net.JoinHostPort(ip, strconv.Itoa(laddr.Port)))
+		}
 	}
 	return &PrepareResult{
 		Addrs:         addrs,