Linux NAT IPIP Tunnel
Oct 22, 2017

An IPIP tunnel is similar to a GRE tunnel but with slightly less overhead.

$PUBLIC_IP - your local public IP address (https://ipv4.icanhazip.com) $LAN_IP - your machines local LAN IP (ip a) $REMOTE_IP - IP address of the remote Linux server you are tunneling to

Local

auto ipip1
iface ipip1 inet tunnel
	address 192.168.0.2
	netmask 255.255.255.252
	mtu 1480
	mode ipip
	endpoint $REMOTE_IP
	ttl 255
	post-up ip rule add from 192.168.0.0/30 table IPIP && ip route add default via 192.168.0.1 table IPIP

Run this once:

echo '500 IPIP' >> /etc/iproute2/rt_tables
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ipip+ -j TCPMSS --clamp-mss-to-pmtu

Remote

auto ipip1
iface ipip1 inet tunnel
	address 192.168.0.1
	netmask 255.255.255.252
	mtu 1480
	endpoint $PUBLIC_IP
	ttl 255
iptables -A INPUT -p ipip -s $PUBLIC_IP -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.0.0/30 ! -o ipip+ -j SNAT --to-source $REMOTE_IP
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ipip+ -j TCPMSS --clamp-mss-to-pmtu
# Port forwarding
iptables -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j DNAT --to 192.168.0.2:443
iptables -A FORWARD -d 192.168.0.2 -p tcp --dport 443 -j ACCEPT

Make sure net.ipv4.ip_forward=1 and net.ipv4.conf.all.proxy_arp=1 are enabled and net.ipv4.conf.all.rp_filter=0 is off.

EdgeMAX

Inbound Interface: Internet facing interface Translations Address: Local LAN IP Protocol: ipip Src Address: Remote server

Ubiquiti EdgeMAX

Keep Alive

The tunnel appears to become unreachable after a certain amount of time when no data is being passed between the ends. Any iptables forward rules will not reach the destination in this case. I could not find any information about setting a keepalive variable in the interfaces file for Debian. So, the easiest thing is to setup a systemd service with a ping interval of 5 seconds.

/etc/systemd/system/tunnel-keepalive.service

[Unit]
Description=Tunnel Keepalive
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/bin/ping -q -i 5 192.168.0.1

[Install]
WantedBy=multi-user.target
Comments