Search code examples
ubuntunetwork-programmingvpniptablesforwarding

How to forward incoming requests to IP through VPN


I am working on a project that requires connecting to our clients' networks through VPN (we are sending HTTP requests and connecting to databases on their local servers).

What I'm trying to achieve is this:

I have a set of instances on AWS but I don't want to set up VPN connections on each and every one of them, in fact I'd prefer not to change them at all if possible. (Let's call these app instances.)

So what I thought I would do is set up other instances with VPN connections per client. (Let's call these vpn instances.)

The idea is that the app instances would have the DNS of a vpn instance (e.g.: myclient.vpn.myservice) and use that for all traffic through the VPN.

Example: app instance #1 sends an HTTP request to http://myclient.vpn.myservice:1234, the vpn instance receives the request, forwards it to 1.2.3.4:1234 (on the client's local network) and returns the response to app instance #1, so from the app instance's point of view it's like sending a regular HTTP request to myclient.vpn.myservice (side-note: this should also work with regular tcp and udp connections as well).

What I've tried is enabling ip forwarding and setting iptables rules on the vpn instance like so:

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 1.2.3.4:1234
iptables -t nat -A PREROUTING -p udp --dport 1234 -j DNAT --to-destination 1.2.3.4:1234
iptables -t nat -A POSTROUTING -j MASQUERADE

but that does not seem to work (at least with HTTP requests).

All servers are running on Ubuntu 20.04.

I'm not sure whether the idea is all wrong or not and I don't have particularly huge experience with Ubuntu so I'm open to suggestions, the only thing that's important is that I really don't want to change the app instances.


Solution

  • Okay, so I figured it out. First of all the steps that I wrote above were working just not from the vpn instances themselves, from the app instances it did work, but these iptables rules were too permissive, they messed up the system's internal host resolution and the sudo command became very slow after applying them.

    So here's what I ended up with (staying with the example in the question):

    On the vpn instances:

    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1234 -j DNAT --to-destination 1.2.3.4:1234
    iptables -t nat -A PREROUTING -i eth0 -p udp --dport 1234 -j DNAT --to-destination 1.2.3.4:1234
    iptables -t nat -A OUTPUT -o lo -p tcp --dport 1234 -j DNAT --to-destination 1.2.3.4:1234
    iptables -t nat -A OUTPUT -o lo -p udp --dport 1234 -j DNAT --to-destination 1.2.3.4:1234
    iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
    

    where eth0 is the instance's public network interface and tun0 is the network interface attached by the vpn.

    After these rules I am able to curl http://myclient.vpn.myservice:1234 from the all instances and receive the response from the other side of the vpn.