# This should really be set per host, but I'm abusing the fact that there's only # one vpn_server host wireguard_addresses: - "{{ wireguard_ipv6_subnet | ansible.utils.ipaddr('net') | ansible.utils.ipaddr('1') }}" wireguard_endpoint: "{{ inventory_hostname }}" wireguard_preup: - echo 1 > /proc/sys/net/ipv4/ip_forward - echo 1 > /proc/sys/net/ipv6/conf/all/forwarding wireguard_postup: | {% filter from_yaml %} {% for value in (nat_map | dict2items | map(attribute='value')) %} - ip -6 addr add {{ value.vps_ipv6 }} dev eth0 # Incoming packets to this node's public IP are DNAT'd and forwarded to the # matching internal VPN IP - ip6tables -t nat -A PREROUTING -p tcp -d {{ value.vps_ipv6 }} --dport 20000:20100 -j DNAT --to-destination {{ value.vpn_ipv6 }} # Incoming packets to an internal VPN IP are SNAT'd to use this node's public # IP. I think `-j MASQUERADE` might work here rather than doing the SNAT # manually(?), but I don't mind being explicit here. - ip6tables -t nat -A POSTROUTING -p tcp -s {{ value.vpn_ipv6 }} -j SNAT --to-source {{ value.vps_ipv6 }} # Same thing with UDP. We do this selectively so we don't mess with things # like ICMP6 and whatnot. - ip6tables -t nat -A PREROUTING -p udp -d {{ value.vps_ipv6 }} --dport 20000:20100 -j DNAT --to-destination {{ value.vpn_ipv6 }} - ip6tables -t nat -A POSTROUTING -p udp -s {{ value.vpn_ipv6 }} -j SNAT --to-source {{ value.vps_ipv6 }} {% endfor %} {% endfilter %} # Exact reverse of above to delete all the rules wireguard_predown: | {% filter from_yaml %} {% for value in (nat_map | dict2items | map(attribute='value') | reverse) %} - ip6tables -t nat -D POSTROUTING -p udp -s {{ value.vpn_ipv6 }} -j SNAT --to-source {{ value.vps_ipv6 }} - ip6tables -t nat -D PREROUTING -p udp -d {{ value.vps_ipv6 }} --dport 20000:20100 -j DNAT --to-destination {{ value.vpn_ipv6 }} - ip6tables -t nat -D POSTROUTING -p tcp -s {{ value.vpn_ipv6 }} -j SNAT --to-source {{ value.vps_ipv6 }} - ip6tables -t nat -D PREROUTING -p tcp -d {{ value.vps_ipv6 }} --dport 20000:20100 -j DNAT --to-destination {{ value.vpn_ipv6 }} - ip -6 addr del {{ value.vps_ipv6 }} dev eth0 {% endfor %} {% endfilter %} wireguard_postdown: - echo 0 > /proc/sys/net/ipv6/conf/all/forwarding - echo 0 > /proc/sys/net/ipv4/ip_forward # https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/ # Above recommends to just add specific routing rules rather than compute # an equivalent list of subnets # # Yes, this is supposed to be defined on vpn_server rather than vpn_client, like # I initially thought. The reason for this is likely because the role was meant # for a fully meshed network rather than a single server with multiple clients, # and each host defines a list of IPs that should be routed _to this host_, not # a list of IPs that should be routed to the "server" (because everyone is a # peer in a fully meshed network) wireguard_allowed_ips: "::0/0"