This is the alpha version of my IP tunneling driver. Protocol Tunneling: A network tunneling driver encapsulates packets of one protocol type within packets of another protocol type. It sends them out over the network to a relay (or destination) where the packet is unwrapped and is forwarded to its ultimate destination. Packet tunneling is useful in situations where you want to route packets of a non-standard protocol type over the common network. A good example of this is 'IPX encapsulation', in which IPX packets from a DOS network are routed across an IP network by encapsulating them in IP packets. There are two parts to every protocol tunnel. There is the encapsulator, and the decapsulator. The encapsulator wraps the packets in the host protocol and sends them on their way, while the decapsulator takes wrapped packets at the other end and unwraps them and forwards them (or whatever else should be done with them.) IP tunneling is a specific case of protocol tunneling, in which the encapsulating protocol is IP, and the encapsulated protocol may be any other protocol, including Apple-Talk, IPX, or even IP within IP. For more information on the semantics and specifications of IP encapsulation, see RFC-1241, also included in this package. My Implementation: My implementation of IP tunneling for Linux consists of two loadable module drivers, one an encapsulator (tunnel.o) and the other a decapsulator (ipip.o). Both are used for setting up a working IP-in-IP tunnel. Currently, the drivers only support IP encapsulated in IP. The tunnel driver is implemented as a network device, based on the Linux loopback driver written (in part) by Ross Biro, Fred N. van Kempen, and Donald Becker. After the driver is loaded, it can be set up as any other network interface, using ifconfig. The tunnel device is given its own IP address, which can match that of the machine, and also is given a pointopoint address. This pointopoint address is the address of the machine providing the decapsulating endpoint for the IP tunnel. After the device is configured for use, the 'route' command can be used to route traffic through the IP tunnel. There must be a route to the decapsulating endpoint that does not go through the tunnel device, otherwise a looping tunnel is created, preventing the network traffic from leaving the local endpoint. The decapsulating endpoint must have loaded the ipip.o decapsulator module for it to understand IP-in-IP encapsulation. This module takes any IP-in-IP packet that is destined for the local machine, unwraps it, and sends it on its way, using standard routing rules. The current implementation of IP decapsulation does no checking on the packet, other than making sure wrapper is bound for the local machine. Note that the above setup only provides a one-way pipe. To provide a full two-way IP tunnel, the decapsulation host must set up an IP encapsulation driver, and the encapsulating host must load the IP decapsulation module, providing full duplex communication through the IP tunnel. An example setup might be as follows. Machine A has an ethernet interface with an IP address of 111.112.101.37, while machine B is on a different network, with an ethernet interface at IP address 111.112.100.86. For some reason, machine A needs to appear on machine B's network. It could do that by setting up an IP tunnel with machine B. First, the commands that would be run on machine A: (Assuming both machines are Linux hosts, running Linux 1.1.x) # insmod ipip.o ; insmod tunnel.o // Here the drivers are loaded. # ifconfig tunl 111.112.100.87 pointopoint 111.112.100.86 # ifconfig tunl netmask 255.255.255.0 // Set a proper netmask. # route add 111.112.100.86 dev eth0 // Set a static route to B. # route add -net 111.112.100.0 dev tunl // Set up other routes. At this point, machine A is ready to route all traffic to the network that machine B resides on. But now, machine B needs to set up its half of the IP tunnel: # insmod ipip.o ; insmod tunnel.o // Here the drivers are loaded. # ifconfig tunl 111.112.100.86 pointopoint 111.112.101.37 # ifconfig tunl netmask 255.255.255.0 // Set a proper netmask. # route add 111.112.100.87 dev eth0 // Set a static route to B. # arp -s 111.112.100.87 EE.EE.EE.EE.EE pub // Act as a proxy arp server. The extra step of "arp -s" is needed so that when machines on network B query to see if 111.112.100.87 (the "ghost" host) exists, machine B will respond, acting as an arp proxy for machine A. In the command line, EE.EE.EE.EE.EE should be replaced with the ethernet hardware address of machine B's ethernet card. Notice that machine B's setup is almost the inverse of machine A's setup. This is because IP tunneling is a peer-to-peer concept. There is no client and no server, there is no state to keep track of. The concept is simple. Every IP packet outbound through the tunnel interface is wrapped and sent to the pointopoint address and every incoming IP-in-IP packet bound for the local machine is unwrapped and re-routed normally. The only difference in the two machines setup shown above is that machine A set its tunnel address to one existing on machine B's network, while B set a route to machine A's tunnel device address through the tunnel. This is because machine A wants to have a new address on network B, and machine B is simply acting as a proxy for machine A. Machine A needs its tunnel address to be on network B so that when packets from machine B are unwrapped, the Linux routing system knows that the address is a local one. Due to a feature of Linux, any packets received locally, bound for another local address, are simply routed through the loopback interface. This means that the tunnel device should never receive packets. Even on machine B, it is the ethernet interface that is receiving wrapped packets, and once they are unwrapped they go back out the ethernet interface. This could cause Linux to generate ICMP redirect messages if this special routing case isn't caught (see /linux/net/inet/ip.c)