Emulating
Networks Using User-Mode Linux
Ralf Spenneberg
When evaluating a new product or planning your firewall or VPN,
it is always handy to be able to emulate your network virtually.
Many people use VMware for this task and, although VMware does a
very good job, it is quite cost-intensive. In this article, I'll
describe how to use User-Mode Linux (UML) to model a network. UML
is a Linux kernel capable of running on Linux. It offers networking,
access to the host filesystem, jail, and honeypot features. Using
virtual switches, you can combine several hosts to form a network.
To use UML, you just need a Linux filesystem that the UML kernel
can boot. I will also show how to use UML to emulate a testbed for
a VPN solution.
Virtual private networks (VPNs) have been around for quite some
time. Several protocols are available to implement VPN solutions.
The most prominent protocols are the Point-to-Point-Tunneling-Protocol
(PPTP) and the IP Security Protocols (IPsec). I have played around
with both protocols during the past 5-6 years building both small
and worldwide implementations. Most often I used open source operating
systems like Linux or OpenBSD to implement the VPN gateways.
A lot of the time I spend working with VPNs is actually spent
on testing new implementations and products -- testing the interoperability,
robustness, and speed. So naturally I looked for ways to emulate
and test new scenarios. In some cases, you have to use VMware. If
you want to emulate and test a heterogeneous IPsec setup involving
Microsoft Windows operating systems and Linux boxes on your Linux
host, you will have to use VMware at least for the Windows part.
Whenever possible, however, I use User-Mode Linux for its stability,
reliability, and last but not least speed. In terms of speed, there
are hosting companies around that offer a virtual server setup at
a fraction of the cost of a dedicated server. They often use User-Mode
Linux for this task.
Get the Source
When Jeff Dike started the User-Mode Linux project several years
ago, he hosted it from the very start on SourceForge. You can download
and access all the User-Mode Linux documentation at:
http://user-mode-linux.sourceforge.net/
Additionally, there is a UML-community site at:
http://usermodelinux.org
If you have any problems using User-Mode Linux, you can join the
IRC channel #uml on irc.usermodelinux.org.
To get started with User-Mode Linux, you must first download the
UML kernel patch and a vanilla Linux kernel from:
http://www.kernel.org
You can then patch and build the kernel by issuing the following commands:
tar xjf linux-<version>.tar.bz2
cd linux
bzcat ../uml-patch-<version>.bz2 | patch -p1
make ARCH=um xconfig
make ARCH=um linux
make ARCH=um modules
You may find it easier to compile a monolithic kernel without using
modules. To do so, you can omit the last command. If you have problems
building the kernel, you can download a pre-built kernel at the UML
homepage. There you will also find additional UML utilities and filesystems
that you need to download.
VPN Setup
Next, I will describe how to use the UML kernel to set up a testbed
for the VPN shown in Figure 1. This figure shows two VPN gateways
connected by a router. Behind both gateways there is an additional
machine that will use the tunnel created by the gateways. The router
will be implemented on the Linux host. All other machines, both
gateways, and both private machines will be emulated.
In this case, we want to use the new IPsec features of the Linux
kernel 2.6. For more information about these new features, you can
read the September issue of Sys Admin magazine where I explained
them in detail (http://www.samag.com/documents/s=8859/sam0309i/).
To begin, you'll need a UML kernel capable of using IPsec. Download
a recent UML-patch from the UML homepage and the corresponding 2.6
Linux kernel from kernel.org. Then, extract the kernel and patch
it as shown above. When configuring the kernel, disable "Loadable
Module Support" and activate all options needed for IPsec (see Figures
2 and 3). Compile the kernel.
Download the uml_utilities from the UML homepage and compile and
install them:
tar xjf uml_utilities-<version>.tar.bz2
make
make install
Additionally, you will need a UML filesystem. You can either download
your filesystem from the UML homepage or create your own. I usually
create my own filesystems, because I like to choose the distribution
and packages to install. There are several utilities available to
help you create a UML filesystem. The UML homepage lists mkrootfs,
gBootRoot, rootstrap, and UML Builder. I usually use UML Builder --
it's a graphical tool capable of building filesystems based on all
RPM-based Linux distributions such as Red Hat Linux.
Next, we must configure the host and the UML sessions to use the
correct IP addresses. When starting the UML kernel, we can create
virtual network interfaces. These network interfaces are either
connected to the host or to a separate switch, which is just shared
in between chosen UML instances. We want the private client and
the corresponding VPN gateway to share a switch. Therefore, we need
two switches: one for the left side and one for the right side.
The switch is part of the UML utilities and is started using the
command uml_switch. Because we need to start two switch instances,
we must define the file that the switch uses to communicate with
the UML kernel:
uml_switch -unix /tmp/left.ctl
uml_switch -unix /tmp/right.ctl
The uml_switch stays in the foreground. This is especially helpful
in the beginning, because you can watch the clients connect to the
switch. Later you can start the switch using:
uml_switch -unix /tmp/left.ctl &>/tmp/switch_left &
Now you can start the first private client. When starting the client,
you must define the UML root filesystem to use and the switch to connect
to. If you want to use a swap filesystem, you first need to create
one like this:
dd if=/dev/zero of=swapfs count=128 size=1024k
/sbin/mkswap swapfs
Start the first UML instance:
linux umid="Left private client" root=6200 ubd0=rootfs_left \
ubd7=swapfs_left eth0=daemon,10:00:01:02:00:00,,/tmp/left.ctl
Once the operating system is booted, it will spawn an xterm. The title
of the xterm can be specified using the umid-Option. The UML-block-device
ubd0 is the root filesystem. The ub7 is the swap filesystem. The eth0
definition tells the UML kernel how to emulate the UML Ethernet card.
Here it will be connected to the uml_switch using /tmp/left.ctl and
will use the specified MAC address. Once the client has started, you
will see a login similar to the one in Figure 4.
Now start the second private client using:
linux umid="Right private client" root=6200 ubd0=rootfs_right \
ubd7=swapfs_right eth0=daemon,10:00:02:02:00:00,,/tmp/right.ctl
Once both clients have been started, configure them to use the IP
addresses shown in Figure 1. The left private client should use:
IP: 10.0.1.100
Netmask: 255.255.255.0
GW: 10.0.1.1
The right client should use:
IP: 10.0.2.100
Netmask: 255.255.255.0
GW: 10.0.2.1
Next, start the VPN gateways. These gateways both have two network
cards. One card is used to connect to the private client using the
UML switch. The other card is connected to the host being the router.
Start the first VPN gateway using:
linux umid="Left GW" root=6200 ubd0=rootfs_leftgw \
ubd7=swapfs_leftgw eth0=tuntap,,,3.255.255.254 \
eth1=daemon,10:00:01:01:00:00,,/tmp/left.ctl,
Here we define two network cards. The first will use a tap device
to connect to the host. The tap0 device on the host will get the IP
address 3.255.255.254. The second network card, eth1, will be connected
to the switch. Make sure you use a different MAC address here or the
switch will not work. As soon as the first VPN gateway has booted,
configure the network cards:
eth0:
IP: 3.0.0.1
Netmask: 255.0.0.0
GW: 3.255.255.254
eth1:
IP:10.0.1.1
Netmask: 255.255.255.0
The tap0 interface on the host is configured automatically by the
UML kernel:
# /sbin/ifconfig tap0
tap0 Protokoll:Ethernet Hardware Adresse 00:FF:3C:71:26:13
inet Adresse:3.255.255.254 Bcast:3.255.255.255 \
Maske:255.255.255.255 \
inet6 Adresse: fe80::2ff:3cff:fe71:2613/64 \
Gltigkeitsbereich:Verbindung
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
Kollisionen:0 Sendewarteschlangenlnge:100
RX bytes:168 (168.0 b) TX bytes:460 (460.0 b)
Now start the second VPN gateway using:
linux umid="Right GW" root=6200 ubd0=rootfs_rightgw \
ubd7=swapfs_rightgw eth0=tuntap,,,5.255.255.254 \
eth1=daemon,10:00:02:01:00:00,,/tmp/right.ctl,
Configure the network cards of the second VPN gateway according to
Figure 1. You must configure IP forwarding on both VPN gateways and
configure routing on the host. To configure IP forwarding, enter on
the VPN gateway:
sysctl -w net.ipv4.ip_forward=1
To configure the routing on the host, use the following commands on
the host:
route add -net 10.0.1.0 netmask 255.255.255.0 gw 3.0.0.1
route add -net 10.0.2.0 netmask 255.255.255.0 gw 5.0.0.1
If you have no firewalling enabled, you should be able to log into
the left private client and ping the right private client. Running
tcpdump on the host should show non-encrypted packets passing back
and forth.
To configure a VPN, create the following configuration file, /etc/setkey.conf,
on the left gateway:
#!/usr/sbin/setkey -f
# Clear the SAD and SPD
flush;
spdflush;
# Create the IPsec SAs
add 5.0.0.1 3.0.0.1 esp 0x200 -m tunnel -E 3des-cbc 0x3f0b868ad03e68acc6e4e4644
ac8bb80ecea3426d3d30ada -A hmac-md5 0xbf9a081e7ebdd4fa824c822ed94f5226;
add 3.0.0.1 5.0.0.1 esp 0x200 -m tunnel -E 3des-cbc 0x3f0b868ad03e68acc6e4e4644
ac8bb80ecea3426d3d30ada -A hmac-md5 0xbf9a081e7ebdd4fa824c822ed94f5226;
# Create the security policies for the networks
spdadd 10.0.1.0/24 10.0.2.0/24 any -P out ipsec
esp/tunnel/3.0.0.1-5.0.0.1/require;
spdadd 10.0.2.0/24 10.0.1.0/24 any -P in ipsec
esp/tunnel/5.0.0.1-3.0.0.1/require;
On the right gateway, use:
#!/usr/sbin/setkey -f
# Clear the SAD and SPD
flush;
spdflush;
# Create the IPsec SAs
add 5.0.0.1 3.0.0.1 esp 0x200 -m tunnel -E 3des-cbc \
0x3f0b868ad03e68acc6e4e4644 ac8bb80ecea3426d3d30ada \
-A hmac-md5 0xbf9a081e7ebdd4fa824c822ed94f5226;
add 3.0.0.1 5.0.0.1 esp 0x200 -m tunnel -E 3des-cbc \
0x3f0b868ad03e68acc6e4e4644 ac8bb80ecea3426d3d30ada \
-A hmac-md5 0xbf9a081e7ebdd4fa824c822ed94f5226;
# Create the security policies for the networks
spdadd 10.0.1.0/24 10.0.2.0/24 any -P in ipsec
esp/tunnel/3.0.0.1-5.0.0.1/require;
spdadd 10.0.2.0/24 10.0.1.0/24 any -P out ipsec
esp/tunnel/5.0.0.1-3.0.0.1/require;
Be aware that the directions (in/out) of the policies have changed.
When calling the setkey command /sbin/setkey -f /etc/setkey.conf,
these files will manually create the security associations and policies
needed to set up an encrypted tunnel between the VPN gateways. When
pinging, now tcpdump will see encrypted traffic between the gateways:
13:55:04.084453 3.0.0.1 > 5.0.0.1: ESP(spi=0x00000200,seq=0x1) (DF)
13:55:04.116751 5.0.0.1 > 3.0.0.1: ESP(spi=0x00000200,seq=0x1)
13:55:05.316298 3.0.0.1 > 5.0.0.1: ESP(spi=0x00000200,seq=0x2) (DF)
13:55:05.348958 5.0.0.1 > 3.0.0.1: ESP(spi=0x00000200,seq=0x2)
If your distribution does not provide the setkey command, you can
download the ipsec-tools from the ipsec-tools homepage:
http://ipsec-tools.sourceforge.net
These ipsec-tools include the racoon-IKE-daemon, which can also be
used to create IPsec tunnels. If you need more information about the
ipsec-tools, refer to my IPsec article in the September 2003 issue
of Sys Admin magazine.
Using UML, you can emulate any kind of network and test IPsec,
Netfilter, IPv6, QoS, etc. Just make sure you include the needed
capabilities when configuring and compiling the UML kernel. With
UML, you can greatly speed up the testing phase, because you need
less hardware and the network setup goes much faster. You can also
demonstrate new features more easily because a simple notebook will
suffice to demonstrate large networks. I have also used UML very
successfully in talks and courses.
Ralf Spenneberg has used Linux since 1992 and worked as a systems
administrator since 1994. During this time, he worked on numerous
Windows, Linux, and Unix systems. He has been working as a freelancer
in the Linux/Unix field for the past five years, mostly providing
Linux/Unix training. His specialty is network administration and
security (firewalling, VPNs, intrusion detection). He has developed
several training classes used by Red Hat and other IT training companies
in Germany. He has spoken at several SANS conferences and even more
Unix/Linux-specific conferences. He was chosen to be member of the
program committee of the Linux Kongress and the GUUG Frühjahrsfachgespräch.
He has written two books, Intrusion Detection for Linux Server
and VPN using Linux.
|