Wednesday, July 31, 2019

PS4 Tunneling

While setting up a couple of PS4s at work on a guest wifi network we ran into issues getting them to play well with each online.  The play station would complain about the NAT type being 3 or restrictive.  We could join a lobby that another play had hosted but not one of our own.  If we were both in the same lobby we could not see each other's cars.

The first solution I came up with involved tunneling the traffic through a Raspberry PI and GCE instance using Wireguard, IPtables and Dnsmasq.
PS4 --> Switch --> Pi --> Wifi --> GCE --> Internet

For my personal record a few snippets of the configs.
root@wireguard:~# cat /etc/rc.local
#! /bin/sh -e
ip link add dev wg0 type wireguard
wg setconf wg0 /etc/wireguard/wg0.conf
ip link set up dev wg0
ip address add dev wg0 172.16.0.1/24
# Roue packets back
ip route add 192.168.3.0/24 dev wg0
exit 0 
root@wireguard:~# cat /etc/wireguard/wg0.conf
[Interface]
ListenPort = *****
PrivateKey = *****
[Peer]
PublicKey = *****
AllowedIPs = 0.0.0.0/0
Endpoint = ***** 
root@wireguard:~# cat /etc/iptables.up.rules
# Generated by iptables-save v1.6.0 on Wed Jul 31 01:22:23 2019
*filter
:INPUT ACCEPT [67:11564]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [45:5251]
-A FORWARD -i eth0 -p udp -m udp --dport 3478:3480 -j ACCEPT
-A FORWARD -i eth0 -p tcp -m tcp --dport 3478:3480 -j ACCEPT
-A FORWARD -i eth0 -p tcp -m tcp --dport 1935 -j ACCEPT
-A FORWARD -i eth0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i wg0 -o eth0 -j ACCEPT
COMMIT
# Completed on Wed Jul 31 01:22:23 2019
# Generated by iptables-save v1.6.0 on Wed Jul 31 01:22:23 2019
*nat
:PREROUTING ACCEPT [2:160]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [4:240]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i eth0 -p udp -m udp --dport 3478:3480 -j DNAT --to-destination 192.168.3.4
-A PREROUTING -i eth0 -p tcp -m tcp --dport 3478:3480 -j DNAT --to-destination 192.168.3.4
-A PREROUTING -i eth0 -p tcp -m tcp --dport 1935 -j DNAT --to-destination 192.168.3.4
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
# Completed on Wed Jul 31 01:22:23 2019

And on the PI.  Note the MTU was dropped to 1432 in the DHCP config.
 pi@raspberrypi:~ $ cat /etc/rc.local
#!/bin/sh -e
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
# Wireguard interface
ip link add dev wg0 type wireguard
wg setconf wg0 /etc/wireguard/wg0.conf
ip link set up dev wg0
ip address add dev wg0 172.16.0.3/24
# Default route magic
wg set wg0 fwmark 1234
ip route add default dev wg0 table 2468
ip rule add not fwmark 1234 table 2468
ip rule add table main suppress_prefixlength 0
exit 0
root@raspberrypi:~# cat /etc/wireguard/wg0.conf
[Interface]
ListenPort = ****
PrivateKey = *****
[Peer]
PublicKey = ****
AllowedIPs = 0.0.0.0/0
Endpoint = **** 
root@raspberrypi:~# grep -e '^#' -v /etc/dhcpcd.conf
....
interface eth0
static ip_address=192.168.3.3/24
root@raspberrypi:~# grep -e '^#' -e '^$' -v /etc/dnsmasq.conf | tr -s \n
interface=eth0
dhcp-range=192.168.3.50,192.168.3.150,12h
dhcp-host=,2c:cc:44:6a:ae:32,192.168.3.4,12h
dhcp-option-force=26,1432
dhcp-mac=set:client_is_a_pi,B8:27:EB:*:*:*
dhcp-reply-delay=tag:client_is_a_pi,2

The max MTU size was discovered by sending pings with increasing sizes until they no longer work.
# ping google.com -c 1 -s 1432

Useful tcpdump commands
  tcpdump -i eth0 -v port 53
  tcpdump -i wg0 host 192.168.3.129
  tcpdump host 192.168.3.129 port 53
  tcpdump -i eth0
  tcpdump -i eth0 port 53
  tcpdump -i eth0 port 53 -v
  tcpdump -i eth0 portrange 3478-3480 or port 1935 -n
  tcpdump -i eth0,wg0 portrange 3478-3480 or port 1935 -n
  tcpdump -i eth0 -i wg0 portrange 3478-3480 or port 1935 -n
We noticed once the playstations were connected that most of the link light traffic on the switch was for the PS4s and not the PI.  The latest theory is that maybe uPNP is being used to discovery each other and connect locally instead through the internet.  Had this not been the case I was playing on adding a NAT rule on the PI for the PS4 hosting the lobby.  Since the traffic is local maybe we can get away without the tunnel and have the PI NAT the guest WIFI.  I cringed as I typed that.