Since I run a server for hosting my websites and providing mail, I decided to setup tunnel service as well. Just in case I get stuck in an airport with limited internet access. Initially, I chose ICMP as the tunneling protocol, but more will follow later.
Server Setup
The server is used as the tunnel endpoint, and must always be running the tunnel service, as you never know when you will need it. To accomplish this, I installed hans and configured it using systemd.
First install by compiling from source or, if running Arch Linux, using the PKGBUILD. Then install the following systemd-service to /etc/systemd/system/hans.service
:
[Unit]
Description=ICMP Tunneling Daemon
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=/etc/conf.d/hans
Restart=on-abort
ExecStart=/usr/bin/hans -s $HANS_IP -d $HANS_DEV -p $HANS_PASS
ExecStartPost=/usr/bin/ip link set dev $HANS_DEV mtu 1200
ExecStartPost=/usr/bin/sysctl -w net.ipv4.ip_forward=1
ExecStartPost=/usr/bin/iptables -t nat -A POSTROUTING -o $HANS_WAN -j MASQUERADE
ExecStartPost=/usr/bin/iptables -A FORWARD -i $HANS_DEV -j ACCEPT
ExecStopPost=/usr/bin/iptables -D FORWARD -i $HANS_DEV -j ACCEPT
ExecStopPost=/usr/bin/iptables -t nat -D POSTROUTING -o $HANS_WAN -j MASQUERADE
[Install]
WantedBy=multi-user.target
The service file sets up hans
and configures NAT-routing on virtual interface created by hans
. It expects a config file in /etc/conf.d/hans
:
HANS_IP=10.0.0.1
HANS_DEV=tun1
HANS_PASS=<password>
HANS_WAN=eth0
Now change the password in /etc/conf.d/hans
and test the service with systemctl:
# systemctl start hans
If systemd doesn't complain, you can enable the service at boot time:
# systemctl enable hans
The server is now ready to accept tunnel-connections from the outside.
Client Setup
Since we use ICMP tunneling only occasionally, we don't need hans
to run as a service on our clients. Instead I cooked a little bash script to start hans
and configure the network to use the tunnel as default internet connection:
#!/bin/bash
host=<hostname>
ip=$(host -t A $host | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
gw=$(ip route | grep default | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
wan=$(ip route | grep default | grep -E -o "dev [a-z]+[0-9]+")
pass=<password>
hans_gw=10.0.0.1
hans_dev=tun1
if [ $UID -ne 0 ]; then
echo Must be root
exit 1
fi
echo starting icmp tunnel
hans -c $host -p $pass -d $hans_dev || exit 1
echo decreasing mtu
ip link set dev $hans_dev mtu 1200 || exit 1
echo waiting for hans to connect
while sleep 1; do
if ip addr show dev $hans_dev | grep -q inet; then
break
fi
done
echo adding route to icmp server
if ip route | grep -q $ip; then
ip route del $ip || exit 1
fi
ip route add $ip via $gw $wan || exit 1
echo changing default route to icmp tunnel
if ip route | grep -q default; then
ip route del default via $gw $wan || exit 1
fi
ip route add default via $hans_gw dev $hans_dev || exit 1
echo "Done"
echo ""
echo "To revert to primary connection, execute the following:"
echo " # killall hans"
echo " # ip route add default via $gw $wan"
The script starts hans
with the parameters in the top of the script (don't forget to change the hostname and password), and then configures a route to run the tunnel on, and finally sets the default route to use the tunnel for everything else.
Happy tunneling!