Hi,
TL:DR trying to route port 80 inbound on a VPS, through a WireGuard tunnel to OpenWrt behind my ISPs public IP and then to a container on a VLAN.
I'm going round the bend here trying to figure this out, hopefully someone can put me out of my misery
I have recently provisioned a VPS and have set up a WireGuard tunnel between the VPS and OpenWrt at home (a static ISP IP).
The VPS has 10.10.10.1 for its wg0 interface and is the listening port, and OpenWrt has a tunnel with IP 10.10.10.10 on its IONOS WireGuard interface
I also have a WireGuard tunnel to ProtonVPN with a static route using a table for one of my VLANs; this is working fine.
I also have a site-to-site WireGuard tunnel for another building which isn't currently working (the other end is also OpenWrt using a USB 4G connection and has worked in the past; I just haven't bothered to troubleshoot it as it's not that important)
What I'm trying to achieve is, to forward inbound port 80 on the VPS, through the tunnel to a container on one of the VLANs behind OpenWrt. The container is called mail and its internal IP is 192.168.22.25 in a zone called DMZ. Therefore the full route would be
VPS_PUBLIC_IP@ens6 <> 10.10.10.1@wg0 <> 10.10.10.10@IONOS <> 192.168.22.25@eno1.22
I have a Port Forward from the IONOS zone on OpenWrt for port 80 on 192.168.22.25 in the DMZ zone.
nftables.conf looks as follows on the VPS
flush ruleset
define DEV_WORLD = ens6
define DEV_PRIVATE = wg0
define NET_PRIVATE = { 10.10.10.0/24 }
table ip global {
chain inbound_world {
# accept SSH connections to this VPS only from ISP
ip saddr *ISP_PUBLIC_IP* tcp dport ssh accept
# accept inbound WireGuard connections to this VPS
udp dport 51820 accept
}
chain inbound_private {
# accept rate-limited ping from LAN for testing
icmp type echo-request limit rate 5/second accept
}
chain inbound {
type filter hook input priority 0; policy drop;
ct state vmap { established : accept, related : accept, invalid : drop }
iifname vmap { lo : accept, $DEV_WORLD : jump inbound_world, $DEV_PRIVATE : jump inbound_private }
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state vmap { established : accept, related : accept, invalid : drop }
iifname $DEV_PRIVATE accept;
# forward from this VPS to WireGuard tunnel
iifname $DEV_WORLD oifname $DEV_PRIVATE accept
}
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
# outbonud NAT connections to this VPS on port 80, to port 80 on the WireGuard peer (OpenWrt)
iifname $DEV_WORLD tcp dport 80 dnat 10.10.10.10:80
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
# masquerade returning connections from the WireGuard perr (OpenWrt) to this VPS' public interface
ip saddr $NET_PRIVATE oifname $DEV_WORLD masquerade
}
}
Currently, I can curl http://10.10.10.10 from the VPS and nginx responds from 192.168.22.25
What I can't get to work is curl http://VPS_PUBLIC_IP and have 192.168.22.25 respond.
I did get it to work at one point, and I think it was by adding 0.0.0.0/0 to AllowedIPs on the OpenWrt peer, but this changed the default route for everything which is definitely not what I want (all home traffic going to the VPS, which didn't work anyway for obvious reasons!).
The VPS has AllowedIPs = 10.10.10.10/32, 192.168.22.25/32
OpenWrt has AllowedIPs = 10.10.10.1/32
AllowedIPs hurts my head. I just saw it described as Inbound is like an ACL and Outbound is a routing table.
I really don't want to use PBR for this. I have tried several times to get on with PBR and it doesn't gel for me. It's also another level of abstraction, whereas I'd like to understand how to do this myself. I have my reasons for forwarding port 80; primarily it's for testing so I can get an understanding and working configuration for both nftables and routes in OpenWrt before opening other services.
Help me understand, please
BTW, OpenWrt is 24.10 and the VPS is Debian 12 if that's relevant.
Also, on the VPS:
sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1