@ -28,6 +28,7 @@ import (
"tailscale.com/derp"
"tailscale.com/derp/derphttp"
"tailscale.com/logpolicy"
"tailscale.com/metrics"
"tailscale.com/stun"
"tailscale.com/tsweb"
"tailscale.com/types/key"
@ -213,51 +214,60 @@ func serveSTUN() {
log . Fatalf ( "failed to open STUN listener: %v" , err )
}
log . Printf ( "running STUN server on %v" , pc . LocalAddr ( ) )
var (
stunReadErrors = expvar . NewInt ( "stun_read_error" )
stunWriteErrors = expvar . NewInt ( "stun_write_error" )
stunReadNotSTUN = expvar . NewInt ( "stun_read_not_stun" )
stunReadNotSTUNValid = expvar . NewInt ( "stun_read_not_stun_valid" )
stunReadIPv4 = expvar . NewInt ( "stun_read_ipv4" )
stunReadIPv6 = expvar . NewInt ( "stun_read_ipv6" )
stunWrite = expvar . NewInt ( "stun_write" )
stats = new ( metrics . Set )
stunDisposition = & metrics . LabelMap { Label : "disposition" }
stunAddrFamily = & metrics . LabelMap { Label : "family" }
stunReadError = stunDisposition . Get ( "read_error" )
stunNotSTUN = stunDisposition . Get ( "not_stun" )
stunWriteError = stunDisposition . Get ( "write_error" )
stunSuccess = stunDisposition . Get ( "success" )
stunIPv4 = stunAddrFamily . Get ( "ipv4" )
stunIPv6 = stunAddrFamily . Get ( "ipv6" )
)
stats . Set ( "counter_requests" , stunDisposition )
stats . Set ( "counter_addrfamily" , stunAddrFamily )
expvar . Publish ( "stun" , stats )
var buf [ 64 << 10 ] byte
for {
n , addr , err := pc . ReadFrom ( buf [ : ] )
if err != nil {
log . Printf ( "STUN ReadFrom: %v" , err )
time . Sleep ( time . Second )
stunReadError s . Add ( 1 )
stunReadError . Add ( 1 )
continue
}
ua , ok := addr . ( * net . UDPAddr )
if ! ok {
log . Printf ( "STUN unexpected address %T %v" , addr , addr )
stunReadError s . Add ( 1 )
stunReadError . Add ( 1 )
continue
}
pkt := buf [ : n ]
if ! stun . Is ( pkt ) {
stun Read NotSTUN. Add ( 1 )
stun NotSTUN. Add ( 1 )
continue
}
txid , err := stun . ParseBindingRequest ( pkt )
if err != nil {
stun Read NotSTUNValid . Add ( 1 )
stun NotSTUN. Add ( 1 )
continue
}
if ua . IP . To4 ( ) != nil {
stun Read IPv4. Add ( 1 )
stun IPv4. Add ( 1 )
} else {
stun Read IPv6. Add ( 1 )
stun IPv6. Add ( 1 )
}
res := stun . Response ( txid , ua . IP , uint16 ( ua . Port ) )
_ , err = pc . WriteTo ( res , addr )
if err != nil {
stunWriteError s . Add ( 1 )
stunWriteError . Add ( 1 )
} else {
stun Write . Add ( 1 )
stun Success . Add ( 1 )
}
}
}