Implement NAT discovery (RFC 5780) at the client

Snowflake clients will now attempt NAT discovery using the provided STUN
servers and report their NAT type to the Snowflake broker for matching.
The three possibilities for NAT types are:
- unknown (the client was unable to determine their NAT type),
- restricted (the client has a restrictive NAT and can only be paired
with unrestricted NATs)
- unrestricted (the client can be paired with any other NAT).
This commit is contained in:
Cecylia Bocovich 2020-06-10 17:16:12 -04:00
parent 1448c3885f
commit bf924445e3
5 changed files with 296 additions and 0 deletions

View file

@ -16,6 +16,7 @@ import (
pt "git.torproject.org/pluggable-transports/goptlib.git"
sf "git.torproject.org/pluggable-transports/snowflake.git/client/lib"
"git.torproject.org/pluggable-transports/snowflake.git/common/nat"
"git.torproject.org/pluggable-transports/snowflake.git/common/safelog"
"github.com/pion/webrtc/v2"
)
@ -158,6 +159,8 @@ func main() {
if err != nil {
log.Fatalf("parsing broker URL: %v", err)
}
go updateNATType(iceServers, broker)
snowflakes.Tongue = sf.NewWebRTCDialer(broker, iceServers)
// Use a real logger to periodically output how much traffic is happening.
@ -219,3 +222,26 @@ func main() {
snowflakes.End()
log.Println("snowflake is done.")
}
// loop through all provided STUN servers until we exhaust the list or find
// one that is compatable with RFC 5780
func updateNATType(servers []webrtc.ICEServer, broker *sf.BrokerChannel) {
var restrictedNAT bool
var err error
for _, server := range servers {
addr := strings.TrimPrefix(server.URLs[0], "stun:")
restrictedNAT, err = nat.CheckIfRestrictedNAT(addr)
if err == nil {
if restrictedNAT {
broker.SetNATType(nat.NATRestricted)
} else {
broker.SetNATType(nat.NATUnrestricted)
}
break
}
}
if err != nil {
broker.SetNATType(nat.NATUnknown)
}
}