mirror of
https://github.com/fatedier/frp.git
synced 2025-07-04 23:41:29 +07:00
xtcp: when connection timeout occurs, support fallback to STCP (#3460)
This commit is contained in:
@ -661,9 +661,10 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
BindAddr: "127.0.0.1",
|
||||
BindPort: 9001,
|
||||
},
|
||||
Protocol: "quic",
|
||||
MaxRetriesAnHour: 8,
|
||||
MinRetryInterval: 90,
|
||||
Protocol: "quic",
|
||||
MaxRetriesAnHour: 8,
|
||||
MinRetryInterval: 90,
|
||||
FallbackTimeoutMs: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,10 @@ type BaseVisitorConf struct {
|
||||
Sk string `ini:"sk" json:"sk"`
|
||||
ServerName string `ini:"server_name" json:"server_name"`
|
||||
BindAddr string `ini:"bind_addr" json:"bind_addr"`
|
||||
BindPort int `ini:"bind_port" json:"bind_port"`
|
||||
// BindPort is the port that visitor listens on.
|
||||
// It can be less than 0, it means don't bind to the port and only receive connections redirected from
|
||||
// other visitors. (This is not supported for SUDP now)
|
||||
BindPort int `ini:"bind_port" json:"bind_port"`
|
||||
}
|
||||
|
||||
type SUDPVisitorConf struct {
|
||||
@ -63,10 +66,12 @@ type STCPVisitorConf struct {
|
||||
type XTCPVisitorConf struct {
|
||||
BaseVisitorConf `ini:",extends"`
|
||||
|
||||
Protocol string `ini:"protocol" json:"protocol,omitempty"`
|
||||
KeepTunnelOpen bool `ini:"keep_tunnel_open" json:"keep_tunnel_open,omitempty"`
|
||||
MaxRetriesAnHour int `ini:"max_retries_an_hour" json:"max_retries_an_hour,omitempty"`
|
||||
MinRetryInterval int `ini:"min_retry_interval" json:"min_retry_interval,omitempty"`
|
||||
Protocol string `ini:"protocol" json:"protocol,omitempty"`
|
||||
KeepTunnelOpen bool `ini:"keep_tunnel_open" json:"keep_tunnel_open,omitempty"`
|
||||
MaxRetriesAnHour int `ini:"max_retries_an_hour" json:"max_retries_an_hour,omitempty"`
|
||||
MinRetryInterval int `ini:"min_retry_interval" json:"min_retry_interval,omitempty"`
|
||||
FallbackTo string `ini:"fallback_to" json:"fallback_to,omitempty"`
|
||||
FallbackTimeoutMs int `ini:"fallback_timeout_ms" json:"fallback_timeout_ms,omitempty"`
|
||||
}
|
||||
|
||||
// DefaultVisitorConf creates a empty VisitorConf object by visitorType.
|
||||
@ -134,7 +139,9 @@ func (cfg *BaseVisitorConf) check() (err error) {
|
||||
err = fmt.Errorf("bind_addr shouldn't be empty")
|
||||
return
|
||||
}
|
||||
if cfg.BindPort <= 0 {
|
||||
// BindPort can be less than 0, it means don't bind to the port and only receive connections redirected from
|
||||
// other visitors
|
||||
if cfg.BindPort == 0 {
|
||||
err = fmt.Errorf("bind_port is required")
|
||||
return
|
||||
}
|
||||
@ -155,7 +162,6 @@ func (cfg *BaseVisitorConf) unmarshalFromIni(prefix string, name string, section
|
||||
if cfg.BindAddr == "" {
|
||||
cfg.BindAddr = "127.0.0.1"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -169,7 +175,6 @@ func preVisitorUnmarshalFromIni(cfg VisitorConf, prefix string, name string, sec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -268,7 +273,9 @@ func (cfg *XTCPVisitorConf) Compare(cmp VisitorConf) bool {
|
||||
if cfg.Protocol != cmpConf.Protocol ||
|
||||
cfg.KeepTunnelOpen != cmpConf.KeepTunnelOpen ||
|
||||
cfg.MaxRetriesAnHour != cmpConf.MaxRetriesAnHour ||
|
||||
cfg.MinRetryInterval != cmpConf.MinRetryInterval {
|
||||
cfg.MinRetryInterval != cmpConf.MinRetryInterval ||
|
||||
cfg.FallbackTo != cmpConf.FallbackTo ||
|
||||
cfg.FallbackTimeoutMs != cmpConf.FallbackTimeoutMs {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -290,6 +297,9 @@ func (cfg *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section
|
||||
if cfg.MinRetryInterval <= 0 {
|
||||
cfg.MinRetryInterval = 90
|
||||
}
|
||||
if cfg.FallbackTimeoutMs <= 0 {
|
||||
cfg.FallbackTimeoutMs = 1000
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -87,9 +87,10 @@ func Test_Visitor_UnmarshalFromIni(t *testing.T) {
|
||||
BindAddr: "127.0.0.1",
|
||||
BindPort: 9001,
|
||||
},
|
||||
Protocol: "quic",
|
||||
MaxRetriesAnHour: 8,
|
||||
MinRetryInterval: 90,
|
||||
Protocol: "quic",
|
||||
MaxRetriesAnHour: 8,
|
||||
MinRetryInterval: 90,
|
||||
FallbackTimeoutMs: 1000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -63,20 +63,20 @@ var (
|
||||
}
|
||||
|
||||
// mode 2, HardNAT is receiver, EasyNAT is sender
|
||||
// sender, portsRandomNumber 1000, sendDelayMs 2000 | receiver, listen 256 ports, ttl 7
|
||||
// sender, portsRandomNumber 1000, sendDelayMs 2000 | receiver, listen 256 ports, ttl 4
|
||||
// sender, portsRandomNumber 1000, sendDelayMs 2000 | receiver, listen 256 ports
|
||||
// sender, portsRandomNumber 1000, sendDelayMs 3000 | receiver, listen 256 ports, ttl 7
|
||||
// sender, portsRandomNumber 1000, sendDelayMs 3000 | receiver, listen 256 ports, ttl 4
|
||||
// sender, portsRandomNumber 1000, sendDelayMs 3000 | receiver, listen 256 ports
|
||||
mode2Behaviors = []lo.Tuple2[RecommandBehavior, RecommandBehavior]{
|
||||
lo.T2(
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 2000},
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 3000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, TTL: 7},
|
||||
),
|
||||
lo.T2(
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 2000},
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 3000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, TTL: 4},
|
||||
),
|
||||
lo.T2(
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 2000},
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 3000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256},
|
||||
),
|
||||
}
|
||||
@ -98,21 +98,21 @@ var (
|
||||
}
|
||||
|
||||
// mode 4, Regular ports changes are usually the sender.
|
||||
// sender, portsRandomNumber 1000, sendDelayMs: 2000 | receiver, listen 256 ports, ttl 7, portsRangeNumber 10
|
||||
// sender, portsRandomNumber 1000, sendDelayMs: 2000 | receiver, listen 256 ports, ttl 4, portsRangeNumber 10
|
||||
// sender, portsRandomNumber 1000, SendDelayMs: 2000 | receiver, listen 256 ports, portsRangeNumber 10
|
||||
// sender, portsRandomNumber 1000, sendDelayMs: 2000 | receiver, listen 256 ports, ttl 7, portsRangeNumber 2
|
||||
// sender, portsRandomNumber 1000, sendDelayMs: 2000 | receiver, listen 256 ports, ttl 4, portsRangeNumber 2
|
||||
// sender, portsRandomNumber 1000, SendDelayMs: 2000 | receiver, listen 256 ports, portsRangeNumber 2
|
||||
mode4Behaviors = []lo.Tuple2[RecommandBehavior, RecommandBehavior]{
|
||||
lo.T2(
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 2000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, TTL: 7, PortsRangeNumber: 10},
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 3000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, TTL: 7, PortsRangeNumber: 2},
|
||||
),
|
||||
lo.T2(
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 2000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, TTL: 4, PortsRangeNumber: 10},
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 3000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, TTL: 4, PortsRangeNumber: 2},
|
||||
),
|
||||
lo.T2(
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 2000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, PortsRangeNumber: 10},
|
||||
RecommandBehavior{Role: DetectRoleSender, PortsRandomNumber: 1000, SendDelayMs: 3000},
|
||||
RecommandBehavior{Role: DetectRoleReceiver, ListenRandomPorts: 256, PortsRangeNumber: 2},
|
||||
),
|
||||
}
|
||||
)
|
||||
|
@ -85,11 +85,6 @@ func ClassifyNATFeature(addresses []string, localIPs []string) (*NatFeature, err
|
||||
}
|
||||
}
|
||||
|
||||
natFeature.PortsDifference = portMax - portMin
|
||||
if natFeature.PortsDifference <= 10 && natFeature.PortsDifference >= 1 {
|
||||
natFeature.RegularPortsChange = true
|
||||
}
|
||||
|
||||
switch {
|
||||
case ipChanged && portChanged:
|
||||
natFeature.NatType = HardNAT
|
||||
@ -104,6 +99,12 @@ func ClassifyNATFeature(addresses []string, localIPs []string) (*NatFeature, err
|
||||
natFeature.NatType = EasyNAT
|
||||
natFeature.Behavior = BehaviorNoChange
|
||||
}
|
||||
if natFeature.Behavior == BehaviorPortChanged {
|
||||
natFeature.PortsDifference = portMax - portMin
|
||||
if natFeature.PortsDifference <= 5 && natFeature.PortsDifference >= 1 {
|
||||
natFeature.RegularPortsChange = true
|
||||
}
|
||||
}
|
||||
return natFeature, nil
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ func sendSidMessageToRangePorts(
|
||||
if err := sendFunc(conn, detectAddr); err != nil {
|
||||
xl.Trace("send sid message from %s to %s error: %v", conn.LocalAddr(), detectAddr, err)
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user