Score:1

Properly configuring iptables for two layers of port forwarding: external server connected to local server via VPN

ru flag

I had a minecraft server running on a VPS (Debian 10), but the VPS was too puny to handle it so I wanted to use a beefier local server to run it (Ubuntu 22.04). The VPS is hosting an OpenVPN server, and the local server connects as the only client. The VPS is at 10.8.0.1 and the local server is at 10.8.0.6 (192.168.1.185 on the local network).

I used iptables rules to forward tun0 VPN packets at 10.8.0.6:25565 to the local server's IP. This is working fine: I can query the minecraft server from the VPS. I then set up the same set of rules (with relevant IPs swapped of course) on the VPS to forward connections from vps_external_ip:25565 to 10.8.0.6:25565. This rule is forwarding the packets all the way to the local server, but the connection always times out. The weird thing is that neither working connections from VPS -> local server nor external -> VPS -> local server increasing the packet counters of any the POSTROUTING MASQUERADE rules, but they do for the PREROUTING rules. There TCP/UDP connections simply time out when hitting the VPS on eth0:25565, there are no connection refused errors.

IPV4 forwarding is enabled on both machines and I've tried with UFW disabled, no luck there.

I set up a log rule on both server's NAT POSTROUTE, but I'm not really sure how to fix the issue as I could not find any.

POSTROUTE Log Output (iptables -t nat -I POSTROUTING -j LOG --log-prefix "NAT:" --log-level 7)

##### VPS
Apr 23 20:52:02 vpskernel: [1552376.122382] NAT1:IN= OUT=tun0 SRC=<my ip> DST=10.8.0.6 LEN=48 TOS=0x08 PREC=0x20 TTL=114 ID=21284 DF PROTO=TCP SPT=1806 DPT=25565 WINDOW=64240 RES=0x00 SYN URGP=0

#### Local server
<could not find any relevant logs grepping /var/log/kern.log for NAT1 and there were no logs at all for tun0>

I used /etc/ufw/before.rules for each server to set up the iptables rules.
VPS /etc/ufw/before.rules:

# START OPENVPN RULES
# NAT table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
# END OPENVPN RULES

-A PREROUTING -i eth0 -d <vps external IP> -p tcp --dport 25565 -j DNAT --to-destination 10.8.0.6:25565
-A PREROUTING -i eth0 -d <vps external IP> -p udp --dport 25565 -j DNAT --to-destination 10.8.0.6:25565
-A POSTROUTING -s 10.0.0.0/8 ! -d 10.0.0.0/8 -j MASQUERADE
COMMIT

Local server /etc/ufw/before.rules:

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i tun0 -d 10.8.0.6 -p tcp --dport 25565 -j DNAT --to-destination 192.168.1.185:25565
-A PREROUTING -i tun0 -d 10.8.0.6 -p udp --dport 25565 -j DNAT --to-destination 192.168.1.185:25565
# setup routing
-A POSTROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j MASQUERADE
COMMIT

The PREROUTING rules are working, but the POSTROUTING rules counters are not incrementing.

I ran tcpdump on 25565 to debug. I see the packets coming in, but I don't see any return on any interfaces when connecting externally. When directly querying from the VPS, I see the local server respond on tun0. It looks like the issue is the local server is trying to respond directly to my IP on en01 instead of to the VPS on tun0, but I'm not sure how to fix that.

VPS tcpdump:

# eth 0
21:43:39.972647 IP my_ip.2729 > vps_ip.25565: Flags [S], seq 1483515507, win 64240, options [mss 1460,nop,nop,sackOK], length 0
# tun0
21:43:39.972739 IP my_ip.2729 > 10.8.0.6.25565: Flags [S], seq 1483515507, win 64240, options [mss 1460,nop,nop,sackOK], length 0

Local server tcpdump:

#tun0
21:43:39.972566 IP my_ip.2729 > 10.8.0.6.25565: Flags [S], seq 1483515507, win 64240, options [mss 1356,nop,nop,sackOK], length 0

#en01
21:43:39.972618 IP 10.8.0.6.25565 > my_ip.2729: Flags [S.], seq 2141764446, ack 1483515508, win 64240, options [mss 1460,nop,nop,sackOK], length 0

Score:0
ru flag

Finally figured it out. Most of the port forwarding guides online had a POSTROUTING rule that doesn't work for OpenVPN (or for my situation). Instead of allowing local IPs as the source with a destination that was not a local IP, I had to make the postrouting rule for anything but a local IP to get rewritten as a tun0 VPS IP.

VPS /etc/ufw/before.rules (swapped s and d):
-A POSTROUTING -d 10.0.0.0/8 ! -s 10.0.0.0/8 -j MASQUERADE -t nat

Additionally, the POSTROUTING rule was only needed on the VPS.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.