Getting VOIP Plus IP Forwarding to Work on the Speedtouch

With my subscription to XS4ALL, I received a Thomson Speedtouch 716 ADSL/Wifi router, currently running software release 6.1.9.6. Behind that router, I have a Linux server which serves as the webserver for the blog you’re reading right now, as well as my mailserver and a few other things. The Linux server also acts as a firewall for the rest of my network:

As you can see, the ADSL router and anything connected to it through the WiFi is considered untrusted: the real access point to my internal network is the Linux machine.

Among other things, the Speedtouch has the ability to support Voice-Over-IP by attaching an analog phone. Unfortunately, this functionality does not work in combination with the “assign public IP to a machine on the local network” setting. Which is a pity, because behind the router is my Linux server, running a web- and mailserver among other things, and I really want that server to have my public IP address. Partly because having the server NATted could cause problems with mail, in particular, in the sense that when I send out mail to another server, some suspicious spamblocker software may take offense if the address reported in the headers of my outgoing mail does not match my actual IP. But mostly because having a web/mail/FTP/whatever server hidden behind a NAT, just feels wrong.

So, I have two conflicting desires here: I want to use VOIP over a phone connected to the Speedtouch, and I want my server to believe that it is listening directly on my public IP. A little googling confirms that a lot of other people have this same problem, but if anybody has found a solution already, I didn’t see it.

There does exist a way to expose the server to the outside world without breaking VOIP: use the “game and application sharing” feature to forward all TCP and UDP ports except port 5060 (which is the SIP port used by the VOIP service) to the server. But then we are using NAT again, which is not what we want. What I want is: port 5060 is handled by the Speedtouch, all other packets are sent straight to my Linux server, which should receive them on the public IP address of my Internet account. Unfortunately, it seems that there isn’t any way to configure the Speedtouch like that.

How I eventually solved this problem is by adding an iptables rule on my server, which uses DNAT to translate the source address of each packet back into my public IP before the server sees it.

Like this:

  • A packet comes in from the outside world on my public IP address (82.95.250.5).
  • The router sees it, and if the packet is not aimed at the VOIP port (5060), sends it on to my server, which has a local IP of 10.0.0.1 (assigned to it by the router through DHCP).
  • An iptables rule on my server intercepts the packet and changes the source address back to 82.95.250.5. This way, all services running on my server can pretend that they are connected directly to the Net, without any special configuration needed.
  • As my server sends a response to the packet, the destination address is changed back to the router’s address (10.0.0.138).
  • The router performs a second layer of NAT, translating the destination address of the response packet back into 82.95.250.5 again, before sending it along to its final destination.

So every packet exchanged between my server and the rest of the world, is NATted twice: once by the router, once by the server. Not a particularly elegant solution, but it will have to do until somebody comes along with a better way to bend the Speedtouch to his will (or until I buy a better ADSL router).

Here’s the magic iptables statement:

iptables -A PREROUTING -t nat -i $EXTERNAL -d $FAKEPUBLICIP -j DNAT --to-destination $PUBLICIP

In my case, $EXTERNAL would be eth1 and $FAKEPUBLICIP is 10.0.0.1.

But maybe somebody has already found a nice, clean way to configure the Thomson router to do what I want, and I just missed it. Any ideas would be appreciated.

As I said, it’s not a particularly elegant solution. One annoying consequence is the fact that if you try to browse to mwolf.net from the WiFi network, you’ll get an error because the router will get confused about where to send packets for 82.95.250.5. This could be solved with a bit of DNS magic.