Skip to content

STUN Server

Status Implemented
Revision 2026-10-27, skywire f37a464a4
Code pkg/deployment/stun, pkg/services/stun, pkg/transport/network/stun_client.go, pkg/visor/init_transport.go

Abstract

The STUN server answers Binding Requests over UDP. It supports the NAT type discovery of RFC 3489, which needs the response to come from a different IP address or port than the request reached. Visors use it to learn their public address and NAT class.

Overview

A visor sends Binding Requests to the STUN servers in its configuration. The result decides whether the visor creates sudph transports and is published as the visor's NAT class in the reach declaration (see Address Resolver). The STUN server is not an HTTP service. It is the one deployment service that is reached over UDP rather than dmsg HTTP, and it holds no state.

Addressing

Each STUN server is a host:port string. The visor takes the list from the stun_servers key of its configuration. The Config Bootstrapper serves the deployment's list under the same key (see Config Bootstrapper). The server listens on IPv4 only.

Interfaces

Sockets

The server binds four UDP sockets (stunserver.Server).

Socket IP Port
1 primary primary, 3478 default
2 primary alternate, 3479 default
3 secondary primary
4 secondary alternate

Both IP addresses are required (primary_ip and secondary_ip in stun.Config). The service type name is stun-server.

Messages

The server reads datagrams of up to 1024 bytes. It parses the 20 byte STUN header and the attributes. It ignores a datagram that is shorter than the header, declares a length that exceeds the data, or is not a Binding Request (type 0x0001).

A Binding Request may carry CHANGE-REQUEST (0x0003). The server answers from the socket selected by the flags in the last byte of the value.

Flag Value Effect on the source of the response
change IP 0x04 the other IP, same port as the receiving socket
change port 0x02 the same IP, the other port
both the other IP and the other port
none the receiving socket

The response is a Binding Response (0x0101) sent to the source address of the request. It copies the transaction ID of the request and carries these attributes in this order.

Attribute Code Value
XOR-MAPPED-ADDRESS 0x0020 the client address, XOR coded
MAPPED-ADDRESS 0x0001 the client address
SOURCE-ADDRESS 0x0004 the address the response is sent from
RESPONSE-ORIGIN 0x802b the same address
CHANGED-ADDRESS 0x0005 the other IP and the other port of the receiving socket
OTHER-ADDRESS 0x802c the same address
SOFTWARE 0x8022 skywire-stun
FINGERPRINT 0x8028 CRC-32 of the message XOR 0x5354554e

An address attribute is 8 bytes: a zero byte, the family 0x01 and the port and IPv4 address. The server has no authentication, and no other message types.

Behaviour

Visor use

A visor runs the NAT discovery of the go-stun client against its configured servers in order (network.GetStunDetails). The first server that returns a result other than an error, unknown or blocked ends the search. The result is the NAT type and the public address. If every server fails, the last result is kept.

The visor does not probe on the js platform.

If the result is an error, unknown or blocked, the visor repeats the probe every 5 minutes (stunRetryInterval), and starts its sudph client when a probe succeeds. A symmetric NAT or a symmetric UDP firewall is a final result and is not repeated.

When it dials a peer, a visor tries sudph only when the NAT type is none, full cone, restricted or port restricted. It waits up to 20 s for the first probe to finish before it decides.

The public address is also a source for the public_ip it declares to the Address Resolver. The visor takes that address from the dmsg servers first and uses STUN as the fallback (resolvePublicIPForAR).

The reach declaration carries the NAT class (natClass).

stun.NATType Class arfeed.NAT*
NATNone open
NATFull full-cone
NATRestricted restricted
NATPortRestricted port-restricted
NATSymmetric symmetric
NATSymmetricUDPFirewall udp-firewall

Other results give an empty class.

Security Considerations

The server answers any datagram to any address with a response that is about the size of the request, and keeps no state. A visor trusts the reported address and NAT type of the first server that answers.

References

  • Address Resolver
  • Config Bootstrapper
  • Public Autoconnect