Search:  
Gentoo Wiki

HOWTO_DNAT_SNAT_OpenVPN_iproute2:_routing_setup


This article is part of the HOWTO series.
Installation Kernel & Hardware Networks Portage Software System X Server Gaming Non-x86 Emulators Misc

Contents

Introduction

This HOWTO is a reference point for people who need, or want, to squeeze more from their routing setup.

Sometimes you dont know what to do to get what you want, specially when routing and firewalls, NAT and such, are involved. This guide will try to help clarifing what you need.

Even if this is not exactly what you need, you might still find good hints or pointers to get where you want to go. No pun intended with some OS commercials.

Goals

So, if you follow this guide you will be able to transform a private non internet accessible server into a full capable internet server.

The scenario is the following:

PROS:

CONS:

This is the ideal setup:


Requirements

What you need, is the following:

The Idea Behind

Looks complex, and it is, but it works and it works around any network block (firewall, NAT, Proxy, and such)

This is it:

Charming, isnt it? Lets go

Server B setup - spare IP setup

First of all, if you want your Server A to be accessible using IP 1.2.3.5, you need to have IP 1.2.3.5 spare on Network B. So, pick your spare IP and set it to Server B main ethernet card:

Note: For a quick test, just type in
ifconfig eth0:1 1.2.3.5 up

Edit /etc/conf.d/net and add the following:

alias_eth0 = {"1.2.3.5 netmask 1.2.3.0/24"}
/etc/init.d/net.eth0 restart
Note: Since IP 1.2.3.4 is already routed by Network B router, also IP 1.2.3.5 will be routed correctly. This is a feature of the IP routing mechanism

Now check it:

ifconfig eth0:1

Should show you your ned IP

Server B setup - configure OpenVPN end

Please follow the OpenVPN HOWTO and setup a working OpenVPN configuration for your Server B. Refer to the "Server side setup" and for now skip the client side.

We will choose 192.168.100.1 as IP on the OpenVPN server side and 192.168.100.2 as IP on the OpenVPN client side.

Please use the following setup as guideline, specially the persist* settings and the ping setting is required to prevent timeouts.

dev tun
proto tcp-server
ifconfig 192.168.100.1 192.168.100.2
secret /etc/openvpn/myname/public_key.txt
comp-lzo
port 1198
ping 1
ping-restart 60
persist-tun
persist-key

Server B setup - Squid setup

Please refer to the squid howto on how to install and open your Squid (http proxy) so that your Server A can access it. You might want to setup some extra security on this step.

Note: You might want to choose a different port other than the default 3128. Often firewalls and NATs will truncate traffic on port 3128 for security reasons. I usually pick 4128 which works great.

Server B setup - configure iptables (DNAT/SNAT)

Setup the required DNAT and SNAT:

iptables -t nat -A PREROUTING -d 1.2.3.5 -j DNAT --to 192.168.100.2
iptables -t nat -A POSTROUTING -s 192.168.100.2 -j SNAT --to-source 1.2.3.5
Note: DNAT will ensure that packes incoming to 1.2.3.5 will be routed to 192.168.100.2 with destination IP changed, and SNAT will ensure that packets coming out of 192.168.100.2 (which will be our private Server A) will be routed to the sender with source IP changed in 1.2.3.5

also, you will need to enable ip forwarding:

echo "1" >> /proc/sys/net/ipv4/ip_forward

And set it up permanently in your /etc/sysctl.conf by setting 1 to the line:

net.ipv4.ip_forward = 1

All done on the server side!

Server A setup - OpenVPN end

Now go back to the OpenVPN HOWTO and set it up for the client... And do not forget to use any required authentication for the Squid proxy, if you set it up!

Use the following configuration parameters:

remote 1.2.3.4 1198
dev tun
ifconfig 192.168.100.2 192.168.100.1
secret /etc/openvpn/fast/public_key.txt
comp-lzo
proto tcp-client
http-proxy 1.2.3.4 4128
ping 1
persist-tun
persist-key

Specially, note the http-proxy directive and the ping directive, which is needed to prevent timeouts.

When done, start the openvpn and check if it works:

ping 192.168.100.2
ping 192.168.100.1

If not, refer to the OpenVPN howto and fix it before continuing.

Note: Since Server A is not accessible from the internet, we are telling Server A to connect to Server B and not viceversa. Of course for this to work you need to be able to reach the proxy on Server B. You might want to move it to port 80 or 443 (https).

Server A setup - more on OpenVPN

Since sometimes my connection simply stops working, or some other bad things can go wrong on the network, i created the following script to automatically restart OpenVPN if the remote host is not accessible:

Script /usr/bin/openvpn_keepalive

#!/bin/bash
if [ "`/etc/init.d/openvpn status | awk '{ print $3 }'`" == "started" ]
then
 while (true)
 do
  ping -c 1 -q 192.168.100.1 &> /dev/null
  if [ "$?" == "1" ]
  then
     ping -c 1 -q 1.2.3.4 &> /dev/null
     if [ "$?" == "1" ]
      then
       sleep 300
      else
        /etc/init.d/openvpn stop
        /etc/init.d/openvpn start
      fi
   else
     sleep 1
  fi
done
fi

Please tailor it to your configuration (IP addresses) and then start it automatically from your /etc/conf.d/local.start:

/usr/bin/openvpn_keepalive&

You are set! Even if the VPN will get terminated for any reason, or if the network will go down, as soon as the network is up again it will start again.

Note: What have we accomplished so far? We have Server A and Server B directly connected via a (fake) network connection called tun0. Now its like the two servers are directly linked with a cable. Go get this over any kind of entwork setup, we are using an http proxy to bypass firewalls and NAT and similar things.

Server A setup - fix the routing

By now you should be able to access Server A from Server B.

The following command on Server B:

ssh 192.168.100.2

Should give you a shell on Server A.

We want more, we want to do:

ssh 1.2.3.5

from any internet host and access Server A. Do achieve this, we need a way to tell Server A to route any response to packets coming from Server B trough the interface tun0 (the OpenVPN).

Lets have a better look at the problem:

Now, we need to close the loop:

Pretty comples, uh?

But we are almost done, since the SNAT on Server B is already in place we only need to do some routing on Server A.

We need to use iproute2 to achieve this. So emerge it if you dont have it already:

emerge -vp iproute2

Now, create a routing table by adding to the file /etc/iproute2/rt_tables a line like: 100 my_new_table

Then, load a new rule:

ip rule add from 192.168.100.2 table my_new_table

And create the default route for this table/rule:

ip route add default via 192.168.100.1 table my_new_table

What this will do is: any packet coming out of IP 192.168.100.2 will be sent to Server B over the VPN and not trough the default route of the Server A.

Cool, isnt it? And pretty easy too.

Testing your setup...

Now, log in to Host C and try:

ssh 1.2.3.5

you should be able to log in into Server A!

Troubleshooting

So many things can go wrong, its a complex setup.

Some suggestions are:

References

Check link Source Based Routing info

And also link Forum thread on this subject

Contacts

Please feel free to write me at <willy (at) gardiol (dot) org> if you need help!

Retrieved from "http://www.gentoo-wiki.info/HOWTO_DNAT_SNAT_OpenVPN_iproute2:_routing_setup"

Last modified: Thu, 04 Sep 2008 04:11:00 +0000 Hits: 8,246