Linux – GRE (IP protocol 47) NAT rules seem to expire

iptableslinuxnat;

I have a machine that is connected to another host over a permanent GRE tunnel. I have put the machine behind a Linux firewall (Smoothwall), and NAT-ed all GRE packets to the machine, using the rules:

/sbin/iptables -t nat -A PREROUTING -p 47 --src $tunnel_server_ip -j DNAT --to-destination $false_ip
/sbin/iptables -t nat -A POSTROUTING -p 47 --src $false_ip -j SNAT --to-source $real_ip    
/sbin/iptables -t nat -A INPUT -p 47 -j ACCEPT

(see NAT GRE (IP protocol 47) over Linux router)

It all works fine, but after a period of inactivity on the tunnel, of approximately 15 minutes, I cannot connect from the internet to the machine over the tunnel. After I send any packet from the machine to the internet, ping, open a web page in a browser, the tunnel gets activated again. As a workaround I now use a cron script that starts curl to a page in the internet.

Please help me understand what causes the tunnel to stop functioning, and tell me what can I do to replace the curl hack.

Best Answer

You may be having problems with conntrack timeouts. I don't know if it is the case, it seems that your rules would suffice without using conntrack, but anyways, you may want to keep some traffic in the tunnel to keep it open. You don't need to load a web page using curl, a simple ping should suffice.

If you want to try with bigger conntrack timeout, try this:

sysctl net.netfilter.nf_conntrack_generic_timeout=7200
sysctl net.ipv4.netfilter.ip_conntrack_generic_timeout=7200

Other general notes:

  • It is generally good practice to add a -i <eth> argument to the PREROUTING rule, and a -o <eth> argument to the POSTROUTING rule. Avoids the rules to misfire and reduces the load to the firewall.
  • The INPUT chain rule is useless. Also, it makes little sense to use ACCEPT target in the nat table. Perhaps what you are looking for is a similar rule in the FORWARD chain of the filter (default) table.