diff --git a/Release.md b/Release.md index 5b2724d8..e0f5084e 100644 --- a/Release.md +++ b/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. diff --git a/client/proxy/xtcp.go b/client/proxy/xtcp.go index 31f9ac89..6e1deac3 100644 --- a/client/proxy/xtcp.go +++ b/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() diff --git a/client/visitor/xtcp.go b/client/visitor/xtcp.go index cb374b68..353577db 100644 --- a/client/visitor/xtcp.go +++ b/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) diff --git a/conf/frpc_full_example.toml b/conf/frpc_full_example.toml index d8d93a3f..dfae9573 100644 --- a/conf/frpc_full_example.toml +++ b/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" diff --git a/pkg/config/v1/common.go b/pkg/config/v1/common.go index ddb23356..38965a3c 100644 --- a/pkg/config/v1/common.go +++ b/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, diff --git a/pkg/config/v1/proxy.go b/pkg/config/v1/proxy.go index 34bd7125..37701b6d 100644 --- a/pkg/config/v1/proxy.go +++ b/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) { diff --git a/pkg/config/v1/visitor.go b/pkg/config/v1/visitor.go index f00391c3..7629875a 100644 --- a/pkg/config/v1/visitor.go +++ b/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) { diff --git a/pkg/nathole/nathole.go b/pkg/nathole/nathole.go index bdd0ee83..72522fac 100644 --- a/pkg/nathole/nathole.go +++ b/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,