Routing traffic through tinc
Tinc is a mesh VPN which creates secure connections between nodes allowing them to communicate through each other, it doesn't require a central server which is useful for ad-hoc networks and devices without static IPs.
Recently when travelling I've been using Wireguard to connect to servers in my home country, however this isn't ideal since on Android you can only run one VPN at a time.
So I decided to see if I could route using tinc and then connect via my home connection. Expanding on the tinc documentation here is how to do it:
For simplicities sake I'm going to assume there are just two nodes, in practice the number doesn't matter.
Let's call these nodes home and remote. We will want all traffic from remote to be routed through home.
Home
First on home we need to configure IP forwarding and appropriate firewall rules.
- Enable ip forwarding by adding
net.ipv4.ip_forward=1
to/etc/sysctl.conf
- Run
sysctl --system
to apply this change immediately - Set the Subnet in the hosts/home file to be
Subnet = 0.0.0.0/0
this tells tinc to route all traffic through this node, if you don't do this it'll fail. - Enable forwarding via iptables how you do this will vary depending on how you manage your firewall
for a one off the following will do
iptables -P FORWARD ACCEPT
- Enable iptables masquerading using the following snippet:
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s VPN_CIDR -o NETWORK_INTERFACE -j MASQUERADE
COMMIT
Replacing VPN_CIDR with the VPN range in CIDR format e.g. 172.16.0.0/24 and NETWORK_INTERFACE with the primary network interface e.g eth0
Remote
Next we configure remote.
We need two new files, hosts/home-up
and hosts/home-down
, these need to be executable.
For home-up
add the following:
#!/bin/sh
ORIGINAL_GATEWAY=`ip route show | grep ^default | cut -d ' ' -f 2-5`
REMOTEADDRESS=$(dig +short remote.dns.name)
echo "$REMOTEADDRESS" > /run/.home-ip
chmod 0600 /run/.home-ip
ip route add $REMOTEADDRESS $ORIGINAL_GATEWAY
ip route add 0.0.0.0/1 dev $INTERFACE
ip route add 128.0.0.0/1 dev $INTERFACE
sed -i '1s/^/nameserver REMOTEDNS\n/' /etc/resolv.conf
Replacing remote.dns.name
with the DNS name of home assuming it has one otherwise simply
set REMOTEADDRESS to the IP of home.
Replace REMOTEDNS with the IP of your home DNS server assuming you want to use it (I have a Pi-hole so want to use this while away).
If you don't want to set a custom DNS server remove the last line. This also assumes you're using network manager to set your DNS resolvers (which you may not be, long gone are the days of resolv.conf being the source of all DNS truth).
For home-down
add the following:
#!/bin/sh
ORIGINAL_GATEWAY=`ip route show | grep ^default | cut -d ' ' -f 2-5`
REMOTEADDRESS=$(cat /run/.home-ip)
ip route del $REMOTEADDRESS $ORIGINAL_GATEWAY
ip route del 0.0.0.0/1 dev $INTERFACE
ip route del 128.0.0.0/1 dev $INTERFACE
sed -i '/REMOTEDNS/d' /etc/resolv.conf
Replacing REMOTEDNS as with home-up
And that's it, when remote connects to home either via a peer node or via a ConnectTo statement in tinc.conf it will run home-up and route all traffic through home. When tinc disconnects it will run home-down and traffic will return to normal.
If remote is an Android device and you are using the excellent Tinc App then you need to modify things slightly since it doesn't support up/down scripts due to how Android works.
The changes are the same for home but for remote instead of adding the scripts add the following to network.conf
# IP address of this node
Address = IPOFREMOTE/32
# Traffic to route through the VPN
Route = 0.0.0.0/0
# DNS server(s)
DNSServer = REMOTEDNS
AllowBypass = false
Replacing IPOFREMOTE with the VPN IP address of remote and REMOTEDNS with the REMOTEDNS server or omit this line if you're not using REMOTEDNS.
References: