Public IP via VPN

Hello,

I have a VPS server with 2 public IP addresses and I would like one of them to point to my NAS in home, which is connected directly to the router. I have VPN configured on both VPS server and router already and it seems to work properly, i.e. I can connect from VPS to NAS using private IP address, ping works as well both directions.

The connection looks as follows: VPS -> router -> NAS
Now I have executed following commands on VPS:

iptables -A FORWARD -i eth0 -o tun0 -d 192.168.1.100 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -d SECONDARY_PUBLIC_IP -j DNAT --to-destination 192.168.1.100 -i eth0
iptables -t nat -A POSTROUTING -s 192.168.1.100 -j SNAT --to SECONDARY_PUBLIC_IP -o eth0

When I launch tcpdump on VPS (tcpdump -i tun0) I can see:
08:08:20.302382 IP PUBLIC_IP.44358 > 192.168.1.100.ssh: Flags [S], seq 3107117489, win 64240, options [mss 1460,sackOK,TS val 328826691 ecr 0,nop,wscale 7], length 0

But I don't see any incoming traffic in tcpdump on my router. Why? What do I do wrong?

192.168.1.100 is IP of my NAS, router has 192.168.1.1 assigned. Could you help me guys?

1 Like

How is the routing looking on the VPS?
Which VPN are you using and how is the config?
Does the VPN allow the public IP range?

I use wireguard. Here is it's config:

[Interface]
Address = 192.168.2.1/32
ListenPort = 443
MTU = 1360
PrivateKey = ###

[Peer]
AllowedIPs = 192.168.1.0/24
PresharedKey = ###
PublicKey = ###

And configuration on my router:

config wireguard_tun0
        option allowed_ips              '192.168.0.0/16'
        option endpoint_host            'IP'
        option endpoint_port            '443'
        option persistent_keepalive     '25'
        option preshared_key            '###'
        option public_key               '###'
        option route_allowed_ips        '1'

Routing table on VPS:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default            GW                  0.0.0.0           UG    2      0        0 eth0
GW                 0.0.0.0       255.255.255.0     U      0      0        0 eth0
192.168.1.0    0.0.0.0        255.255.255.0     U     0      0        0 tun0

If you want to receive packets from the internet then allowed_ips should include 0.0.0.0/0.

Another option is to set up a reverse proxy on the vps instead of using DNAT, the vps then makes connections using 192.168.2.1 as source address.

3 Likes

As you don't NAT the incoming public IP's you would need to configure 0.0.0.0/0 as allowed IPs on the VPS side

1 Like

When I set this to 0.0.0.0/0 it sets default route to tun0 interface. This is something I don't want, as I have other devices in my network and the default route should not change for them. Only outgoing traffic from NAS should go through VPN.

When I set 0.0.0.0/0 in Peer config on VPS side, it also sets the default gateway for tun0 and then I loose connection to VPS.

Option 1: Source NAT the Public IP's on the VPS before you put it in the tunnel
Option 2: Add table = off to the wireguard config and then set the route on the NAS individual

I think I don't understand option 1.
How can I set route manually on OpenWrt and tell it depends on specific network interface? I can add table = off parameter, but I cannot add route before enabling the tunnel.

Well you can source nat the Public IP on the VPS to a private IP of the VPS LAN before you put it in the tunnel.

You would just set a route on the NAS to sent all traffic to the VPS. But it would not be the best solution. Either suggest the Option 1 or the Proxy solution that @mikma suggested.

The tunnel end is set on router, not on NAS, so I need some routing table on OpenWrt.

You can set it after the tunnel comes up via script.
See https://openwrt.org/docs/guide-user/network/ip_rules for ideas

1 Like

OK, one more question. Are you sure that the problem is related to AllowedIPs = 192.168.1.0/24 config line on VPS side? According to the documentation - "From the server's point of view, the AllowedIPs are IPs that a peer is allowed to use as source IP addresses." and it seems to affect only a routing table. But routing table has specified how to reach 192.168.1.0/24. Why DNAT simply does not work with that setup?

I might have wrote that misleading. But @mikma wrote it more clear that it is the router config side that need change.
But as you figured out you would need to avoid the automatic route creation on your router.

DNAT works as your Destination IP is changed, but the Tunnel just reject your package as it is not coming from an allowed IP

OK, this seems to really work this way. I just cannot find how to set the postup and predown scripts in /etc/config/network ... OpenWrt wiki is not describing wireguard well I think.

I browsed the /lib/netifd/proto/wireguard.sh and seems it does not support such scripts :frowning:

I think it can be solved without postup/predown scripts.

Is it possible to add a second IP address to the NAS? If you have a separate IP address that's only used with the WireGuard tunnel it will be easy to write the ip rule that's required (use "from ").

I think the destination IP (NAS) is not a problem, but the source public IP addresses that are forwarded by VPS to my LAN. And since I hae to specify 0.0.0.0/0 to make this working, I also have to disable automatic route creation. This means, that I miss the route.

Normally I could use postup and predown scripts to solve that, but they seems are not supported by OpenWrt. So I am actually thinking about netif script in /etc/hotplug.d that will add/remove route for me.

uci set network.@wireguard_tun0[0].route_allowed_ips="1"
uci -q delete network.@wireguard_tun0[0].allowed_ips
uci add_list network.@wireguard_tun0[0].allowed_ips="0.0.0.0/0"
uci set network.lan.ip4table="1"
uci set network.tun0.ip4table="2"
uci -q delete network.lan_vpn
uci set network.lan_vpn="rule"
uci set network.lan_vpn.in="lan"
uci set network.lan_vpn.src="192.168.1.100/32"
uci set network.lan_vpn.lookup="2"
uci set network.lan_vpn.priority="30000"
uci commit network
/etc/init.d/network restart
2 Likes

When I manually add a route by executing ip r a 192.168.0.0/16 dev tun0 then VPN works as expected and when I try to connect via SSH to public IP, I see packets on my router - but I don't see them on my NAS anyway.

When I reconfigure network as @vgaetera suggested, then I have no internet access from my NAS and when I try to to connect via SSH to public IP, I successfully connect to VPS - like the traffic goes from VPS to my router and then goes back to VPS somehow?

Collect the diagnostics from both router and VPS and post it to pastebin.com redacting the private parts:

uci show network; uci show firewall; uci show dhcp; \
wg show; ip address show; ip route show table all; \
ip rule show; iptables-save -c; nft list ruleset
2 Likes