... | ... | @@ -4,7 +4,7 @@ Snowflake uses STUN ([RFC 5780](https://tools.ietf.org/html/rfc5780)) to travers |
|
|
|
|
|
## Types of NATs
|
|
|
|
|
|
Not all NAT and firewall configurations are the same. Two specific peers are not necessarily guaranteed to be able to form a P2P connection using STUN. There are two different factors that determine whether the NATs are two peers are **compatible**: The NAT mapping behaviour and the NAT filtering behaviour.
|
|
|
Not all NAT and firewall configurations are the same. Two specific peers are not necessarily guaranteed to be able to form a P2P connection using STUN. There are two different factors that determine whether the NATs of two peers are **compatible**: The NAT mapping behaviour and the NAT filtering behaviour.
|
|
|
|
|
|
### NAT Mapping Behaviour
|
|
|
|
... | ... | @@ -24,11 +24,57 @@ Filtering behaviour can also be generalized into the same three types: |
|
|
- **Address-only-dependent (AO)** filtering: incoming connections are filtered if there was not a corresponding outgoing connection to the remote IP address
|
|
|
- **Address-and-port-dependent (AP)** filtering: incoming connections are filtered if there was not a corresponding outgoing connection to the remote IP address and port pair
|
|
|
|
|
|
### NAT Variations
|
|
|
|
|
|
The following [NAT variations](https://datatracker.ietf.org/doc/html/rfc3489#section-5) (that present a combination of NAT mapping and filtering behaviour) are typically seen in the wild:
|
|
|
|
|
|
- **Full Cone**: A full cone NAT is one where all requests from the
|
|
|
same internal IP address and port are mapped to the same external
|
|
|
IP address and port. Furthermore, any external host can send a
|
|
|
packet to the internal host, by sending a packet to the mapped
|
|
|
external address.
|
|
|
|
|
|
Mapping: AI
|
|
|
Filtering: AI
|
|
|
|
|
|
- **Restricted Cone**: A restricted cone NAT is one where all requests
|
|
|
from the same internal IP address and port are mapped to the same
|
|
|
external IP address and port. Unlike a full cone NAT, an external
|
|
|
host (with IP address X) can send a packet to the internal host
|
|
|
only if the internal host had previously sent a packet to IP
|
|
|
address X.
|
|
|
|
|
|
|
|
|
Mapping: AI
|
|
|
Filtering: AO
|
|
|
|
|
|
- **Port Restricted Cone**: A port restricted cone NAT is like a
|
|
|
restricted cone NAT, but the restriction includes port numbers.
|
|
|
Specifically, an external host can send a packet, with source IP
|
|
|
address X and source port P, to the internal host only if the
|
|
|
internal host had previously sent a packet to IP address X and
|
|
|
port P.
|
|
|
|
|
|
|
|
|
Mapping: AI
|
|
|
Filtering: AP
|
|
|
|
|
|
- **Symmetric**: A symmetric NAT is one where all requests from the
|
|
|
same internal IP address and port, to a specific destination IP
|
|
|
address and port, are mapped to the same external IP address and
|
|
|
port. If the same host sends a packet with the same source
|
|
|
address and port, but to a different destination, a different
|
|
|
mapping is used. Furthermore, only the external host that
|
|
|
receives a packet can send a UDP packet back to the internal host.
|
|
|
|
|
|
Mapping: AO or AP
|
|
|
Filtering: AO or AP
|
|
|
|
|
|
### NAT Compatibility
|
|
|
|
|
|
The following chart shows which NATs are compatible with each other. Columns and rows show the NAT type in the form: (mapping, filtering). Pairwise compatible NATs are marked with a checkmark (:heavy_check_mark:), and incompatible NATs are marked with an X.
|
|
|
|
|
|
![snowflake-chart](uploads/b1fe413b3b87b7f42f6666b9d09f60ef/snowflake-chart.png)
|
|
|
![nat-table](uploads/46ccf47ad7862a8130f7c32eae0c8a77/nat-table.png)
|
|
|
|
|
|
## TURN Servers
|
|
|
|
... | ... | @@ -44,9 +90,9 @@ Fortunately, we don't have to match specific clients to specific proxies. We can |
|
|
|
|
|
The broker is responsible for sorting proxies into buckets, according to which types of NATs they are compatible with. When a client polls, the broker picks a proxy out of a compatible bucket to give to the client.
|
|
|
|
|
|
In practice, we don't need 9 buckets for each possible combination of mapping and filtering behaviour. We simplify this to 2 buckets:
|
|
|
- **unrestricted**: proxies in this bucket will work with all clients, even those with the most restrictive symmetric NATs and filtering behaviour. Only (AI,AI) and (AI,AO) proxies belong in this bucket.
|
|
|
- **restricted**: all proxies that aren't (AI,AI) or (AI,AO) are restricted. Most[^1] of the proxies in this bucket will work for clients without symmetric NATs.
|
|
|
In practice, we don't need buckets for each possible combination of mapping and filtering behaviour. We simplify this to 2 buckets:
|
|
|
- **unrestricted**: proxies in this bucket will work with all clients, even those with the most restrictive symmetric NATs and filtering behaviour. This includes proxies with no NATs, full cone NATs, and restricted cone NATs.
|
|
|
- **restricted**: all other proxies are restricted. This includes port restricted cone NATs and symmetric NATs. Most[^1] of the proxies in this bucket will work for clients without symmetric NATs.
|
|
|
|
|
|
### Determining NAT behaviour
|
|
|
|
... | ... | |