SCID: IP
over IP tunnel
Yu Cai
1) IP tunnel Introduction
IP tunneling (IP
encapsulation) is a technique to encapsulate IP datagram within IP datagrams,
which allows datagrams destined for one IP address to be wrapped and redirected
to another IP address. IP encapsulation is now commonly used in Extranet,
Mobile-IP, IP-Multicast, tunneled host or network.
There are 3 kinds of tunnels: IP over IP tunneling, GRE tunneling and tunnels
that live outside the kernel. In
this project, we are using IP over IP tunneling, also noted as IPIP tunnel, or
IP in IP tunnel. Examples of tunnels include PPTP, IPSec, L2TP etc.
Tunneling increases overhead, because it needs an extra set of IP headers.
Typically this is 20 bytes per packet, so if the normal packet size (MTU) on a
network is 1500 bytes, a packet that is sent through a tunnel can only be 1480
bytes big.
Here is an IP tunneling diagram:
2) Steps
to setup IP over IP tunnel (IPIP tunnel) on Redhat Linux
2.1) Install IP tunnel package.
Most of the time, your redhat linux should already have ip tunnel package
installed by default. You can check it by running "ip tunnel add tunl1 mode ipip remote
192.168.1.1". If you can successfully add a new ip tunnel, then you are ok.
But If not, then you need to recompile linux kernel to enable IPIP tunnel.
see this howto for kernel recompile from redhat linux.
Kernel Compile Options:
Networking options ---> [*] TCP/IP networking [*] IP: forwarding/gateway .... <*> IP: tunneling |
2.2) Setup
the IP tunnel testbed and config route tables/firewall rules on each machine
Below is the test bed view graph (all machines are running redhat 9)
In most IP tunnel scenarios, people use public IP address and private IP address to config the tunnel. It makes sense because connecting two private lan through IP tunnel is one of the major use of IP tunneling. But in our project, we don't want any private IP address, so we config the IPIP tunnel with only public IP.
Below are
scripts on each machine.
a) Script on
client to setup tunnel 1
#!/bin/sh #------------------------------------------------ # IPIP tunnel config scipt on client side # # By Yu Cai (ycai@uccs.edu) at UCCS, June 2003 #------------------------------------------------ #define var client_ip=128.198.61.51 client_gw=128.198.61.1 proxy_ip=128.198.60.42 proxy_gw=128.198.60.1 gw_ip=128.198.60.200 gw_gw=128.198.60.129 target_ip=128.198.60.201 tunl=tunl1 #config tunnel between client and proxy ip tunnel add $tunl mode ipip remote $proxy_ip dev eth0 ifconfig $tunl $client_ip ip link set $tunl up ip route add $proxy_ip via $client_gw dev $tunl onlink #route traffic between client and gateway through tunnel ip route add $gw_ip via $client_gw dev $tunl onlink #route traffic between client and target through tunnel ip route add $target_ip via $client_gw dev $tunl onlink |
Script on client to setup tunnel 3
#!/bin/sh #------------------------------------------------ # IPIP tunnel config scipt on client side # # By Yu Cai (ycai@uccs.edu) at UCCS, June 2003 #------------------------------------------------ #define var client_ip=128.198.61.51 client_gw=128.198.61.1 proxy_ip=128.198.61.100 proxy_gw=128.198.61.1 gw_ip=128.198.60.199 gw_gw=128.198.60.129 tunl=tunl3 #config tunnel between client and proxy ip tunnel add $tunl mode ipip remote $proxy_ip dev eth0 ifconfig $tunl $client_ip ip link set $tunl up ip route add $proxy_ip via $client_gw dev $tunl onlink #route traffic between client and gateway through tunnel ip route add $gw_ip via $client_gw dev $tunl onlink |
b) Script on proxy (script on proxy2 is similiar)
#!/bin/sh #------------------------------------------------ # IPIP tunnel config scipt on proxy side # # By Yu Cai (ycai@uccs.edu) at UCCS, June 2003 #------------------------------------------------ iptables -F iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT #enable ip forwarding echo "1" > /proc/sys/net/ipv4/ip_forward #define var client_ip=128.198.61.51 client_gw=128.198.61.1 proxy_ip=128.198.60.42 proxy_gw=128.198.60.1 gw_ip=128.198.60.200 gw_gw=128.198.60.129 target_ip=128.198.60.201 #config tunnel between proxy and client tunl=tunl1 ip tunnel add $tunl mode ipip remote $client_ip dev eth0 ifconfig $tunl $proxy_ip ip link set $tunl up ip route add $client_ip via $proxy_gw dev $tunl onlink #config tunnel between proxy and gateway tunl=tunl2 ip tunnel add $tunl mode ipip remote $gw_ip dev eth0 ifconfig $tunl $proxy_ip ip link set $tunl up ip route add $gw_ip via $proxy_gw dev $tunl onlink #route between proxy and target through tunnel ip route add $target_ip via $proxy_gw dev $tunl onlink |
c) Script on gateway (script on gateway2 is similiar)
#!/bin/sh #------------------------------------------------ # IPIP tunnel config scipt on gateway side # # By Yu Cai (ycai@uccs.edu) at UCCS, June 2003 #------------------------------------------------ iptables -F iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT echo "1">/proc/sys/net/ipv4/ip_forward #define var client_ip=128.198.61.51 client_gw=128.198.61.1 proxy_ip=128.198.60.42 proxy_gw=128.198.60.1 gw_ip=128.198.60.200 gw_gw=128.198.60.129 tunl=tunl2 #config tunnel between gateway and proxy ip tunnel add $tunl mode ipip remote $proxy_ip dev eth0 ifconfig $tunl $gw_ip ip link set $tunl up ip route add $proxy_ip via $gw_gw dev $tunl onlink #route traffic between client and gateway through tunnel ip route add $client_ip via $gw_gw dev $tunl onlink |
d) Script on target
#!/bin/sh #----------------------------------------------- #IPIP tunnel config script on target side # #By Yu Cai(ycai@uccs.edu) at UCCS, June 2003 #----------------------------------------------- #define var client_ip=128.198.61.51 gw_ip=128.198.60.200 #route between client and target through gateway ip route add $client_ip via $gw_ip dev eth0 onlink |
2.3) Verify your config and make sure the IPIP
tunnel set up successfully.
After the
configuration, you should be able to see the ip tunnel device.
[root@client root]# ifconfig eth0 Link encap:Ethernet HWaddr 00:0C:29:47:59:30 inet addr:128.198.61.51 Bcast:128.198.61.63 Mask:255.255.255.192 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:116492 errors:0 dropped:0 overruns:0 frame:0 TX packets:543 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:8552726 (8.1 Mb) TX bytes:48894 (47.7 Kb) Interrupt:18 Base address:0x10a0 tunl1 Link encap:IPIP Tunnel HWaddr inet addr:128.198.61.51 P-t-P:128.198.61.51 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MTU:1480 Metric:1 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:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) [root@client root]# ip link show 1: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:0c:29:47:59:30 brd ff:ff:ff:ff:ff:ff 2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop link/ipip 0.0.0.0 brd 0.0.0.0 3: tunl1@eth0: <POINTOPOINT,NOARP,UP> mtu 1480 qdisc noqueue link/ipip 0.0.0.0 peer 128.198.60.42 [root@client root]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 128.198.60.42 128.198.61.1 255.255.255.255 UGH 0 0 0 tunl1 128.198.61.0 0.0.0.0 255.255.255.192 U 0 0 0 eth0 0.0.0.0 128.198.61.1 0.0.0.0 UG 0 0 0 eth0 |
Also, you should be able to ping gateway from client, and vice verse,
by passing through IPIP tunnel.
How to you know you are going through IPIP
tunnel, not a regular internet route?
Run "netstat -i" on each machine several times during the ping session, you
will
see IP packages passing through tunnel interfaces.
[root@proxy root]# netstat -i Kernel Interface table Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg eth0 1500 0 76651 0 0 0 863 0 0 0 BMRU tunl1 1480 0 0 0 0 0 0 0 0 0 OPRU [root@proxy root]# netstat -i Kernel Interface table Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg eth0 1500 0 76676 0 0 0 878 0 0 0 BMRU tunl1 1480 0 52 0 0 0 52 0 0 0 OPRU [root@proxy root]# netstat -i Kernel Interface table Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg eth0 1500 0 76676 0 0 0 878 0 0 0 BMRU tunl1 1480 0 104 0 0 0 104 0 0 0 OPRU |
For some reason, when you use tethereal to
monitor the traffic, you won't see any thing!?
To disable the tunnel interface, run "ifconfig tunl1 down".
2.4) For those who want to setup IP tunnel with private
IP and public IP
In most IP
tunnel scenarios, people use public IP address and private IP address to config
the tunnel. It makes sense because connecting two private lan through IP tunnel
is one of the major use of IP tunneling.
Below is the testbed view graph for IP tunnel with private IP and public IP.
Below is the config script.
#----------------------------------------------------- # IPIP tunnel config scipt on client side #----------------------------------------------------- #config tunl1 connecting client and proxy ip tunnel add tunl1 mode ipip remote 128.198.60.42 dev eth0 ifconfig tunl1 192.168.4.1 ip link set tunl1 up #route between client and proxy ip route add 192.168.2.1 via 128.198.61.1 dev tunl1 onlink ip route add 192.168.3.1 via 128.198.61.1 dev tunl1 onlink |
#----------------------------------------------------- # IPIP tunnel config scipt on proxy side #----------------------------------------------------- iptables -F iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT echo "1" > /proc/sys/net/ipv4/ip_forward #config tunl1 between proxy and client ip tunnel add tunl1 mode ipip remote 128.198.61.51 ifconfig tunl1 192.168.2.1 ip link set tunl1 up ip route add 192.168.4.1 via 128.198.60.1 dev tunl1 onlink #config tunl2 between proxy and gateway ip tunnel add tunl2 mode ipip remote 128.198.60.200 ifconfig tunl2 192.168.2.1 ip link set tunl2 up ip route add 192.168.3.1 via 128.198.60.1 dev tunl2 onlink |
#----------------------------------------------------- # IPIP tunnel config scipt on gateway side #----------------------------------------------------- #config tunl2 between proxy and gateway ip tunnel add tunl2 mode ipip remote 128.198.60.42 ifconfig tunl2 192.168.3.1 ip link set tunl2 up ip route add 192.168.2.1 via 128.198.60.129 dev tunl2 onlink ip route add 192.168.4.1 via 128.198.60.129 dev tunl2 onlink |
2.5) For those who want to setup IP tunnel on
Windows.
If you want to setup IP tunnel on windows,
make sure you have windows 2000 server or advance server.
Since IP tunnel requires advanced features of routing and remote access, windows
Me, window XP, window 2000 professional don't support IPIP tunnel. (This is kind
of weird, because windows XP support IPsec tunnel, but not IPIP tunnel.)
Also, IP tunnel on Windows didn't support public IP only configuration, you have to config the machines with private IP as well as public IP.
You can set up IP tunnel between two windows machines, or a windows/ a linux.
Below is the test bed view graph: (Client is windows 2000 advance server, proxy/gateway/target are redhat 9)
Here is a step by step guide on how to configure IP tunnel
between a windows 2000 advance server and a redhat 9 machine
[client (win 2000, IP 128.198.60.45 and 192.168.10.1) and proxy (redhat 9, IP
128.198.61.51 and 192.168.4.1) in above graph].
1) On windows 2000 machine (client), see if Routing and Remote Access Service is running | Windows Control Pane or
Administrative Tools ==>Service ==> Routing and Remote Access Running.
If it is not running, |
2) Create Tunnel Interface |
Windows Control Pane or Administrative Tools ==>Routing and Remote Access ==> In the console tree, click the server you use & select Routing Interface ==> R-click Routing Interface & choose 'New IP tunnel' ==> In interface name, type a name for the tunnel, and click OK Now we have a new IP tunnel interface, below is how we use it. ==> In the console tree, click IP Routing, r-click General, and then click New Interface ==> In Interfaces, click the IP-in-IP tunnel you just created ==> On the Tunnel tab - Local address : IP address of the tunnel start point (your public IP) - Remote address: IP address of the tunnel endpoint (remote public IP) |
3) Add
new Static Route |
In Administrative Tools
==> Routing & Remote Access ==> Choose the server you want ==>IP Routing ==> R-click 'Static Route' ==> Select 'New Static Route' ==> Enter the parameter below: - Interface : the IP tunnel which you just created. - Destination : IP address of the tunnel endpoint (remote private IP) - Net Mask : 255.255.255.255 - Gateway: IP address of the tunnel start point (your public IP) |
4) Above is the manual configuration on windows 2000. We can use netsh script to setup the ip tunnel on windows. | #------------------------------------------------------------------------- # IPIP tunnel config batch script on windows 2000 advance server # # By Yu Cai (ycai@uccs.edu) at UCCS, June 2003 #------------------------------------------------------------------------- netsh interface add interface tunl1 tunnel netsh routing ip set ipiptunnel tunl1 128.198.60.45 128.198.61.50 5 netsh routing ip add rtmroute dest=192.168.4.1 mask=255.255.255.255 nameorindex=tunl1 |
5) Now the config on windows 2000 is finished. Let's config on the redhat 9 machine (Proxy). Here is the script. |
#!/bin/sh #------------------------------------------------ # IPIP tunnel config scipt on proxy side # connecting a redhat linux 9 and a windows 2000 advance server # # By Yu Cai (ycai@uccs.edu) at UCCS, June 2003 #------------------------------------------------ #config tunl1 between win2000 and redhat9 ip tunnel add tunl1 mode ipip remote 128.198.60.45 dev eth0 ifconfig tunl1 192.168.4.1 ip link set tunl1 up ip route add 192.168.10.1 via 128.198.61.1 dev tunl1 onlink |
6) See if the IP tunnel is really setup. | Ping 192.168.10.1 from 192.168.4.1 and vice
verse. Run ethereal on one side, you should catch some TCP packages like below. Notice that the packages have two IP header with different IP address. |
3) Performance
Benchmark
Test below is based on configuration of
Section 2.2: linux machines with public IP only.
3.1) Testbed machine configuration.
Machine | Settings |
Client | Virtual Machine on ardor.uccs.edu, 256M RAM, 2 G hard disk |
Proxy | same |
Gateway | same |
Target | same |
Proxy 2 | Virtual Machine on athena.uccs.edu, 256M RAM, 2 G hard disk |
Gateway 2 | Virtual Machine on wait.uccs.edu, 256M RAM, 2 G hard disk |
3.2) Response Time benchmark using Ping
I ping gateway from client. Below is the testing result (result is the average of 10 tests).
With direct route | With indirect route through IPIP tunnel |
0.54 ms (only 1 hop) |
1.18 ms (2 hops, you can't see them with traceroute) |
3.3) Throughput benchmark using FTP
I installed VSFTP server
on gateway machine. On client machine, retrieve a 100MB file from gateway.
Below is the testing result (result is the average of 10 tests).
With direct route | With indirect route through IPIP tunnel |
12.8 second | 24.5 second |
When the main gateway got
attacked, the performance on the direct route will go from 12 seconds to days or
infinity. The overhead occurs in the indirect route include more hop, more
protocol processing (it goes through proxy server; and IP over IP overhead
related to fragmentation; can be reduced if the client can set MSB to max - 20
(additional IP header)).
4) Related Questions
1) How many IP tunnels are allowed in redhat
linux and windows 2000 server?
It seems unlimited or only limited by
system resources. I wrote a script to add more than 100 tunnels, and it seems to
work fine (on linux and on windows).
Not sure about the effect of frequent and large amount of connect and disconnect
of tunnel.
Not sure about the effect of heavy traffic passing through tunnel.
5) Related Resources
1)
Compile linux kernel.
2)
IP tunnel howto from redhat
3) IProute2
4)
IPIP howto from redhat
5)
IPtables command reference