I have a router on Tomato (shibby) running an OpenVPN server (with TAP; interface is tap21 on the router). Various resources (including some workstations) are physically connected to eth0 on this router. I have another physical device across the country which is running nginx and other services. Now, I know this isn't a great topographical setup, but unalterable circumstances require that the device running nginx must be a client of the router VPN and all of this device's inbound traffic and outbound traffic on ports 80 and 443 must be tunnelled through this VPN connection.

So basically, what needs to happen is:

  1. example.com resolves to IP of WAN on the router
  2. router forwards ports 80 and 443 through tap21 interface to nginx server
  3. nginx server response comes back through tap21 and is routed back through WAN

The #2 part is what I'm having trouble with.

The server is currently able to communicate with other devices on the subnet (able to ping other resources on the VPN as well as resources physically connected to eth0 on the router) and can access the internet through the VPN. However, I've been unable to forward ports from WAN to the server's address on the VPN. The first attempt I made was simply trying the port forwarding GUI in Tomato (but this seems not to work for IPs on the VPN, only those on eth0 or wlan0). When that didn't work, I tried adding iptables rules, but as I'm still largely uncomfortable with iptables I've only been able to find snippets from other answers for questions that don't really relate to this weird and problematic networking setup. Here's what I'm trying (using 10000 as a test port with nc listening):

iptables -t nat -I PREROUTING -p tcp -m tcp --dport 10000 -j DNAT --to-destination
iptables -I FORWARD -d -p tcp --dport 10000 -j ACCEPT

However, I can't figure out what's happening to packets being re-routed in this way--they're certainly not reaching the server. Essentially, my question is how can I forward inbound connections on particular ports to a particular device on a VPN? Outbound traffic on ports 80 and 443 from other resources on the router's eth0 must, of course, not be affected.

Thanks for any help you can provide!


After a lot of tinkering, I figured it out (although I welcome any comments that could explain why this is working). Firstly, not having a POSTROUTING rule was, apparently, causing the server to discard the packets. By examining the iptables rules that Tomato creates through the GUI, I created similar entries for WANPREROUTING, wanin, and INPUT; I'm not entirely sure why the INPUT rule is necessary; perhaps it could be removed and the -m flag could be added to wanin?

iptables -t nat -I WANPREROUTING -i vlan2 -p tcp -m tcp --dport 80 -j DNAT --to-destination {SERVER_IP}:80
iptables -I wanin -d {SERVER_IP} -i vlan2 -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp -m tcp -i vlan2 --dport 80 -m state --state NEW -j shlimit

The Tomato GUI does not create POSTROUTING rules automatically, so I had to do that as well:

iptables -t nat -I POSTROUTING -p tcp -d {SERVER_IP} --dport 80 -o tun22 \! -s {GATEWAY_IP} -j SNAT --to-source {GATEWAY_IP}

I did sets of rules like this for ports 80 and 443, and I can now access the server through the VPN from the internet.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.