Using Wireguard to expose a public IPv4 subnet to VMs behind a LAN

Summary

I want to use Wireguard to allow VMs on my home network to each have one unique public IP from a /27 pool (32 IPs) that I have routed to a dedicated server with a hosting provider.

My goal is to avoid using SNAT/DNAT, and instead just use static routes whenever possible, so that the WAN-facing interface of each VM can claim a public IP.

What Works

  • My laptop ==> Proxmox servers and VMs using private IPs on a few different VLANs (so, inter-VLAN routing is working fine)
  • Proxmox servers ==> Internet through my local gateway's NAT
  • Cloud-hosted dedicated server ==> Internet

What Doesn't Work

The problem I'm facing is that I can't send/receive ping or ssh (or any traffic that I've tried) across the Wireguard tunnel (just from one end of the tunnel to the other), suggesting I have some configuration wrong.


High-Level Config

Datacenter Hosted

Server

  • Ubuntu 20.04 LTS x86_64
  • Network config is done using systemd-networkd 245
  • Firewall is ufw (currently wide open for testing)
  • Server has multiple public IP subnets allocated to it - including a dedicated /32 for management that won't be getting exposed to VMs
  • One of the public subnets, hereafter represented as "44.44.44.0/27" is what I want to expose to the VMs on my home network.
  • Has Wireguard IP 10.10.10.1

Home Network

Gateway

  • RHEL8 x86_64
  • Network config is done using systemd-networkd v239
  • Firewall is Shorewall (currently wide open for testing)
  • Wireguard tools and kernel module are installed
  • Has a 4-port Intel I350-T4 NIC, with one port connected to the ISP and one connected to Managed Switch
  • Configured systemd-networkd and Shorewall to NAT on VLAN 1 ("untagged"), VLAN 70 ("Proxmox Management VLAN"), and VLAN 80 ("VM private VLAN")
  • Has Wireguard IP 10.10.10.2

Cisco Managed Switch (CMS)

  • Cisco RV345 in switch mode (no WAN port use, no IPv4 routing, no NAT)
  • VLAN port mapping is as follows: VLAN 1 => all ports untagged except the port to Dumb Switch for Proxmox (DSP). VLAN 70 => all ports Excluded except the port to Gateway = Tagged, and the port to DSP = Untagged. VLAN 80 => all ports Excluded except the port to Gateway = Tagged, and the port to DSP = Tagged. VLAN 90 => all ports Excluded except the port to Gateway = Tagged, and the port to DSP = Tagged.
  • Devices connected to the CMS other than the DSP and Gateway are on VLAN 1 and do not need routed public IPs; they just go through Gateway's NAT and use my home network's public IP.

Dumb Switch for Proxmox (DSP)

  • Netgear GS308v3
  • Ports occupied by several Proxmox Hosts (PHs) and one connection to CMS
  • No on-device configuration, but it does preserve 802.1Q VLAN tags that are passed to it

Proxmox Hosts (PHs)

  • Running Proxmox VE 6.3 x86_64
  • Each box has one GbE NIC connected to DSP
  • Sends untagged traffic on private subnet 10.0.0.128/25 as the Proxmox Management VLAN (CMS tags the traffic when sending it to Gateway)
  • Has a vmbr0 (virtual Layer 2 bridge) connecting VMs to the network. The nice part about this is I can test out my layer 3 IP config settings on a VM without potentially breaking the networking of the Proxmox host.

Proxmox VM (PVM)

  • Running Ubuntu 20.04 LTS
  • Network config is done using systemd-networkd 245
  • Two virtual NICs....
  • One on VLAN 80 on private subnet 10.0.1.0/24 that works for outbound Internet traffic (via my local ISP) when the default gateway is set to 10.0.1.1 (Gateway's VLAN 80 IP). Also works for inbound LAN traffic (including from other VLANs, like VLAN 1 where my laptop is) for SSH access.
  • One on VLAN 90 intended to be on public subnet 44.44.44.0/27; when the default gateway is set to Gateway's VLAN 90 IP, or the Wireguard IP of Gateway, or the Wireguard IP of Server, the box has no functioning networking. It can't ping any of these boxes with the default gateway set on the VLAN 90 NIC. I don't expect this to work until I solve the problem with Wireguard though.

Config Dump

IPv6 is trimmed from printouts since it isn't in the picture. All routing, etc. that I'm doing is exclusively IPv4.

Representative IPs

I "anonymized" some public IPs within these configs to hide my actual identity.

  • 44.44.44.0/27: Represents the public /27 I want my VMs to be able to claim, via Wireguard and clever routing.
  • 55.55.55.0/24: Represents the public "management interface" of Server. This is NOT being routed to my local network, and is just used to SSH to Server and for connecting the WG tunnel.
  • 71.71.71.0/24: Represents the public IP of my home Internet. I have one dynamic IP obtained via DHCP from the ISP's gateway. Gateway's public IP is represented here by 71.71.71.200, and the ISP's infrastructure gateway is represented by 71.71.71.1.

Server

╭─root@server /etc/systemd/network
╰─# wg show all
interface: wg0 public key: (public key) private key: (hidden) listening port: 12345
peer: (peer) preshared key: (hidden) endpoint: 71.71.71.200:35795 allowed ips: 10.10.10.0/24, 44.44.44.0/27 latest handshake: 23 seconds ago transfer: 143.44 KiB received, 115.30 MiB sent
╭─root@server /etc/systemd/network
╰─# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 12:34:(some MAC) brd 12:34:(some MAC)
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) # VFs used for existing VMs on the server vf 0 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking off, link-state auto, trust off vf 1 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking off, link-state auto, trust off vf 2 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking off, link-state auto, trust off vf 3 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking on, link-state auto, trust off vf 4 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking on, link-state auto, trust off vf 5 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking on, link-state auto, trust off vf 6 link/ether 12:34:(some MAC) brd 12:34:(some MAC) spoof checking on, link-state auto, trust off
3: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
4: enp2s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
5: enp2s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
6: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
12: eno1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
13: eno1v4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
14: eno1v5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
15: eno1v6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
29: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
30: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
61: tap15ad56cf: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master lxdbr0 state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
74: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/none
╭─root@server /etc/systemd/network
╰─# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 12:34:(some MAC) brd 12:34:(some MAC) inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 55.55.55.1/24 brd 55.55.55.255 scope global eno1 valid_lft forever preferred_lft forever
3: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
4: enp2s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
5: enp2s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
6: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 10.231.114.1/24 scope global lxdbr0 valid_lft forever preferred_lft forever
12: eno1v3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
13: eno1v4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
14: eno1v5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
15: eno1v6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
29: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 valid_lft forever preferred_lft forever
30: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
61: tap15ad56cf: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master lxdbr0 state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
74: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 10.10.10.1/32 scope global wg0 valid_lft forever preferred_lft forever
╭─root@server /etc/systemd/network
╰─# ip route
default via 55.55.55.254 dev eno1 proto static
10.231.114.0/24 dev lxdbr0 proto kernel scope link src 10.231.114.1
44.44.44.0/27 via 10.10.10.1 dev wg0 proto static
55.55.55.0/24 dev eno1 proto kernel scope link src 55.55.55.1
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
╭─root@server /etc/systemd/network
╰─# for i in $(ls *.net*); do echo '----'"${i}"'----'; cat "${i}"; done
----50-default.network----
[Match]
MACAddress=12:34:(some MAC)
[Network]
Description=network interface on public network, with default route
DHCP=no
Address=55.55.55.1/24
Gateway=55.55.55.254
IPv6AcceptRA=no
NTP=pool.ntp.org
DNS=127.0.0.1
DNS=1.1.1.1
----wg0.netdev----
[NetDev]
Name = wg0
Kind = wireguard
Description = wg server to expose 44.44.44.0/27
[WireGuard]
# For systemd >= 242
PrivateKeyFile = /etc/systemd/network/wg-private.key
ListenPort = 12345
[WireGuardPeer]
PublicKey = (public key)
AllowedIPs = 44.44.44.0/27,10.10.10.0/24
# For systemd >= 242
PresharedKeyFile = /etc/systemd/network/wg-preshared.key
----wg0.network----
[Match]
Name = wg0
[Network]
Address = 10.10.10.1/32
[Route]
Gateway = 10.10.10.1
Destination = 44.44.44.0/27

Gateway

[root@gateway network]# wg show all
interface: wg0 public key: (public key) private key: (hidden) listening port: 35795
peer: (public key) preshared key: (hidden) endpoint: 55.55.55.1:12345 allowed ips: 10.10.10.0/24, 44.44.44.0/27 latest handshake: 2 minutes, 1 second ago transfer: 3.18 MiB received, 2.17 KiB sent persistent keepalive: every 25 seconds
[root@gateway network]# systemctl --version
systemd 239 (239-41.el8_3.2)
+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy
[root@gateway network]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 12:34:(some MAC) brd 12:34:(some MAC)
2: wan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
3: eno1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
4: lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
5: enp2s0f2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
6: enp2s0f3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
7: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/none
8: lan0.70@lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
9: lan0.80@lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
10: lan0.90@lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
[root@gateway network]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 12:34:(some MAC) brd 12:34:(some MAC) inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: wan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 71.71.71.200/24 brd 71.71.71.255 scope global dynamic wan0 valid_lft 4925sec preferred_lft 4925sec
3: eno1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
4: lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 10.0.0.1/25 brd 10.0.0.127 scope global lan0 valid_lft forever preferred_lft forever
5: enp2s0f2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
6: enp2s0f3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC)
7: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 10.10.10.2/32 scope global wg0 valid_lft forever preferred_lft forever
8: lan0.70@lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 10.0.0.129/25 brd 10.0.0.255 scope global lan0.70 valid_lft forever preferred_lft forever
9: lan0.80@lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 10.0.1.1/24 brd 10.0.1.255 scope global lan0.80 valid_lft forever preferred_lft forever
10: lan0.90@lan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 12:34:(some MAC) brd 12:34:(some MAC) inet 44.44.44.3/27 brd 44.44.44.254 scope global lan0.90 valid_lft forever preferred_lft forever
[root@gateway network]# ip route show table all
default via 44.44.44.1 dev lan0.90 table 47 proto static onlink
10.0.0.0/25 dev lan0.90 table 47 proto static scope link
10.0.1.0/24 dev lan0.90 table 47 proto static scope link
10.0.2.0/24 dev lan0.90 table 47 proto static scope link
default via 71.71.71.1 dev wan0 proto dhcp src 71.71.71.200 metric 1024
10.0.0.0/25 dev lan0 proto kernel scope link src 10.0.0.1
10.0.0.128/25 dev lan0.70 proto kernel scope link src 10.0.0.129
10.0.1.0/24 dev lan0.80 proto kernel scope link src 10.0.1.1
44.44.44.0/27 via 10.10.10.1 dev wg0 proto static onlink
71.71.71.0/24 dev wan0 proto kernel scope link src 71.71.71.200
71.71.71.1 dev wan0 proto dhcp scope link src 71.71.71.200 metric 1024
broadcast 10.0.0.0 dev lan0 table local proto kernel scope link src 10.0.0.1
local 10.0.0.1 dev lan0 table local proto kernel scope host src 10.0.0.1
broadcast 10.0.0.127 dev lan0 table local proto kernel scope link src 10.0.0.1
broadcast 10.0.0.128 dev lan0.70 table local proto kernel scope link src 10.0.0.129
local 10.0.0.129 dev lan0.70 table local proto kernel scope host src 10.0.0.129
broadcast 10.0.0.255 dev lan0.70 table local proto kernel scope link src 10.0.0.129
broadcast 10.0.1.0 dev lan0.80 table local proto kernel scope link src 10.0.1.1
local 10.0.1.1 dev lan0.80 table local proto kernel scope host src 10.0.1.1
broadcast 10.0.1.255 dev lan0.80 table local proto kernel scope link src 10.0.1.1
local 10.10.10.2 dev wg0 table local proto kernel scope host src 10.10.10.2
broadcast 44.44.44.0 dev lan0.90 table local proto kernel scope link src 44.44.44.3
local 44.44.44.3 dev lan0.90 table local proto kernel scope host src 44.44.44.3
broadcast 44.44.44.254 dev lan0.90 table local proto kernel scope link src 44.44.44.3
broadcast 71.71.71.0 dev wan0 table local proto kernel scope link src 71.71.71.200
local 71.71.71.200 dev wan0 table local proto kernel scope host src 71.71.71.200
broadcast 71.71.71.255 dev wan0 table local proto kernel scope link src 71.71.71.200
broadcast 127.0.0.0 dev lo table local proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1
::1 dev lo proto kernel metric 256 pref medium
local ::1 dev lo table local proto kernel metric 0 pref medium
[root@gateway network]# for i in $(ls *.net*); do echo '----'"${i}"'----'; cat "${i}"; done
----lan0.70.netdev----
[NetDev]
Name=lan0.70
Kind=vlan
[VLAN]
Id=70
----lan0.70.network----
[Match]
Name=lan0.70
[Network]
DHCP=no
Address=10.0.0.129/25
DHCPServer=yes
IPMasquerade=ipv4
[DHCPServer]
PoolOffset=100
PoolSize=20
EmitDNS=yes
DNS=1.1.1.1
DNS=8.8.8.8
----lan0.80.netdev----
[NetDev]
Name=lan0.80
Kind=vlan
[VLAN]
Id=80
----lan0.80.network----
[Match]
Name=lan0.80
[Network]
DHCP=no
Address=10.0.1.1/24
DHCPServer=yes
IPMasquerade=ipv4
[DHCPServer]
PoolOffset=100
PoolSize=20
EmitDNS=yes
DNS=1.1.1.1
DNS=8.8.8.8
----lan0.90.netdev----
[NetDev]
Name=lan0.90
Kind=vlan
[VLAN]
Id=90
----lan0.90.network----
[Match]
Name=lan0.90
[Network]
DHCP=no
Address=44.44.44.3/27
DHCPServer=no
[RoutingPolicyRule]
Table=47
From=44.44.44.0/27
#Not sure if needed - tried with and without
#[Route]
#Table=47
#Scope=link
#Type=unicast
#Destination=44.44.44.0/27
#Also not sure if needed - tried with and without
[Route]
Table=47
GatewayOnLink=true
Gateway=44.44.44.1
Destination=0.0.0.0/0
Scope=global
[Route]
Table=47
Scope=link
Type=unicast
Destination=10.0.0.0/25
[Route]
Table=47
Scope=link
Type=unicast
Destination=10.0.1.0/24
[Route]
Table=47
Scope=link
Type=unicast
Destination=10.0.2.0/24
----lan0.network----
[Match]
Name=lan0
[Network]
Address=10.0.0.1/25
VLAN=lan0.70
VLAN=lan0.80
VLAN=lan0.90
DHCPServer=yes
IPMasquerade=ipv4
[DHCPServer]
PoolOffset=2
PoolSize=100
EmitDNS=yes
DNS=1.1.1.1
DNS=8.8.8.8
----wan0.network----
[Match]
Name=wan0
[Network]
DHCP=yes
DNS=1.1.1.1 8.8.8.8
----wg0.netdev----
[NetDev]
Name = wg0
Kind = wireguard
Description = wg client for 44.44.44.0/27
[WireGuard]
# For systemd < 242
PrivateKey = (private key)
[WireGuardPeer]
PublicKey = (public key)
AllowedIPs = 44.44.44.1/27,10.10.10.0/24
Endpoint = 55.55.55.1:12345
# If running systemd >= 242
#PresharedKeyFile = /etc/systemd/network/wg-preshared.key
# If running systemd < 242
PresharedKey = (preshared key)
PersistentKeepalive = 25
----wg0.network----
[Match]
Name = wg0
[Network]
Address = 10.10.10.2/32
[Route]
Gateway = 10.10.10.1
Destination = 44.44.44.0/27
GatewayOnlink = true
[root@gateway network]# for i in $(ls *.link); do echo '----'"${i}"'----'; cat "${i}"; done
----10-lan0.link----
[Match]
MACAddress=12:34:(some MAC)
[Link]
Name=lan0
----10-wan0.link----
[Match]
MACAddress=12:34:(some MAC)
[Link]
Name=wan0
# Shorewall config
[root@gateway shorewall]# for i in zones interfaces policy rules snat; do echo '----'"${i}"'----'; cat "${i}"; done
----zones----
#ZONE TYPE OPTIONS IN_OPTIONS OUT_OPTIONS
fw firewall
lan ip
wan ip
lan80 ip
wan90 ip
wg ip
----interfaces----
?FORMAT 2
#ZONE INTERFACE OPTIONS
lan lan0 dhcp
wan wan0
lan lan0.70 dhcp
lan80 lan0.80
wan90 lan0.90
wg wg0
----policy----
#SOURCE DEST POLICY LOGLEVEL RATE CONNLIMIT
wan all REJECT info
wg all ACCEPT
all wg ACCEPT
all wan ACCEPT
all lan80 ACCEPT
lan80 all ACCEPT
all wan90 ACCEPT
wan90 all ACCEPT
all all REJECT info
----rules----
#ACTION SOURCE DEST PROTO DPORT SPORT ORIGDEST RATE USER MARK CONNLIMIT TIME HEADERS SWITCH HELPER
?SECTION ALL
?SECTION ESTABLISHED
?SECTION RELATED
?SECTION INVALID
?SECTION UNTRACKED
?SECTION NEW
Ping(ACCEPT) all all
ACCEPT lan $FW tcp ssh
----snat----
#ACTION SOURCE DEST PROTO PORT IPSEC MARK USER SWITCH ORIGDEST PROBABILITY
MASQUERADE lan0 wan0
MASQUERADE lan0.70 wan0
MASQUERADE lan0.80 wan0

PHs and PVM config omitted because I can't even get the two ends of the WG tunnel to talk yet.

3

1 Answer

The problem I'm facing is that I can't send/receive ping or ssh (or any traffic that I've tried) across the Wireguard tunnel (just from one end of the tunnel to the other), suggesting I have some configuration wrong.

The tutorial that you're following designates a /24 for the WireGuard network. It configures each endpoint's wg0 interface with a /32 prefix, then manually defines a route for the remaining /24, which is an (unnecessarily) verbose equivalent of just configuring the actual address as a /24 prefix.

Either way, the tutorial's configuration leads to each peer having a direct route to the other peer's address – the client knows that 10.213.213.2 (the server) is reachable through wg0 because it matches the 10.213.213.0/24 route. In other words, it works pretty much like a normal /24 subnet.

However, when you adapted the tutorial to your configuration, you only kept the /32 address assignment but did not keep the /24 route for the remaining WireGuard range. As a result, whenever your client tries to ping 10.10.10.1 (the server), the only matching route it has (in main table) is "default via 71.71.71.1 dev wan0" – not leading anywhere useful.

Both your server and your client should have:

[Network]
Address = 10.10.10.2/32
[Route]# It is normally pointless to specify a gateway for one's own subnet, and it's also
# pointless to specify a gateway when routing through a "layer-3 tunnel" interface
# such as tun0 or wg0.#Gateway = 10.10.10.1Destination = 10.10.10.0/24#GatewayOnlink = true

or alternatively:

[Network]
Address = 10.10.10.2/24

After configuring everything, ip route get 10.10.10.2 on the server should be choosing wg0 as the nexthop interface, and likewise on the client.


You shouldn't have specified the 44.44.44.0/27 network there – it's a separate thing from the the WireGuard subnet. Because you want to route it through the client, it only needs a custom route on your server (in addition to the above):

[Route]# You can specify the client as gateway, technically, but it'll mean nothing
# because wg0 is a "layer-3" interface and the gateway field only influences
# layer-2 addressing. Instead, WireGuard uses the "AllowedIPs" parameter to
# choose which peer to send the packets to.
#Gateway = 10.10.10.2Destination = 44.44.44.0/27

On the client, 44.44.44.0/27 should be routed through your VM bridge interface, not through WireGuard.

On the server, depending on how your datacenter's gateway is configured, the 44.44.44.0/27 prefix might be either routed through one of your server's other IP addresses (in which case everything is fine), or it might be configured as an "on-link" prefix (in which case you'll need to set up Proxy-ARP on the server).


  • ip route get 10.10.10.2
  • ip route show match 10.10.10.2
  • echo "module wireguard +p" > /sys/kernel/debug/dynamic_debug/control
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like