How to configure WireGuard to tunnel traffic from a macOS client through a Debian server with IPv4 and IPv6
- Follow the installation instructions on the WireGuard website.
- Generate keypairs for both the client and server: wg genkey | tee privatekey | wg pubkey > publickey
- Put the following in /etc/wireguard/wg0.conf on your Linux box, modifying accordingly.
Address = 10.222.222.1/24, fd00:222:222::1/64
ListenPort = REPLACE_WITH_SERVER_PORT
PrivateKey = REPLACE_WITH_SERVER_PRIVATE_KEY
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PublicKey = REPLACE_WITH_CLIENT_PUBLIC_KEY
AllowedIPs = 10.222.222.2/32, fd00:222:222::2/128
- Put the following in /etc/wireguard/utun.conf on your Mac, modifying accordingly. macOS requires the utun naming; choose utun[0-9] if you want to be explicit, but with no trailing integer the OS will choose one for you. Additionally, this config uses CloudFlare's DNS servers, but that line is not a requirement.
Address = 10.222.222.2/32, fd00:222:222::2/128
PrivateKey = REPLACE_WITH_CLIENT_PRIVATE_KEY
DNS = 126.96.36.199, 2606:4700:4700::1111
Endpoint = REPLACE_WITH_SERVER_IP:REPLACE_WITH_SERVER_PORT
PublicKey = REPLACE_WITH_SERVER_PUBLIC_KEY
AllowedIPs = 0.0.0.0/0, ::/0
- Ensure IPv4 and IPv6 forwarding are enabled. Add net.ipv4.ip_forward=1 and net.ipv6.conf.all.forwarding=1 to /etc/sysctl.conf and run sysctl -p.
- For unclear reasons, the static IP address on my VPS had its primary IPv6 preferred lifetime set to 0, i.e., deprecated. When the WireGuard IPv6 interface came up, no packets were routed through the deprecated interface, so I had to explicitly set its preferred lifetime to forever. The preferred-lifetime option in /etc/network/interfaces didn't work for me, so I added this explicit post-up line to the interface definition in /etc/network/interfaces:
post-up ip addr change REPLACE_WITH_SERVER_PUBLIC_IPV6_ADDR/64 dev eth0 preferred_lft forever
- Start the interface on the server: wg-quick up wg0
- Start the interface on the client: wg-quick up utun
You should be good to go. (I know I should do IPv6 The Real Way(tm) and not NAT, but one step at a time.)