Total Pageviews

Sunday, 26 June 2016

ICMPTX (IP-over-ICMP tunnel)

See the current ICMPTX project home page.


You're sitting in an airport or in a cafe, and people want your money for Internet access. They do allow ICMP traffic, though (i.e., you can ping machines on the Internet). Enters ICMPTX. (If you can't use ping, but you can issue name queries, use NSTX: IP-over-DNS.) There are several resources online to point you in the right direction, most notably Case of a wireless hack by Siim Põder. There is a similar, thoroughly undocument program called itun, a simple icmp tunnel that claims to do the same thing. Also, check out PingTunnel which is not IP-over-ICMP, but rather TCP-over-ICMP and, therefore, less useful.
Once you've followed these instructions, you basically have a remote proxy, providing you with access to the Internet. Communication between you and the remote proxy is over ICMP.
Note that these instructions play nicely with NSTX. You can run both on one proxy.


icmptx, ip-over-icmp, firewall piercing, ping, icmp, tunnel, ifconfig, route, tun/tap, tun0.

Solution: icmptx

The tarball below is based on slightly buggy code I found through Siim Põder's page. I modified it ever so slightly, but I deserve no credit at all. Also, if you destroy everything or anything using this program, I am not responsible.
You'll need two copies of icmptx-0.01.tar.gz; one copy for the server, one copy for the client.
Download and compile. For example:
$ wget -O - | tar xvfz -
$ cd icmptx-0.01/
$ make

Proxy-side icmptx setup

You'll need a machine connected to the Internet to serve as your proxy. Make sure the proxy's firewall does not block ICMP traffic. If you can't simply ping the machine, icmptx will surely not work. Also, make sure your kernel supports TUN devices.
After compilation, run the icmptx server as root (assuming the proxy's end of the tunnel is going to be
# ./icmptx -d
Now verify you have a tun device:
# /sbin/ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

Configure the tun device. Also, ensure the kernel doesn't intercept and reply to pings.
# /sbin/ifconfig tun0 mtu 65536 up netmask 
# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
You need to enable forwarding on this server. I use iptables to implement masquerading. There are many HOWTOs about this (a simple one, for example). On Debian, the configuration file for iptables is in /var/lib/iptables/active. The relevant bit is:

Restart iptables:
/etc/init.d/iptables restart
and enable forwarding:
echo 1 > /proc/sys/net/ipv4/ip_forward
You can make sure this change (and the modification that disabled echo replies) are permanent by editing /etc/sysctl.conf, and adding:

Client-side icmptx setup

The client's kernel also needs to support TUN devices. Assuming your proxy's IP address is, run as root:
# ./icmptx -c
Now setup the tun device:
# /sbin/ifconfig tun0 mtu 65536 up netmask
By running /sbin/route -n, figure out what your gateway is. It's the record with the "UG" Flags field. For example:
# /sbin/route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface   U     0      0        0 wlan0         UG    0      0        0 wlan0
OK. So "" is our gateway. Assuming your wireless network device is called "wlan0" (but it might well be "eth1", or whatever), run:
# /sbin/route del default
# /sbin/route add -host gw dev wlan0
# /sbin/route add default gw tun0
Obviously, should be replaced with your proxy's IP address.
If all is well, you should have Internet connection now. All traffic will be tunnelled through your proxy, via ICMP.

Problem: some connections seem to hang

Try increasing the MTU size (that is the number that comes after "mtu" when invoking /sbin/ifconfig). Do this on both the client and the server. Running it with an MTU of 65536 seems to work fine (since, if I recall correctly, that is the maximum IP packet size). If you want to be dead sure that this is not the problem, crank it up.
This problem will only occur if you are behind a firewall that blocks echo reply packets (see TODO, below). More precisely, some firewalls will only allow a single echo reply for a single echo request. If the payload that needs to be stuffed into the ICMP packet is larger than the maximum size of an ICMP packet, you're out of luck. ssh will probably work, fetching small web pages might still work, but your only hope is increasing the MTU.
Bernd Michael Helm wrote in an email to me:
I managed to get around the *hanging connection* problem and speed up icmptx very much: just open a new console and start ping -f (gateway node) so the client will flood the gateway with icmp requests (which will not be answered).With this I was able to get stable connections and improve the http download speed to 210 kb/s which is the full physical bandwith of my internet connection.

Open problems

Note that I do not maintain the code. Please see the current ICMPTX project home page.
As of 2006, three things still needed to happen.
First, icmptx needs to be packaged (preferably for Debian), similar to the Debian nstx package.
Secondly, icmptx needs to deal with small MTUs. Right now you're in trouble if an IP packet is larger than the tun device's MTU. Setting the MTU to 65536 works fine for me, but we need to deal with the situation where that does not work (if intermediate routers refuse large ICMP packets, for example). To compound the problem, a lot of NATs seem to allow only one ICMP echo reply packet per ICMP echo request packet.
An idea that arose in a conversation with Bryan Ford is for the proxy to not only wrap the IP packet in the ICMP packet, but to include an additional header that contains the number of additional ICMP packets required to complete the current IP packet; call this number N. If the IP packet is small enough to fit in one ICMP packet, this number will be zero. If, however, the number is greater than zero, the client responds by sending N ICMP echo requests to the proxy. The proxy uses the N ICMP reply packets to transmit the remaining fragments of the IP packet. This solves both the MTU problem and avoids an intermediate NAT blocking multiple ICMP echo reply packets for one ICMP echo request packet.
Finally, I think the client needs to probe the proxy (similar to NSTX) for pending packets. Currently, only the client can initiate connections. The implementation of this may overlap with the previous point. (Note that John Plaxco seems to have resolved this problem, see the ICMPTX project home page.)


This is the ICMPTX program.

This software is most recently available from

ICMPTX is a program that allows a user with root privledges to create a
virtual network link between two computers, encapsulating data inside of
ICMP packets.

-- license --

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this ICMPTX.  If not, see <>.

-- basic usage instructions --

First, make sure you have the tun module from your 2.6 kernel loaded up
or compiled into your kernel on both ends of your tunnel.

Second, compile the code on both the client machine and the server you
wish to tunnel your traffic between.

Third, on the server side, do something like

./icmpx -s &
sleep 1
ifconfig tun0 netmask

Fourth, on the client side, do something like

./icmptx -c &
sleep 1
ifconfig tun0 netmask

Replace with your internet-accessible IP on the server. At this
point you should have a simple link between the client and server. On
the client, you should be able to ping and get a response. Note
that there are several levels of irony involved in receiving the responses.
SSH tunneling can be used at this point for secure communication over the
channel. Note that there is no encryption capability provided directly by

Once you've confirmed that the tunnel does in fact work, routing should be
easily accomplished. The tun interfaces are just like any other ethernet
devices on your system and can be used as such, for example:

route add -net gw

executed on the client could add a route to your server's DMZ segment.
Access to systems on the subnet from the client would
then be transparently tunneled through the ICMPTX connection.

-- who's to blame for all this? --

ICMPTX has an interesting lineage. The code for the ICMP handling was
originally included from the itunnel program. Tun interface handling
was included from the VTun project, originally authored by Maxim
Krasnyansky. The two were brought together by edi / teso. From there,
Siim Põder cleaned up the code and wrote a short article about it,
possibly still available at .
That seems to be where Thomer Gil found it, after which he further cleaned
it up and presented it at, which is where I,
John Plaxco, came across it.