Example: redirecting the default gateway to a host on the VPN
It is possible to have one node forward all of its network
traffic to a host on the VPN, effectively using this VPN host as
the default gateway. In OpenVPN, there is the
--redirect-gateway
option that does this for a client.
With tinc, there is no such option, but the behaviour can be
replicated with a host-up and host-down script. First there is an
explaination of the theory behind redirecting the default gateway,
then example scripts will follow.
Theory
Normally, there are two entries in the routing table. One is the
route for the local network, which tells the kernel which IP
addresses are directly reachable. The second is the “default
gateway”, which tells the kernel that in order to reach the rest of
the Internet, traffic should be sent to the gateway of the local
network. Usually the gateway is a router or firewall device, and
its IPv4 address usually ends in .1
. An example output
of route -n
on Linux:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
Here, the LAN has the IPv4 address range 192.168.1.0/24, and the gateway is 192.168.1.1. Suppose we have a VPN with address range 172.16.0.0/16, on which a server exists with address 172.16.1.1. If we have a VPN connection, and the client wants to replace the standard default route with a default route pointing to 172.16.1.1, then there is a problem: the kernel does not know anymore how to send the encapsulated VPN packets to the server anymore. So we need to add an exception for traffic to the real IP address of the VPN server. Suppose its real address is 192.0.32.10, then the routing table should become:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 vpn
192.0.32.10 192.168.1.1 255.255.255.255 UGH 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 172.16.1.1 0.0.0.0 UG 0 0 0 vpn
This will ensure the local LAN is reachable, that the VPN server’s real IP address is reachable via the original gateway, that the VPN server’s VPN IP address is reachable on the vpn interface, and that all other traffic goes via the server on the VPN.
It is better not to remove the original default gateway route,
since someone might kill the tincd
process, such that
it doesn’t get a chance to restore the original. Instead, we use a
trick where we add two /1 routes instead of one /0 route:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 vpn
192.0.32.10 192.168.1.1 255.255.255.255 UGH 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
128.0.0.0 172.16.1.1 128.0.0.0 UG 0 0 0 vpn
0.0.0.0 172.16.1.1 128.0.0.0 UG 0 0 0 vpn
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
Since both /1 cover all possible addresses, the real default route will never be used while the two /1 routes are present.
Scripts
Lets assume we have two nodes called client
and
server
, and the netname is myvpn
. Also,
we assume the server has been properly configured to perform
routing or masquerading between the VPN and the Internet for the
clients that will use it as their default gateway. Then, only two
scripts are necessary on the client. The following scripts are
Linux specific:
/etc/tinc/myvpn/hosts/server-up
:
#!/bin/sh
VPN_GATEWAY=172.16.1.1
ORIGINAL_GATEWAY=`ip route show | grep ^default | cut -d ' ' -f 2-5`
ip route add $REMOTEADDRESS $ORIGINAL_GATEWAY
ip route add $VPN_GATEWAY dev $INTERFACE
ip route add 0.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE
ip route add 128.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE
/etc/tinc/myvpn/hosts/server-down
:
#!/bin/sh
ORIGINAL_GATEWAY=`ip route show | grep ^default | cut -d ' ' -f 2-5`
ip route del $REMOTEADDRESS $ORIGINAL_GATEWAY
ip route del $VPN_GATEWAY dev $INTERFACE
ip route del 0.0.0.0/1 dev $INTERFACE
ip route del 128.0.0.0/1 dev $INTERFACE
These script use the iproute2 commands, because they are easier
to work with. The VPN_GATEWAY
variable has to be
filled in by hand. The ORIGINAL_GATEWAY
variable
copies the relevant information from the original default route to
create the exception route to the VPN server.
Further configuration
One must also ensure the tinc daemons know which node to send
all packets to. Make sure the following line is in
/etc/tinc/myvpn/hosts/server
:
Subnet = 0.0.0.0/0
Make sure you have masquerading or another form of routing set up on the server. Do not forget to allow forwarding of packets; check your firewall settings, and make sure forwarding is enabled in the kernel:
echo 1 >/proc/sys/net/ipv4/ip_forward
You can also set up portforwarding or proxies to be able to connect to services running on the clients from the rest of the Internet.
Router versus switch mode
The examples given above will work with both router and switch mode. However, in router mode, there is actually no such thing as a gateway route. In that mode, the following four lines in the tinc-up script:
VPN_GATEWAY=...
ip route add $VPN_GATEWAY dev $INTERFACE
ip route add 0.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE
ip route add 128.0.0.0/1 via $VPN_GATEWAY dev $INTERFACE
Can be replaced with the following two lines without any problem:
ip route add 0.0.0.0/1 dev $INTERFACE
ip route add 128.0.0.0/1 dev $INTERFACE