Date: Sun, 11 Jun 2017 09:50:53 +0200 From: Damjan Jovanovic <damjan.jov@gmail.com> To: freebsd-net@freebsd.org Subject: [patch] NAT hole punching, RFC 4787, and PF/LibAlias/IPFILTER Message-ID: <CAJm2B-k07Tm7RSS9SW0odZg7rpDY63GZcnh2Z90_EY7AfVCHjw@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hi Gaming, VoIP, WebRTC, peer to peer, and many other UDP applications, require the ability to send to and receive from multiple peers through a single UDP socket, and/or communicate the address of this socket to others so they know where to transmit to. Historically NAT usually got in the way, but many applications are NAT-friendly these days, and can establish connections using NAT hole punching, which is the best available technique of NAT traversal, able to work through any number of layers of NAT (eg. both SOHO NAT and carrier grade NAT), requires no special configuration, allows applications to discover the external IP:port that the NAT gave them, and even allows clients to connect to each other when both are NATed. What NAT hole punching needs to work most of all, is what RFC 4787 calls an endpoint-independent mapping NAT, also called a "full cone" NAT: all UDP packets from the internal IP:port pair X:x, go through the same external Y:y no matter the Z:z, and nothing but X:x uses Y:y: Internal External X:x -----> NAT Y:y ----> Z:z This allows X:x to discover the Y:y that the NAT gives it by querying an external server (eg. a STUN server), and rely on packets sent to any Z:z to have Y:y as the source. It can communicate Y:y to a Z:z somehow, and have that Z:z send to it (possibly after first sending to Z:z). This is a mandatory requirement in RFC 4787. Sadly, of FreeBSD's firewalls/NATs, only IPFILTER supports this desirable property (as does "iptables" on Linux). PF's NAT and the LibAlias-based NATs (IPFW, and presumably natd and pppd) are "symmetric" NATs, the worst kind, randomly choosing a different Y:y for each Z:z from the same X:x, which makes it impossible for X:x to predict its Y:y, which makes it impossible for Z:z to learn about Y:y and reach it, especially if Z:z is itself also behind a symmetric NAT. Connections will either fail, or applications will resort to relaying data through other servers (eg. TURN), often compromising bandwidth, latency, security, and/or privacy, and increasing cost. So I've written patches to change NAT port selection in PF and LibAlias to endpoint-independent mapping. Please see here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=219803 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=219918 Currently neither are "full cone" NATs: Z:z can only send to X:x through Y:y if X:x previously sent to Z:z, so they are "address- and port-restricted cone" NATs, or rather an endpoint-independent mapping NAT with address and port-dependent filtering. But applications can discover this using a protocol such as STUN, and can still connect to known peers by sending them a packet first. There's more work to do. RFC 4787 lists several requirements, of which we still fail on at least timeouts and hairpinning. Hairpinning is particularly difficult: on IPFW the hairpinned packet doesn't even reach LibAlias, and on PF there's a whole new path through the code. It may also be desirable to implement a full-cone NAT, at least as an optional extra due to the lower security, but that requires a different traversal of the firewall rules, as unsolicited packets from Z:z to Y:y will match a NAT rule backwards. Would anyone like to help? Thank you Damjan Jovanovic References: [1] http://alumnus.caltech.edu/~dank/peer-nat.html [2] http://www.brynosaurus.com/pub/net/p2pnat [3] https://tools.ietf.org/html/rfc4787 [4] https://tools.ietf.org/html/rfc5128
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJm2B-k07Tm7RSS9SW0odZg7rpDY63GZcnh2Z90_EY7AfVCHjw>