Le 11/07/2018 à 21:12, Christian Worm Mortensen a écrit : > Hi Greg, > >>> I have run two Chrome browsers each behind their own Linux NAT. I have >>> then tried to instruct them to establish a P2P connection with each >>> other using WebRTC. WebRTC is a standard framework that allows P2P >>> communication between browsers and which is available from JavaScript. >>> >>> It turned out that the two browsers were not able to establish a P2P >>> connection. I Made a real test between two real systems: - both at the same ISP (free.fr) - one Ubuntu 14.04 system behind free.fr's "Revolution" box known to be running Linux (https://floss.freebox.fr/freebox_server/3.2.0/index.html, so apparently at least running Linux 4.2), in router/NAT mode. - one Debian 9.5 system behind a Debian 9.5 router/NAT system running kernel 4.16.x itself also behind a freebox, but in switch mode (so completely transparent). - the Ubuntu system runs chromium-browser (65.0.3325.181-0ubuntu0.14.04.1) - the Debian system runs chromium (67.0.3396.87-1~deb9u1) - both systems have a RFC1918 type IP behind their router. - both routers are doing standard MASQUERADE without any WebRTC related DNAT. - both systems "rendez-vous" using WebRTC by using this demo site: https://appr.tc/ and choosing the same join number. It just worked. both systems exchange UDP packets directly and display remote peer's camera video. The UDP packets don't flow through appr.tc but between the two router's public IPs (which de-SNAT them accordingly to their internal system). appr.tc is mostly here as broker to synchronize the direct establishment of the flows between the peers. So it seems your testing didn't work because of an unknown factor, but not because of Linux and you shouldn't conclude Linux NAT does not support NAT hole punching. What is very important: the router/NAT system should *drop* unknown outside incoming packets (thus not generate TCP RST or ICMP unreachable errors). If it doesn't drop packets before conntrack allow reverse-SNATing them because of the internal outgoing flow, then the internal system will give up early and attemps will fail. It's easy to test UDP or TCP hole punching outside of any complex application: by running socat on both sides and choosing the adequate source and destination ports. Here's a full easily reproducible example using network namespaces, to be run as root, using 5 network namespaces: one for each system, one for each router + one for "internet". ###################################### for i in s1 r1 in r2 s2; do ip netns del "$i" 2>/dev/null || : ; done ip netns add s1 ip netns add r1 ip netns add in ip netns add r2 ip netns add s2 ip -n s1 link add eth0 type veth peer name lan0 netns r1 ip -n r1 link add wan0 type veth peer name left0 netns in ip -n in link add right0 type veth peer name wan0 netns r2 ip -n r2 link add lan0 type veth peer name eth0 netns s2 ip netns exec r1 iptables -P INPUT DROP ip netns exec r1 iptables -P FORWARD DROP ip netns exec r1 iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ip netns exec r1 iptables -A FORWARD -i lan0 -j ACCEPT ip netns exec r1 iptables -t nat -A POSTROUTING -o wan0 -j MASQUERADE ip netns exec r2 iptables -P INPUT DROP ip netns exec r2 iptables -P FORWARD DROP ip netns exec r2 iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT ip netns exec r2 iptables -A FORWARD -i lan0 -j ACCEPT ip netns exec r2 iptables -t nat -A POSTROUTING -o wan0 -j MASQUERADE ip -n s1 address add 192.0.2.2/24 dev eth0 ip -n r1 address add 192.0.2.1/24 dev lan0 ip -n r1 address add 198.51.100.11/24 dev wan0 ip -n in address add 198.51.100.1/24 dev left0 ip -n in address add 203.0.113.1/24 dev right0 ip -n r2 address add 203.0.113.12/24 dev wan0 ip -n r2 address add 192.0.2.1/24 dev lan0 ip -n s2 address add 192.0.2.2/24 dev eth0 ip -n in route add unreachable 192.0.2.0/24 # enforce routers' NAT for i in s1 r1 in r2 s2; do ip -n "$i" link set lo up; done ip -n s1 link set eth0 up ip -n s1 route add default via 192.0.2.1 ip -n r1 link set lan0 up ip -n r1 link set wan0 up ip -n r1 route add default via 198.51.100.1 ip -n in link set left0 up ip -n in link set right0 up ip -n r2 link set wan0 up ip -n r2 route add default via 203.0.113.1 ip -n r2 link set lan0 up ip -n s2 link set eth0 up ip -n s2 route add default via 192.0.2.1 ###################################### The most important part in the setup above is probably '-P INPUT DROP' To test (requires simultaneous use of two terminals, as root): UDP: ###################################### #term1: ip netns exec s1 socat udp4:203.0.113.12:2222,reuseaddr,sourceport=1111 - #term2: ip netns exec s2 socat udp4:198.51.100.11:1111,reuseaddr,sourceport=2222 - ###################################### Send a line on both side. After the first line will be lost, both system will have established the same udp flow. TCP: Works exactly the same with tcp (by using a dual SYN/SYN initial handshake, as per rfc793 3.4 figure 8: https://tools.ietf.org/html/rfc793#section-3.4 + rfc1122 4.2.2.10 https://tools.ietf.org/html/rfc1122#page-87 ) ###################################### #term1: ip netns exec s1 socat tcp4:203.0.113.12:2222,reuseaddr,sourceport=1111 - #term2: ip netns exec s2 socat tcp4:198.51.100.11:1111,reuseaddr,sourceport=2222 - ###################################### (use ctrl-D not ctrl-C or a FIN_WAIT might appear). You can observe what's happening on both sides of "internet" with: #term3: ip netns exec in tcpdump -n -s0 -p -i any ip > Best, > > Christian > -- Regards, Adel -- To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html