Site Home Page
The UML Wiki
UML Community Site
The UML roadmap
What it's good for
Case Studies
Kernel Capabilities
Downloading it
Running it
Compiling
Installation
Skas Mode
Incremental Patches
Test Suite
Host memory use
Building filesystems
Troubles
User Contributions
Related Links
Projects
Diary
Thanks
Contacts
Tutorials
The HOWTO (html)
The HOWTO (text)
Host file access
Device inputs
Sharing filesystems
Creating filesystems
Resizing filesystems
Virtual Networking
Management Console
Kernel Debugging
UML Honeypots
gprof and gcov
Running X
Diagnosing problems
Configuration
Installing Slackware
Porting UML
IO memory emulation
UML on 2G/2G hosts
Adding a UML system call
Running nested UMLs
How you can help
Overview
Documentation
Utilities
Kernel projects
Screenshots
A virtual network
An X session
Transcripts
A login session
A debugging session
Slackware installation
Reference
Kernel switches
Slackware README
Papers
ALS 2000 paper (html)
ALS 2000 paper (TeX)
ALS 2000 slides
LCA 2001 slides
OLS 2001 paper (html)
OLS 2001 paper (TeX)
ALS 2001 paper (html)
ALS 2001 paper (TeX)
UML security (html)
LCA 2002 (html)
WVU 2002 (html)
Security Roundtable (html)
OLS 2002 slides
LWE 2005 slides
Fun and Games
Kernel Hangman
Disaster of the Month

Setting up the network

This page describes how to set up the various transports and to provide a UML instance with network access to the host, other machines on the local net, and the rest of the net.

As of 2.4.5, UML networking has been completely redone to make it much easier to set up, fix bugs, and add new features.

There is a new helper, uml_net, which does the host setup that requires root privileges.

There are currently five transport types available for a UML virtual machine to exchange packets with other hosts:

  • ethertap
  • TUN/TAP
  • Multicast
  • a switch daemon
  • slip
  • slirp
  • pcap
The TUN/TAP, ethertap, slip, and slirp transports allow a UML instance to exchange packets with the host. They may be directed to the host or the host may just act as a router to provide access to other physical or virtual machines.

The pcap transport is a synthetic read-only interface, using the libpcap binary to collect packets from interfaces on the host and filter them. This is useful for building preconfigured traffic monitors or sniffers.

The daemon and multicast transports provide a completely virtual network to other virtual machines. This network is completely disconnected from the physical network unless one of the virtual machines on it is acting as a gateway.

With so many host transports, which one should you use? Here's when you should use each one:

  • ethertap - if you want access to the host networking and it is running 2.2
  • TUN/TAP - if you want access to the host networking and it is running 2.4. Also, the TUN/TAP transport is able to use a preconfigured device, allowing it to avoid using the setuid uml_net helper, which is a security advantage.
  • Multicast - if you want a purely virtual network and you don't want to set up anything but the UML
  • a switch daemon - if you want a purely virtual network and you don't mind running the daemon in order to get somewhat better performance
  • slip - there is no particular reason to run the slip backend unless ethertap and TUN/TAP are just not available for some reason
  • slirp - if you don't have root access on the host to setup networking, or if you don't want to allocate an IP to your UML
  • pcap - not much use for actual network connectivity, but great for monitoring traffic on the host
Ethertap is available on 2.4 and works fine. TUN/TAP is preferred to it because it has better performance and ethertap is officially considered obsolete in 2.4. Also, the root helper only needs to run occasionally for TUN/TAP, rather than handling every packet, as it does with ethertap. This is a slight security advantage since it provides fewer opportunities for a nasty UML user to somehow exploit the helper's root privileges.
General setup
First, you must have the virtual network enabled in your UML. If are running a prebuilt kernel from this site, everything is already enabled. If you build the kernel yourself, under the "Network device support" menu, enable "Network device support", and then the three transports.

The next step is to provide a network device to the virtual machine. This is done by describing it on the kernel command line. The general format is

eth<n>=<transport>,<transport args>
For example, a virtual ethernet device may be attached to a host ethertap device as follows:
eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
This sets up eth0 inside the virtual machine to attach itself to the host /dev/tap0, assigns it an ethernet address, and assigns the host tap0 interface an IP address.

Note that the IP address you assign to the host end of the tap device must be different than the IP you assign to the eth device inside UML. If you are short on IPs and don't want to comsume two per UML, then you can reuse the host's eth IP address for the host ends of the tap devices. Internally, the UMLs must still get unique IPs for their eth devices. You can also give the UMLs non-routable IPs (192.168.x.x or 10.x.x.x) and have the host masquerade them. This will let outgoing connections work, but incoming connections won't without more work, such as port forwarding from the host.

Also note that when you configure the host side of an interface, it is only acting as a gateway. It will respond to pings sent to it locally, but is not useful to do that since it's a host interface. You are not talking to the UML when you ping that interface and get a response.

You can also add devices to a UML and remove them at runtime. See the mconsole page for details.

The sections below describe this in more detail.

Once you've decided how you're going to set up the devices, you boot UML, log in, configure the UML side of the devices, and set up routes to the outside world. At that point, you will be able to talk to any other machines, physical or virtual, on the net.

If ifconfig inside UML fails and the network refuses to come up, run 'dmesg' to see what ended up in the kernel log. That will usually tell you what went wrong.

Userspace daemons
You will likely need the setuid helper, or the switch daemon, or both. They are both installed with the RPM and deb, so if you've installed either, you can skip the rest of this section.

If not, then you need to check them out of CVS , build them, and install them. The helper is uml_net, in CVS /tools/uml_net, and the daemon is uml_switch, in CVS /tools/uml_router. They are both built with a plain 'make'. Both need to be installed in a directory that's in your path - /usr/bin is recommend. On top of that, uml_net needs to be setuid root.

Specifying ethernet addresses
Below, you will see that the TUN/TAP, ethertap, and daemon interfaces allow you to specify hardware addresses for the virtual ethernet devices. This is generally not necessary. If you don't have a specific reason to do it, you probably shouldn't. If one is not specified on the command line, the driver will assign one based on the device IP address. It will provide the address fe:fd:nn:nn:nn:nn where nn.nn.nn.nn is the device IP address. This is nearly always sufficient to guarantee a unique hardware address for the device. A couple of exceptions are:
  • Another set of virtual ethernet devices are on the same network and they are assigned hardware addresses using a different scheme which may conflict with the UML IP address-based scheme
  • You aren't going to use the device for IP networking, so you don't assign the device an IP address
If you let the driver provide the hardware address, you should make sure that the device IP address is known before the interface is brought up. So, inside UML, this will guarantee that:
UML# ifconfig eth0 192.168.0.250 up
If you decide to assign the hardware address yourself, make sure that the first byte of the address is even. Addresses with an odd first byte are broadcast addresses, which you don't want assigned to a device.
UML interface setup
Once the network devices have been described on the command line, you should boot UML and log in.

The first thing to do is bring the interface up:

UML# ifconfig ethn ip-address up
You should be able to ping the host at this point.

To reach the rest of the world, you should set a default route to the host:

UML# route add default gw host ip
Again, with host ip of 192.168.0.4:
UML# route add default gw 192.168.0.4
This page used to recommend setting a network route to your local net. This is wrong, because it will cause UML to try to figure out hardware addresses of the local machines by arping on the interface to the host. Since that interface is basically a single strand of ethernet with two nodes on it (UML and the host) and arp requests don't cross networks, they will fail to elicit any responses. So, what you want is for UML to just blindly throw all packets at the host and let it figure out what to do with them, which is what leaving out the network route and adding the default route does.

Note: If you can't communicate with other hosts on your physical ethernet, it's probably because of a network route that's automatically set up. If you run 'route -n' and see a route that looks like this:

                
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0	    0   eth0

              
with a mask that's not 255.255.255.255, then replace it with a route to your host:
UML# route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
UML# route add -host 192.168.0.4 dev eth0
This, plus the default route to the host, will allow UML to exchange packets with any machine on your ethernet.
Multicast
The simplest way to set up a virtual network between multiple UMLs is to use the mcast transport. This was written by Harald Welte and is present in UML version 2.4.5-5um and later. Your system must have multicast enabled in the kernel and there must be a multicast-capable network device on the host. Normally, this is eth0, but if there is no ethernet card on the host, then you will likely get strange error messages when you bring the device up inside UML.

To use it, run two UMLs with

eth0=mcast
on their command lines. Log in, configure the ethernet device in each machine with different IP addresses:
UML1# ifconfig eth0 192.168.0.254
UML2# ifconfig eth0 192.168.0.253
and they should be able to talk to each other.

The full set of command line options for this transport are

ethn=mcast,ethernet address,multicast address,multicast port,ttl
Harald's original README is
here and explains these in detail, as well as some other issues.
TUN/TAP with the uml_net helper
TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the host. The TUN/TAP backend has been in UML since 2.4.9-3um.

The easiest way to get up and running is to let the setuid uml_net helper do the host setup for you. This involves insmod-ing the tun.o module if necessary, configuring the device, and setting up IP forwarding, routing, and proxy arp. If you are new to UML networking, do this first. If you're concerned about the security implications of the setuid helper, use it to get up and running, then read the next section to see how to have UML use a preconfigured tap device, which avoids the use of uml_net.

If you specify an IP address for the host side of the device, the uml_net helper will do all necessary setup on the host - the only requirement is that TUN/TAP be available, either built in to the host kernel or as the tun.o module. The format of the command line switch to attach a device to a TUN/TAP device is

eth<n>=tuntap,,,<host IP address>
For example, this argument will attach the UML's eth0 to the next available tap device, assign the IP address 192.168.0.254 to the host side of the tap device, and assign an ethernet address to it based on the IP address assigned to it by ifconfig inside UML.
eth0=tuntap,,,192.168.0.254

If you using the uml_net helper to set up the host side of the networking, as in this example, note that changing the UML IP address will cause uml_net to change the host routing and arping to match. This is one reason you should not be using uml_net if there is any possibility that the user inside the UML may be unfriendly. This feature is convenient, but can be used to make the UML pretend to be something like your name server or mail server, and the host will steal packets intended for those servers and forward them to the UML. See the next section for setting up networking in a secure manner.

There are a couple potential problems with running the TUN/TAP transport on a 2.4 host kernel

  • TUN/TAP seems not to work on 2.4.3 and earlier. Upgrade the host kernel or use the ethertap transport.
  • With an upgraded kernel, TUN/TAP may fail with
                        File descriptor in bad state
                      
    This is due to a header mismatch between the upgraded kernel and the kernel that was originally installed on the machine. The fix is to make sure that /usr/src/linux points to the headers for the running kernel.
These were pointed out by
Tim Robinson in this uml-user post .
TUN/TAP with a preconfigured tap device
If you prefer not to have UML use uml_net (which is somewhat insecure), with UML 2.4.17-11, you can set up a TUN/TAP device beforehand. The setup needs to be done as root, but once that's done, there is no need for root assistance. Setting up the device is done as follows:
  • Create the device with tunctl (available from the UML utilities tarball)
    host# tunctl -u uid
    where uid is the user id or username that UML will be run as. This will tell you what device was created.
  • Configure the device IP (change IP addresses and device name to suit)
    host# ifconfig tap0 192.168.0.254 up
  • Set up routing and arping if desired - this is my recipe, there are other ways of doing the same thing
    host# bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
    host# route add -host 192.168.0.253 dev tap0
    host# bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
    host# arp -Ds 192.168.0.253 eth0 pub
    Note that this must be done every time the host boots - this configuration is not stored across host reboots. So, it's probably a good idea to stick it in an rc file. An even better idea would be a little utility which reads the information from a config file and sets up devices at boot time.
  • Rather than using up two IPs and ARPing for one of them, you can also provide direct access to your LAN by the UML by using a bridge.
    host# brctl addbr br0
    host# ifconfig eth0 0.0.0.0 promisc up
    host# ifconfig tap0 0.0.0.0 promisc up
    host# ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
    host# brctl stp br0 off
    host# brctl setfd br0 1
    host# brctl sethello br0 1
    host# brctl addif br0 eth0
    host# brctl addif br0 tap0
    Note that 'br0' should be setup using ifconfig with the existing IP address of eth0, as eth0 no longer has its own IP.
  • Also, the /dev/net/tun device must be writable by the user running UML in order for the UML to use the device that's been configured for it. The simplest thing to do is

    host# chmod 666 /dev/net/tun
    Making it world-writeable looks bad, but it seems not to be exploitable as a security hole. However, it does allow anyone to create useless tap devices (useless because they can't configure them), which is a DOS attack. A somewhat more secure alternative would to be to create a group containing all the users who have preconfigured tap devices and chgrp /dev/net/tun to that group with mode 664 or 660.
  • Once the device is set up, run UML with
    eth0=tuntap,devicename
    i.e.
    eth0=tuntap,tap0
    on the command line (or do it with the mconsole config command).
  • Bring the eth device up in UML and you're in business.
If you don't want that tap device any more, you can make it non-persistent with
host# tunctl -d tap device
Finally, tunctl has a -b (for brief mode) switch which causes it to output only the name of the tap device it created. This makes it suitable for capture by a script:
host# TAP=`tunctl -u 1000 -b`
Ethertap
Ethertap is the general mechanism on 2.2 for userspace processes to exchange packets with the kernel.

To use this transport, you need to describe the virtual network device on the UML command line. The general format for this is

eth<n>=ethertap,<device>,<ethernet address>,<host IP address>
So, the previous example
eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
attaches the UML eth0 device to the host /dev/tap0, assigns it the ethernet address fe:fd:0:0:0:1, and assigns the IP address 192.168.0.254 to the host side of the tap device.

The tap device is mandatory, but the others are optional. If the ethernet address is omitted, one will be assigned to it.

The presence of the tap IP address will cause the helper to run and do whatever host setup is needed to allow the virtual machine to communicate with the outside world. If you're not sure you know what you're doing, this is the way to go.

If it is absent, then you must configure the tap device and whatever arping and routing you will need on the host. However, even in this case, the uml_net helper still needs to be in your path and it must be setuid root if you're not running UML as root. This is because the tap device doesn't support SIGIO, which UML needs in order to use something as a source of input. So, the helper is used as a convenient asynchronous IO thread. If you're using the uml_net helper, you can ignore the following host setup - uml_net will do it for you. You just need to make sure you have ethertap available, either built in to the host kernel or available as a module.

If you want to set things up yourself, you need to make sure that the appropriate /dev entry exists. If it doesn't, become root and create it as follows (the $[ ... ] is bash syntax for adding 16 to the minor number) :

mknod /dev/tap<minor> c 36 $[ <minor> + 16 ]
For example, this is how to create /dev/tap0:
mknod /dev/tap0 c 36 $[ 0 + 16 ]
You also need to make sure that the host kernel has ethertap support. If ethertap is enabled as a module, you apparently need to insmod ethertap once for each ethertap device you want to enable. So,
host# insmod ethertap
will give you the tap0 interface. To get the tap1 interface, you need to run
host# insmod ethertap unit=1 -o ethertap1
The switch daemon
Note: This is the daemon formerly known as uml_router, but which was renamed so the network weenies of the world would stop growling at me.

The switch daemon, uml_switch, provides a mechanism for creating a totally virtual network. By default, it provides no connection to the host network (but see -tap, below).

The first thing you need to do is run the daemon. Running it with no arguments will make it listen on a default unix domain socket.

If you want it to listen on a different socket, use

-unix socket

If you want it to act as a hub rather than a switch, use
-hub
If you're planning on putting it in hub mode so you can sniff UML traffic from a tap device on the host, it appears that you need to assign the tap an IP address before you'll see any packets on it.

If you want the switch to be connected to host networking (allowing the umls to get access to the outside world through the host), use

-tap tap0

Note that the tap device must be preconfigured (see "TUN/TAP with a preconfigured tap device", above). If you're using a different tap device than tap0, specify that instead of tap0.

uml_switch can be backgrounded as follows

host% uml_switch [ options ] < /dev/null > /dev/null
The reason it doesn't background by default is that it listens to stdin for EOF. When it sees that, it exits.

The general format of the kernel command line switch is

ethn=daemon,ethernet address,socket type,socket
You can leave off everything except the 'daemon'. You only need to specify the ethernet address if the one that will be assigned to it isn't acceptable for some reason. The rest of the arguments describe how to communicate with the daemon. You should only specify them if you told the daemon to use different sockets than the default. So, if you ran the daemon with no arguments, running the UML on the same machine with
eth0=daemon
will cause the eth0 driver to attach itself to the daemon correctly. The socket argument is the filename of a Unix domain socket which is used for communications between uml_switch and the UMLs on its network. If you do specify a different socket from the default, which you will need to do if you want multiple, separate uml_switch networks on the host, you need to make sure that you name the same path for the socket on both the uml_switch and UML command lines.

Currently the only supported value for the socket type is "unix".

Slip
Slip is another, less general, mechanism for a process to communicate with the host networking. In contrast to the ethertap interface, which exchanges ethernet frames with the host and can be used to transport any higher-level protocol, it can only be used to transport IP.

The general format of the command line switch is

ethn=slip,slip IP
The slip IP argument is the IP address that will be assigned to the host end of the slip device. If it is specified, the helper will run and will set up the host so that the virtual machine can reach it and the rest of the network.

There are some oddities with this interface that you should be aware of. You should only specify one slip device on a given virtual machine, and its name inside UML will be 'umn', not 'eth0' or whatever you specified on the command line. These problems will be fixed at some point.

Slirp
slirp uses an external program, usually /usr/bin/slirp, to provide IP only networking connectivity through the host. This is similar to IP masquerading with a firewall, although the translation is performed in user-space, rather than by the kernel. As slirp does not set up any interfaces on the host, or changes routing, slirp does not require root access or setuid binaries on the host.

The general format of the command line switch for slirp is:

ethn=slirp,ethernet address,slirp path
The ethernet address is optional, as UML will set up the interface with an ethernet address based upon the initial IP address of the interface. The slirp path is generally /usr/bin/slirp, although it will depend on distribution.

The slirp program can have a number of options passed to the command line and we can't add them to the UML command line, as they will be parsed incorrectly. Instead, a wrapper shell script can be written or the options inserted into the ~/.slirprc file. More information on all of the slirp options can be found in its man pages.

The eth0 interface on UML should be set up with the IP 10.2.0.15, although you can use anything as long as it is not used by a network you will be connecting to. The default route on UML should be set to use 'eth0' without a gateway IP:

UML# route add default dev eth0
slirp provides a number of useful IP addresses which can be used by UML, such as 10.0.2.3 which is an alias for the DNS server specified in /etc/resolv.conf on the host or the IP given in the 'dns' option for slirp.

Even with a baudrate setting higher than 115200, the slirp connection is limited to 115200. If you need it to go faster, the slirp binary needs to be compiled with FULL_BOLT defined in config.h.

pcap
The pcap transport is attached to a UML ethernet device on the command line or with uml_mconsole with the following syntax:
ethn=pcap,host interface,filter expression,option1,option2
The expression and options are optional.

The interface is whatever network device on the host you want to sniff. The expression is a pcap filter expression, which is also what tcpdump uses, so if you know how to specify tcpdump filters, you will use the same expressions here. The options are up to two of 'promisc', 'nopromisc', 'optimize', 'nooptimize'. 'promisc' and 'nopromisc' control whether pcap puts the host interface into promiscuous mode. 'optimize' and 'nooptimize' control whether the pcap expression optimizer is used.

Example:

eth0=pcap,eth0,tcp
eth1=pcap,eth0,!tcp
will cause the UML eth0 to emit all tcp packets on the host eth0 and the UML eth1 to emit all non-tcp packets on the host eth0.
Setting up the host yourself
If you don't specify an address for the host side of the ethertap or slip device, UML won't do any setup on the host. So this is what is needed to get things working (the examples use a host-side IP of 192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your own network):
  • The device needs to be configured with its IP address. Tap devices are also configured with an mtu of 1484. Slip devices are configured with a point-to-point address pointing at the UML ip address.
    host# ifconfig tap0 arp mtu 1484 192.168.0.251 up
    host# ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
  • If a tap device is being set up, a route is set to the UML IP.
    UML# route add -host 192.168.0.250 gw 192.168.0.251
  • To allow other hosts on your network to see the virtual machine, proxy arp is set up for it.
    host# arp -Ds 192.168.0.250 eth0 pub
  • Finally, the host is set up to route packets.
    host# echo 1 > /proc/sys/net/ipv4/ip_forward
Hosted at SourceForge Logo