1 |
1626 |
jcastillo |
|
2 |
|
|
This is the alpha version of my IP tunneling driver.
|
3 |
|
|
|
4 |
|
|
Protocol Tunneling:
|
5 |
|
|
|
6 |
|
|
A network tunneling driver encapsulates packets of one
|
7 |
|
|
protocol type within packets of another protocol type. It sends
|
8 |
|
|
them out over the network to a relay (or destination) where the
|
9 |
|
|
packet is unwrapped and is forwarded to its ultimate destination.
|
10 |
|
|
Packet tunneling is useful in situations where you want to route
|
11 |
|
|
packets of a non-standard protocol type over the common network.
|
12 |
|
|
A good example of this is 'IPX encapsulation', in which IPX packets
|
13 |
|
|
from a DOS network are routed across an IP network by encapsulating
|
14 |
|
|
them in IP packets.
|
15 |
|
|
|
16 |
|
|
There are two parts to every protocol tunnel. There is
|
17 |
|
|
the encapsulator, and the decapsulator. The encapsulator wraps
|
18 |
|
|
the packets in the host protocol and sends them on their way,
|
19 |
|
|
while the decapsulator takes wrapped packets at the other end
|
20 |
|
|
and unwraps them and forwards them (or whatever else should be
|
21 |
|
|
done with them.)
|
22 |
|
|
|
23 |
|
|
IP tunneling is a specific case of protocol tunneling,
|
24 |
|
|
in which the encapsulating protocol is IP, and the encapsulated
|
25 |
|
|
protocol may be any other protocol, including Apple-Talk, IPX,
|
26 |
|
|
or even IP within IP.
|
27 |
|
|
|
28 |
|
|
For more information on the semantics and specifications
|
29 |
|
|
of IP encapsulation, see RFC-1241, also included in this package.
|
30 |
|
|
|
31 |
|
|
|
32 |
|
|
My Implementation:
|
33 |
|
|
|
34 |
|
|
My implementation of IP tunneling for Linux consists
|
35 |
|
|
of two loadable module drivers, one an encapsulator (tunnel.o)
|
36 |
|
|
and the other a decapsulator (ipip.o). Both are used for
|
37 |
|
|
setting up a working IP-in-IP tunnel. Currently, the drivers
|
38 |
|
|
only support IP encapsulated in IP.
|
39 |
|
|
|
40 |
|
|
The tunnel driver is implemented as a network device,
|
41 |
|
|
based on the Linux loopback driver written (in part) by Ross Biro,
|
42 |
|
|
Fred N. van Kempen, and Donald Becker. After the driver is
|
43 |
|
|
loaded, it can be set up as any other network interface, using
|
44 |
|
|
ifconfig. The tunnel device is given its own IP address, which
|
45 |
|
|
can match that of the machine, and also is given a pointopoint
|
46 |
|
|
address. This pointopoint address is the address of the machine
|
47 |
|
|
providing the decapsulating endpoint for the IP tunnel. After
|
48 |
|
|
the device is configured for use, the 'route' command can be used
|
49 |
|
|
to route traffic through the IP tunnel. There must be a route to
|
50 |
|
|
the decapsulating endpoint that does not go through the tunnel
|
51 |
|
|
device, otherwise a looping tunnel is created, preventing the
|
52 |
|
|
network traffic from leaving the local endpoint.
|
53 |
|
|
|
54 |
|
|
The decapsulating endpoint must have loaded the ipip.o
|
55 |
|
|
decapsulator module for it to understand IP-in-IP encapsulation.
|
56 |
|
|
This module takes any IP-in-IP packet that is destined for the local
|
57 |
|
|
machine, unwraps it, and sends it on its way, using standard
|
58 |
|
|
routing rules. The current implementation of IP decapsulation does
|
59 |
|
|
no checking on the packet, other than making sure wrapper is bound
|
60 |
|
|
for the local machine.
|
61 |
|
|
|
62 |
|
|
Note that the above setup only provides a one-way pipe.
|
63 |
|
|
To provide a full two-way IP tunnel, the decapsulation host must
|
64 |
|
|
set up an IP encapsulation driver, and the encapsulating host must
|
65 |
|
|
load the IP decapsulation module, providing full duplex communication
|
66 |
|
|
through the IP tunnel.
|
67 |
|
|
|
68 |
|
|
An example setup might be as follows.
|
69 |
|
|
|
70 |
|
|
Machine A has an ethernet interface with an IP address
|
71 |
|
|
of 111.112.101.37, while machine B is on a different network, with
|
72 |
|
|
an ethernet interface at IP address 111.112.100.86. For some
|
73 |
|
|
reason, machine A needs to appear on machine B's network. It could
|
74 |
|
|
do that by setting up an IP tunnel with machine B.
|
75 |
|
|
|
76 |
|
|
First, the commands that would be run on machine A:
|
77 |
|
|
(Assuming both machines are Linux hosts, running Linux 1.1.x)
|
78 |
|
|
|
79 |
|
|
# insmod ipip.o ; insmod tunnel.o // Here the drivers are loaded.
|
80 |
|
|
# ifconfig tunl 111.112.100.87 pointopoint 111.112.100.86
|
81 |
|
|
# ifconfig tunl netmask 255.255.255.0 // Set a proper netmask.
|
82 |
|
|
# route add 111.112.100.86 dev eth0 // Set a static route to B.
|
83 |
|
|
# route add -net 111.112.100.0 dev tunl // Set up other routes.
|
84 |
|
|
|
85 |
|
|
At this point, machine A is ready to route all traffic to the
|
86 |
|
|
network that machine B resides on. But now, machine B needs to
|
87 |
|
|
set up its half of the IP tunnel:
|
88 |
|
|
|
89 |
|
|
# insmod ipip.o ; insmod tunnel.o // Here the drivers are loaded.
|
90 |
|
|
# ifconfig tunl 111.112.100.86 pointopoint 111.112.101.37
|
91 |
|
|
# ifconfig tunl netmask 255.255.255.0 // Set a proper netmask.
|
92 |
|
|
# route add 111.112.100.87 dev eth0 // Set a static route to B.
|
93 |
|
|
# arp -s 111.112.100.87 EE.EE.EE.EE.EE pub // Act as a proxy arp server.
|
94 |
|
|
|
95 |
|
|
The extra step of "arp -s" is needed so that when machines on
|
96 |
|
|
network B query to see if 111.112.100.87 (the "ghost" host)
|
97 |
|
|
exists, machine B will respond, acting as an arp proxy for machine
|
98 |
|
|
A. In the command line, EE.EE.EE.EE.EE should be replaced with
|
99 |
|
|
the ethernet hardware address of machine B's ethernet card.
|
100 |
|
|
|
101 |
|
|
Notice that machine B's setup is almost the inverse of machine A's
|
102 |
|
|
setup. This is because IP tunneling is a peer-to-peer concept.
|
103 |
|
|
There is no client and no server, there is no state to keep track
|
104 |
|
|
of. The concept is simple. Every IP packet outbound through the
|
105 |
|
|
tunnel interface is wrapped and sent to the pointopoint address
|
106 |
|
|
and every incoming IP-in-IP packet bound for the local machine is
|
107 |
|
|
unwrapped and re-routed normally.
|
108 |
|
|
The only difference in the two machines setup shown above is that
|
109 |
|
|
machine A set its tunnel address to one existing on machine B's
|
110 |
|
|
network, while B set a route to machine A's tunnel device address
|
111 |
|
|
through the tunnel. This is because machine A wants to have a new
|
112 |
|
|
address on network B, and machine B is simply acting as a proxy
|
113 |
|
|
for machine A. Machine A needs its tunnel address to be on network
|
114 |
|
|
B so that when packets from machine B are unwrapped, the Linux
|
115 |
|
|
routing system knows that the address is a local one. Due to a
|
116 |
|
|
feature of Linux, any packets received locally, bound for another
|
117 |
|
|
local address, are simply routed through the loopback interface.
|
118 |
|
|
This means that the tunnel device should never receive packets. Even
|
119 |
|
|
on machine B, it is the ethernet interface that is receiving wrapped
|
120 |
|
|
packets, and once they are unwrapped they go back out the ethernet
|
121 |
|
|
interface. This could cause Linux to generate ICMP redirect messages
|
122 |
|
|
if this special routing case isn't caught (see /linux/net/inet/ip.c)
|
123 |
|
|
|