proxy: add optional exponential backoff retry for NAT measurement

This commit is contained in:
KokaKiwi 2025-06-26 11:10:58 +02:00
parent 70974640ab
commit f97186784d
No known key found for this signature in database
GPG key ID: FD333F84686EFE78
4 changed files with 31 additions and 2 deletions

View file

@ -46,6 +46,8 @@ import (
"github.com/pion/transport/v3/stdnet"
"github.com/pion/webrtc/v4"
"github.com/cloudflare/backoff"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/constants"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/messages"
@ -163,6 +165,7 @@ type SnowflakeProxy struct {
NATProbeURL string
// NATTypeMeasurementInterval is time before NAT type is retested
NATTypeMeasurementInterval time.Duration
NATMeasurementRetry bool
// ProxyType is the type reported to the broker, if not provided it "standalone" will be used
ProxyType string
EventDispatcher event.SnowflakeEventDispatcher
@ -822,7 +825,14 @@ func (sf *SnowflakeProxy) Start() error {
}
tokens = newTokens(sf.Capacity)
err = sf.checkNATType(config, sf.NATProbeURL)
for {
err = sf.checkNATType(config, sf.NATProbeURL)
if getCurrentNATType() == NATUnrestricted || !sf.NATMeasurementRetry {
break
}
<-time.After(5 * time.Second)
}
if err != nil {
// non-fatal error. Log it and continue
log.Printf(err.Error())
@ -833,7 +843,21 @@ func (sf *SnowflakeProxy) Start() error {
NatRetestTask := task.Periodic{
Interval: sf.NATTypeMeasurementInterval,
Execute: func() error {
return sf.checkNATType(config, sf.NATProbeURL)
var err error
b := backoff.New(5*time.Minute, sf.NATTypeMeasurementInterval)
for {
err = sf.checkNATType(config, sf.NATProbeURL)
sf.EventDispatcher.OnNewSnowflakeEvent(event.EventOnCurrentNATTypeDetermined{CurNATType: getCurrentNATType()})
if getCurrentNATType() == NATUnrestricted || !sf.NATMeasurementRetry {
break
}
<-time.After(b.Duration())
}
return err
},
// Not setting OnError would shut down the periodic task on error by default.
OnError: func(err error) {

View file

@ -38,6 +38,7 @@ func main() {
allowNonTLSRelay := flag.Bool("allow-non-tls-relay", false, "allow this proxy to pass client's data to the relay in an unencrypted form.\nThis is only useful if the relay doesn't support encryption, e.g. for testing / development purposes.")
NATTypeMeasurementInterval := flag.Duration("nat-retest-interval", time.Hour*24,
"the time interval between NAT type is retests (see \"nat-probe-server\"). 0s disables retest. Valid time units are \"s\", \"m\", \"h\".")
natRetry := flag.Bool("nat-retry", false, "Retry NAT measurement when not unrestricted")
summaryInterval := flag.Duration("summary-interval", time.Hour,
"the time interval between summary log outputs, 0s disables summaries. Valid time units are \"s\", \"m\", \"h\".")
disableStatsLogger := flag.Bool("disable-stats-logger", false, "disable the exposing mechanism for stats using logs")
@ -114,6 +115,7 @@ func main() {
EphemeralMaxPort: ephemeralPortsRange[1],
NATTypeMeasurementInterval: *NATTypeMeasurementInterval,
NATMeasurementRetry: *natRetry,
EventDispatcher: eventLogger,
RelayDomainNamePattern: *allowedRelayHostNamePattern,