I have a host that has a permanent static GRE tunnel to a server on the Internet. Right now the host has its own real IP address. I want to put the host behind a Linux box (Smoothwall), and assign it a private IP address.

Lets call:
tunnel-server-ip = the IP of the end of the tunnel the host is connecting to (on the internet)
real-ip = the real IP currently used by the host, that I want to assign to the Linux router
false-ip = the IP the host will get after it is put behind the Linux firewall

This is what I think I have to do for the tunnel to work:

  1. DNAT all incoming IP GRE packets on the external interface coming from the internet tunnel end, and send them to host. That is change the destination from real-ip to false-ip and send the packet to false-ip
  2. SNAT all incoming IP GRE packets coming on the internal interface coming from the host to appear they are generated by the Linux box and send them to the tunnel server. That is change the source field from false-ip to real-ip and send the packet to tunnel-server-ip

I came up with the following script:

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

Running this results in No chain/target/match by that name. Could you please tell me what I did wrong? Am I on the right track?


You forgot the -t nat table switch in the PREROUTING/POSTROUTING instructions. Just add it at the front.

  • I had to leave the city, so I could not test this. But next week I will test what you said and give feedback. Please don't consider I forgot to accept a valid answer. – andi Jul 10 '09 at 7:19
  • What if I have multiple hosts placed behind the linux firewall ? Let's say I want a range of IP as false IPs ? How the rule will change ? – Shyamkkhadka Nov 19 '18 at 8:56

Late answer, but I came across the same need and the two following commands do the trick:

# iptables -t nat -A PREROUTING -i eth0 -p gre -j DNAT --to-destination
# modprobe nf_conntrack_proto_gre

No need for specifying real IP, simply PREROUTE the gre traffic to the private server and let the gre connection tracker do its job.


For most GRE tunnels you have to have a control protocol on TCP 1723. This has to be forwarded also. Here is a Link that describes the iptables configuration for this. You are on the right track, just missing the control protocol.

  • From what I gather, GRE itself has no dependency on communication over TCP 1723. However, PPTP uses a control protocol over TCP 1723 to negotiate setting up a separate GRE tunnel for the data traffic. – Oskar Berggren Jul 12 '13 at 10:00
  • @Oskar, yes you are correct, GRE doesn't require it, but it's a connectionless protocol, so there needs to be some control channel to negotiate keys etc... – Scott Lundberg Jul 12 '13 at 15:23

You appear to have forgotten to say "--table nat", so it's going into the filter table which doesn't have SNAT/DNAT targets, nor does it have PREROUTING and POSTROUTING chains.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.