Update README.md

pull/16/head
Nick Sweeting 5 years ago committed by GitHub
parent 8a7d914b27
commit 6a2decf357
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -265,20 +265,13 @@ In summary: only direct connections between clients should be configured, any co
More complex topologies are definitely achievable, but these are the basic routing methods used in typical WireGuard setups:
- **Direct node-to-node**
In the best case, the nodes are on the same LAN or are both publicly accessible, and traffic will route over encrypted UDP packets sent directly between the nodes.
In the best case, the nodes are on the same LAN or are both publicly accessible. Define directly accessible nodes with hardcoded `Endpoint` addresses and ports so that WireGuard can connect straight to the open port and route UDP packets without intermediate hops.
- **Node behind local NAT to public node**
When 1 of the 2 parties is behind a remote NAT (e.g. when laptop behind a NAT connects to `public-server2`), the connection will be opened from NAT -> public client, then traffic will route directly between them in both directions as long as the connection is kept alive.
When 1 of the 2 parties is behind a remote NAT (e.g. when laptop behind a NAT connects to `public-server2`), define the publicly accessible node with a hardcoded `Endpoint` and the NAT-ed node without. The connection will be opened from NAT client -> public client, then traffic will route directly between them in both directions as long as the connection is kept alive by ougoing `PersistentKeepalive` pings from the NAT-ed client.
- **Node behind local NAT to node behind remote NAT (via UDP NAT hole-punching)**
"Hole Punching" refers to triggering automatic NAT rules of a router in order to allow inbound traffic. When you send a UDP packet out, the router (usually) creates a temporary rule mapping your source address and port to the destination address and port, and vice versa. This is how most UDP applications function behind NATs (e.g. Bittorent, Skype, etc). UDP packets returning from the destination address and port (and no other) are passed through to the original source address and port (and no other). This rule will timeout after some minutes of inactivity, so the client behind the NAT must send regular outgoing packets to keep it open (see `PersistentKeepalive`).
Getting this to work when both end-points are behind NATs or firewalls would require that both end-points send packets to each-other at about the same time. This means that both sides need to know each-other's public IP addresses and port numbers and need to communicate this to each-other by some other means (in our case by defining them in `wg0.conf`).
WireGuard punches holes through NATs natively as a side effect of its UDP-based design, but it only works if a `ListenPort` is hardcoded for the peer behind the NAT. It does not search for a hole-punching port dynamically like WebRTC/N2N as it has no concept of a signaling server to communicate the port to the other side, it only works with a hardcoded port and `PersistentKeepalive` set to some non-null value.
- **Node behind local NAT to node behind remote NAT (via relay)**
In the worst case when both parties are behind remote NATs, both will open a connection to `public-server1`, and traffic will forward through the intermediary bounce server as long as the connections are kept alive.
While sometimes possible, it's generally infeasible to do direct NAT-to-NAT connections on modern networks, because most NAT routers are quite strict about randomizing the srcport, making it impossible to coordinate an open port for both sides ahead of time. Instead, a signaling server (STUN) must be used that stands in the middle and communicates which random srcports are assigned to the other side. Both clients make an initial connection to the public signaling server, then it records the random srcports and sends them back so the clients, this is how WebRTC works in modern P2P web apps. Even with a signalling server and known srcports for both ends, sometimes direct connections are not possible because the NAT routers are strict about only accepting traffic from the original destination address (the signalling server), and will require a new random srcport to be opened to accept traffic from other IPs (e.g. the other client attempting to use the originally communicated srcport). This is espcially true for "carrier-grade NATs" like cellular networks and some enterprise networks, which are designed specifically to prevent this sort of hole-punching connection. See the full section below on [**NAT to NAT Connections**](#NAT-to-NAT-Connections) for more information.
Choosing the proper routing method is handled automatically by WireGuard as long as at least one server is acting as a public relay with `net.ipv4.ip_forward = 1` enabled, and clients have `AllowIPs = 10.0.0.1/24` set in the relay server `[peer]` (to take traffic for the whole subnet).
More specific (also usually more direct) routes provided by other peers will take precedence when available, otherwise traffic will fall back to the least specific route and use the `10.0.0.1/24` catchall to forward traffic to the bounce server, where it will in turn be routed by the relay server's system routing table back down the VPN to the specific peer that's accepting routes for that traffic.
More specific (also usually more direct) routes provided by other peers will take precedence when available, otherwise traffic will fall back to the least specific route and use the `10.0.0.1/24` catchall to forward traffic to the bounce server, where it will in turn be routed by the relay server's system routing table (`net.ipv4.ip_forward = 1`) back down the VPN to the specific peer that's accepting routes for that traffic. Wireguard does not automatically find the fastest route or attempt to form direct connections between peers if not already defined, it just goes from the most specific route in `[Peers]` to least specific.
You can figure out which routing method WireGuard is using for a given address by measuring the ping times to figure out the unique length of each hop, and by inspecting the output of:
```bash
@ -379,7 +372,7 @@ Overview of the general process:
- `[Peer]` Create a peer section for each public peer not behind a NAT, make sure to specify a CIDR range for the entire VPN subnet when defining the remote peer acting as the bounce server `AllowedIPs = 10.0.0.1/24`. Make sure to specify individual IPs for remote peers that don't relay traffic and only act as simple clients `AllowedIPs = 10.0.0.3/32`.
5. Start wireguard on the main relay server with `wg-quick up /full/path/to/wg0.conf`
6. Start wireguard on all the client peers with `wg-quick up /full/path/to/wg0.conf`
7. Traffic is routed from peer to peer using most optimal route over the WireGuard interface, e.g. `ping 10.0.0.3` checks for local direct route first, then checks for route via public internet, then finally tries to route by bouncing through the public relay server.
7. Traffic is routed from peer to peer using most specific route first over the WireGuard interface, e.g. `ping 10.0.0.3` checks for a direct route to a peer with `AllowedIPs = 10.0.0.3/32` first, then falls back to a relay server that's accepting ips in the whole subnet
### Setup
@ -927,36 +920,49 @@ AllowedIPs = 0.0.0.0/0, ::/0
### NAT To NAT Connections
WireGuard can natively make connections between two clients behind NATs, without need of a public relay server.
WireGuard can sometimes natively make connections between two clients behind NATs without need of a public relay server, but in most cases this is not possible. NAT-to-NAT connections are not possible unless at least one host has a stable, publicly-accessible IP address:port pair that can be hardcoded ahead of time, whether thats using a FQDN updated with dnymaic DNS, or a static public IP with a non-randomized NAT port opened by outgoing packets, anything works as long as all peers can communicate it beforehand and it doesn't change once the connection is initiated.
Wireguard does not search for a hole-punching port dynamically like WebRTC/N2N as it has no concept of a signaling server to communicate the port to the other side, it only works with a hardcoded `Endpoint` address and `ListenPort`, and `PersistentKeepalive` set to some non-null value on both sides.
#### The hole-punching connection process
1. Peer1 sends a UDP packet to Peer2, it's rejected Peer2's NAT router immediately, but that's ok, the only purpose was to get Peer1's NAT to start forwarding any expected UDP responses back to Peer1 behind its NAT
2. Peer2 sends a UDP packet to Peer1, it's accepted and fowarded to Peer1 as Peer1's NAT server is already expecting responses from Peer2 because of the initial outgoing packet
3. Peer1 sends a UDP response to Peer2's packet, it's accepted and forwarded by Peer2's NAT server as it's also expecting responses because of the initial outgoing packet
This process of sending an initial packet that gets rejected, then using the fact that the router has now created a forwarding rule to accept responses is called "UDP hole-punching".
**Requirements**
When you send a UDP packet out, the router (usually) creates a temporary rule mapping your source address and port to the destination address and port, and vice versa. UDP packets returning from the destination address and port (and no other) are passed through to the original source address and port (and no other). This is how most UDP applications function behind NATs (e.g. Bittorent, Skype, etc). This rule will timeout after some minutes of inactivity, so the client behind the NAT must send regular outgoing packets to keep it open (see `PersistentKeepalive`).
Getting this to work when both end-points are behind NATs or firewalls would require that both end-points send packets to each-other at about the same time. This means that both sides need to know each-other's public IP addresses and port numbers and need to communicate this to each-other by some other means (in our case by hard-coding them in `wg0.conf` in advance). WebRTC requires a STUN signaling server to communicate the hole-punching port because it would be impossible for browsers to hardcode listening ports for all possible connections in advance.
#### Requirements for NAT-to-NAT setups
- At least one peer has to have to have a hardcoded, directly-accessible `Endpoint` defined. If they're both behind NATs without stable IP addresses, then you'll need to use Dynammic DNS or another solution to have a stable, publicly accessibly domain/IP for at least one peer
- At least one peer has to have a hardcoded UDP `ListenPort` defined, and it's NAT router must not do UDP source port randomization, otherwise return packets will be sent to the hardocded `ListenPort` and dropped by the router, instead of using the random port assigned by the NAT on the outgoing packet
- All NAT'ed peers must have `PersistentKeepalive` enabled on all other peers, so that they continually send outgoing pings to keep connections persisted in their NAT's routing table
NAT-to-NAT connections are not possible unless at least one host has a stable address, whether thats using a FQDN updated with dnymaic DNS, or a static public IP, anything works as long as all peers can communicate it beforehand.
#### Drawbacks and limitations
As of 2019, many of the old hole-punching methods used that used to work are no longer effective. One example was a novel method pioneered by [pwnat]](https://github.com/samyk/pwnat) that faked an ICMP Time Exceeded response from outside the NAT to get a packet back through to a NAT'ed peer, thereby leaking its own srcport.
*Note:* Some users report having to restart WireGuard to force it to re-rolsve dynamic DNS hostnames for peer `Endpoint`s. You may want to use a `PostUp` hook to make this process easier.
##### Source port randomization
NAT-to-NAT connections are not possible if all endpoints are behind NAT's with strict UDP source port randomization (e.g. most cellular data networks). Since neither side is able to hardcode a `ListenPort` and guarantee that their NAT will accept traffic on that port after the outgoing ping, you cannot coordinate a port for the initial hole-punch between peers and connections will fail. For this reason, you generally cannot do phone-to-phone connections on LTE/3g networks, but you might be able to do phone-to-office or phone-to-home where the office or home has a stable public IP and doesn't do source port randomization.
The connection process looks like this:
##### Dynamic IP addresses
Many users report having to restart WireGuard whenever a dynamic IP changes, as it only resolves hostnames on startup. To force WireGuard to re-resolve dynamic DNS `Endpoint` hostnames more often, you may want to use a `PostUp` hook to restart Wireguard every few minutes or hours.
1. Peer1 sends a UDP packet to Peer2, it's rejected Peer2's NAT router immediately, but that's ok, the only purpose was to get Peer1's NAT to start forwarding any expected UDP responses back to Peer1 behind its NAT
2. Peer2 sends a UDP packet to Peer1, it's accepted and fowarded to Peer1 as Peer1's NAT server is already expecting responses from Peer2 because of the initial outgoing packet
3. Peer1 sends a UDP response to Peer2's packet, it's accepted and forwarded by Peer2's NAT server as it's also expecting responses because of the initial outgoing packet
This process of sending an initial packet that gets rejected, then using the fact that the router has now created a forwarding rule to accept responses is called "UDP hole-punching".
#### Testing it out
When you send a UDP packet out, the router (usually) creates a temporary rule mapping your source address and port to the destination address and port, and vice versa. UDP packets returning from the destination address and port (and no other) are passed through to the original source address and port (and no other). This is how most UDP applications function behind NATs (e.g. Bittorent, Skype, etc). This rule will timeout after some minutes of inactivity, so the client behind the NAT must send regular outgoing packets to keep it open (see `PersistentKeepalive`).
You can see if a hole-punching setup is feasible by using netcat on the client and server to see what ports and connection order work to get a bidirectional connection open: run `nc -v -u -p 51820 <address of peer2> 51820` (on peer1) and `nc -v -u -l 0.0.0.0 51820` (on peer2), then type in both windows to see if you can get bidirectional traffic going. If it doesn't work regardless of which peer sends the initial packet, then WireGuard won't be unable to work between the peers without a public relay server.
Getting this to work when both end-points are behind NATs or firewalls would require that both end-points send packets to each-other at about the same time. This means that both sides need to know each-other's public IP addresses and port numbers and need to communicate this to each-other by some other means (in our case by hard-coding them in `wg0.conf` in advance). WebRTC requires a STUN signaling server to communicate the hole-punching port because it would be impossible for browsers to hardcode listening ports for all possible connections in advance.
NAT-to-NAT connections are often more unstable and have other limitations, which is why having a fallback public relay server is still advised.
WireGuard punches holes through NATs natively as a side effect of it's UDP-based design, but it only works if a `ListenPort` is hardcoded for the peer behind the NAT. It does not search for a hole-punching port dynamically like WebRTC/N2N as it has no concept of a signaling server to communicate the port to the other side, it only works with a hardcoded port and `PersistentKeepalive` set to some non-null value on both sides.
This approach has some limitations, which is why having a fallback public relay server is still advised, see:
#### Further reading
- https://github.com/samyk/pwnat
- https://en.wikipedia.org/wiki/UDP_hole_punching
- https://stackoverflow.com/questions/8892142/udp-hole-punching-algorithm
- https://stackoverflow.com/questions/12359502/udp-hole-punching-not-going-through-on-3g
@ -992,7 +998,9 @@ PersistentKeepalive = 25
### Dynamic IP Allocation
Dynamic allocation of IPs (instead of only having fixed peers) is being developed, the WIP implementation is available here:
*Note: this section is about dynamic peer IPs within the VPN subnet, not dynamic public `Endpoint` addresses*.
Dynamic allocation of peer IPs (instead of only having fixed peers) is being developed, the WIP implementation is available here:
https://github.com/WireGuard/wg-dynamic
You can also build a dynamic allocation system yourself by reading in IP values from files at runtime by using `PostUp` (see below).
@ -1140,11 +1148,11 @@ For more detailed instructions, see the [Quickstart](#Quickstart) guide and API
* priv key: `<private key for public-server1.example-vpn.tld>`
* pub key: `<public key for public-server1.example-vpn.tld>`
* setup required:
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. enable kernel ip & arp forwarding, add iptables forwarding rules
5. start wireguard
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. enable kernel ip & arp forwarding, add iptables forwarding rules
5. start wireguard
* config as remote peer:
```ini
[Peer]
@ -1204,11 +1212,11 @@ AllowedIPs = 10.0.0.5/32
* priv key: `<private key for public-server2.example-vpn.dev>`
* pub key: `<public key for public-server2.example-vpn.dev>`
* setup required:
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
* config as local interface:
```ini
[Interface]
@ -1252,11 +1260,11 @@ PersistentKeepalive = 25
* priv key: `<private key for home-server.example-vpn.dev>`
* pub key: `<public key for home-server.example-vpn.dev>`
* setup required:
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
* config as local interface:
```ini
[Interface]
@ -1300,11 +1308,11 @@ PersistentKeepalive = 25
* priv key: `<private key for laptop.example-vpn.dev>`
* pub key: `<public key for laptop.example-vpn.dev>`
* setup required:
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
* config as local interface:
```ini
[Interface]
@ -1345,11 +1353,11 @@ PersistentKeepalive = 25
* priv key: `<private key for phone.example-vpn.dev>`
* pub key: `<public key for phone.example-vpn.dev>`
* setup required:
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
1. install wireguard
2. generate public/private keypair
3. create wg0.conf (see below)
4. confirm main public relay server is directly accessible
4. start wireguard
* config as local interface:
```ini
[Interface]

Loading…
Cancel
Save