# TUN/TAP and KVM (QEMU)

## HuskyDog

When I try to run KVM (essentially QEMU) I get the following error:

```
warning: could not open /dev/net/tun: no virtual network emulation

Could not initialize device 'tap'
```

So, I read the instructions and basically it says that if you are running a kernel >2.6.18 (mine is 2.6.22-gentoo-r8) then you need to use tunctl to set the appropriate permissions.  So, I enter the following as root:

```
# tunctl -u my_user_name -t tap0

Set 'tap0' persistent and owned by uid 1000
```

That looks right to me.  My user is indeed uid 1000.  Clealy, the tap interface is running and that is confirmed by ifconfig.

However, when I try again with the following command as my user;

```
kvm -hda /dev/mapper/vols-andrew_root -cdrom ./install.iso -boot d -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -vnc :1 -k en-gb -monitor stdio

```

I get exactly the same error as above (i.e. the fix has made no difference at all).  I should add that when I don't bother with this 'tap' lark and just stick with user networking my kvm works just fine.

So, this is one of those cases which occurs all too often with Linux where you get an error, find the exact error and a clearly defined fix, but when you apply the fix it makes no difference!  Would anyone like to suggest another solution?

----------

## VinzC

Having a tap0 interface is just not enough for QEMU/KVM. By default it tries to run a script, /etc/qemu-ifup, to configure the tap interface.  (See the documentation.) If you don't have such a script, add script=no to the -net tap argument list.

If you have no script for KVM to setup the tap interface when launched, you must set the interface up, then add its IP address and routes. If you want it to be bridged against your LAN card, just set it up, create a bridge and add it to the bridge.

If you want your KVM virtual machine to be NAT'ed, setup IP forwarding and configure IPTABLES with a POSTROUTING rule that MASQUERADEs outgoing traffic through your wired or wireless ethernet card.

Additionally you might have to make sure /dev/net/tun can be written to by the user account that runs KVM. I usually do that by adding my regular user account to a group, say vmadmin. I then edit /etc/udev/rules.d/50-udev.rules and change the line that says

```
KERNEL=="tun",          NAME="net/%k",  MODE="0660", OPTIONS+="ignore_remove"
```

 into 

```
KERNEL=="tun",          NAME="net/%k",  MODE="0660", GROUP="vmadmin", OPTIONS+="ignore_remove"
```

Hope this helps.

----------

## HuskyDog

Thanks for your reply.

Adding script=no didn't make any difference.

Your other solution seems to basically work (at least a quick chown /dev/net/tun fixed things).  But I was attempting to implement the apparently approved (and certainly more elegant) solution described at several places on the internet, including:

http://calamari.reverse-dns.net:980/cgi-bin/moin.cgi/FrequentlyAskedQuestions#head-2511814cb92c14dbe1480089c04f83c281117a86

and Miskik1's comment at the end of this section of the HOWTO

http://gentoo-wiki.com/HOWTO:_Qemu#Making_a_bridge

As I see it, this scheme basically involves making the tap device in advance and already owned by the relevant user so that no fiddling around with /dev/net/tun is required.  But, as I said, it doesn't seem to work.

----------

## VinzC

Using script=no implies the tap interfaces must be up and ready before Qemu is run.

I also forgot to say that you need to provide a user name to tunctl when you create the tap interfaces. Basically it's your regular user account, as Mistik1 explained.

That user becomes the owner the tap interface. So there are two possible ways.If you want to use Qemu graphical output to, say, check a bootable CDROM or run a virtual machine directly from the command line, then you need to pass your regular account to tunctl.

If you plan to use Qemu as a daemon and want to control it with VNC, then you can create a user account that you will make member of the vmadmin group, as I mentioned earlier. That user must also be the owner of tap interfaces.Note I don't like to use sudo to configure the network interfaces for Qemu. Hence I do all the tap stuff with a script that I run as root.

Both solutions above allow you to define tap interfaces in /etc/conf.d/net, the Gentoo way. I've tested Qemu in various ways and come to the conclusion that the ideal - maybe not most comfortable, it's a compromise - way is to create a user account that is dedicated to Qemu virtual machines; add it to a vmadmin group so that it can write to /dev/net/tun and launch Qemu with that user account in all circumstances, whether you're logged in with your regular account or running Qemu as a daemon. This has the main advantage to prevent you from editing your network configuration script each time you log on with a different account.

Create a udev rule as in my first post to automate the ACL on /dev/net/tun. You should then not need to chown/chmod manually. The only requirement is that your regular account must be member of the wheel group. Run either su - <vm-user> -c <qemu command> or sudo -u <vm-user> <qemu command>.

Sudo might fit best. At least it doesn't require root privileges.

----------

## HuskyDog

 *Quote:*   

> I also forgot to say that you need to provide a user name to tunctl when you create the tap interfaces.

 

Well, I'm already doing that, but it doesn't seem to make any difference.  That is the whole nub of my problem!  As I said in my initial post:

```
# tunctl -u my_user_name -t tap0

Set 'tap0' persistent and owned by uid 1000
```

So, unless someone else comes up with a solution to my basic problem of the above command not making any difference, then I will go with your "create a dedicated user and add it to the vmadmin group" scheme.

----------

## VinzC

I wasn't suggesting you to create a dedicated user right now, just explaining what I've done  :Smile: . So far, could you post your tap0 (ip addr show dev tap0) configuration, the results of ls -l /dev/net/tun and the results of id my_user_name?

EDIT: You could as well try once running KVM as root to check if you get such messages.

----------

## HuskyDog

```
# ip addr show dev tap0

6: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 500

    link/ether 00:ff:c9:00:34:11 brd ff:ff:ff:ff:ff:ff

    inet 192.168.0.1/24 brd 192.168.0.255 scope global tap0

    inet6 fe80::2ff:c9ff:fe00:3411/64 scope link

       valid_lft forever preferred_lft forever
```

```
# ls -l /dev/net/tun

crw-rw---- 1 root root 10, 200 Nov 17 09:54 /dev/net/tun
```

```
# id my_user_name

uid=1000(my_user_name) gid=100(users) groups=100(users),10(wheel),19(cdrom),80(cdrw),1002(qemu),1004(kvm)
```

Meanwhile, I think that I might have hit on a critical point.  Reading /usr/src/linux/Documentation/networking/tuntap.txt it says:

 *Quote:*   

>  Set permissions:
> 
>      e.g. chmod 0666 /dev/net/tun
> 
>      There's no harm in allowing the device to be accessible by non-root users,
> ...

 

Until now, I had assumed that the 'tunctl -u my_user_name -t tap0' command created tap0 in such a way that it was basically owned by me and my user could therefore access it without any need of further access to /dev/net/tun, and that the benefit of this scheme was that it maintained the security of /dev/net/tun.  But, perhaps this isn't true.  If I do the above chmod, then my virtual machine works, but only if I have previously issued the tunctl command.  Furthermore, despite allowing everyone read/write access to /dev/net/tun, I still need to be root to create the new tap interface, so perhaps this chmod has indeed not reduced the system security.

So, if the above is true then the correct fix to this problem is a patch to udev in order that the permissions of  /dev/net/tun default to 666 as described in the documentation.

----------

## VinzC

 *HuskyDog wrote:*   

> So, if the above is true then the correct fix to this problem is a patch to udev in order that the permissions of  /dev/net/tun default to 666 as described in the documentation.

 

Not exactly; that's the reason why I suggested you changed the above UDEV rule so that the user that launches QEMU/KVM has write access to /dev/net/tun through group vmadmin. You only need to tweak /etc/udev/rules.d/50-udev.rules and add the GROUP= clause with the right group name.

Note the name vmadmin is not mandatory, just create a group for all users who would need to run QEMU and triturate tap interfaces. That group will need to be added to /etc/udev/rules.d/50-udev.rules accordingly with access mode 660.

Tap interfaces need to be created with root privileges. That's also the reason the best Gentoo way is to define them in /etc/conf.d/net.

All you'll have to care for after you a) have UDEV rule the ACLs of /dev/net/tun and b) have Gentoo network config file take care for the creation of your virtual tap interfaces is to run the virtual machine with the selected virtual interfaces. Everything else will have been done automatically at boot.

----------

## sdauth

This finally resolved my issue.   :Cool: 

I added :

```
KERNEL=="tun",          NAME="net/%k",  MODE="0660", GROUP="kvm", OPTIONS+="ignore_remove"
```

to /etc/udev/rules.d/50-udev.rules

I used "kvm" since my user is already in kvm group, and I can finally start my VM with the tap device without needing root.

The wiki : https://wiki.gentoo.org/wiki/QEMU/Options#Networking

only says : "To successfully run VM you need permission for configure /dev/net/tun"

Now of course if you're experienced, it's an easy fix but it was confusing a little bit as I was afraid to manually chown /dev/net/tun. Well, thanks VinzC !

----------

## Hu

Another option would be to use tunctl -u user-who-runs-qemu.  You can arrange for the openrc network scripts to do this for you for the interface kvm01 by setting:

```
tuntap_kvm01=tap

tuntap_kvm01='-u user-who-runs-qemu'
```

Change the interface name as needed.  If you do this, you may also want to use config_kvm01, mac_kvm01, and modules_kvm01 to configure other aspects of the device.

Although your solution is not as comprehensive in configuration, it has the virtue of relying only on udev, so your approach works equally for systemd and openrc users.  Mine would require translation for a systemd user.

Regardless, please consider improving the Wiki to more explicitly describe at least one working solution.

----------

## sdauth

Thanks Hu, I will try that later again because I did try with :

```
tuntap_tap1="tap"

tunctl_tap1="-u sdauth"
```

in /etc/conf.d/net but /dev/net/tun was still owned by root:root even after a reboot.

Full conf :

```
modules="dhclient"

config_eth0="null"

config_br0="192.168.1.19/24"

routes_br0="default via 192.168.1.1"

bridge_br0="eth0 tap1"

rc_net_br0_need="net.eth0 net.tap1"

config_tap1="null"

tuntap_tap1="tap"

tunctl_tap1="-u sdauth"

iproute2_tap1="user root"

bridge_forward_delay_br0=0

bridge_hello_time_br0=1000

bridge_stp_state_br0=0
```

By the way, it was not my solution but VinzC's one, a bit old but hey still valid.   :Cool:   I'll see if I can add it to the wiki, I never did that before.

----------

## Hu

Do you have tunctl installed?  Last time I worked with this, that was required for the network script fragments I showed to work.  It is part of sys-apps/usermode-utilities, which most desktop users would otherwise not have installed.

I see now, you are right about VinzC.  Since you provided it in a code block as a ready-to-use sample, and I did not see such above, I attributed it to you.

----------

## sdauth

Indeed ! I was missing tunctl.

Nonetheless, it still doesn't work. /dev/net/tun is still owned by root:root

I also tried with "-g kvm" instead of "-u sdauth"

config_tap1="null"

tuntap_tap1="tap"

tunctl_tap1="-g kvm"

iproute2_tap1="user root"

also tried :

config_tap1="null"

tuntap_tap1="tap"

iproute2_tap1="group kvm"

Also, it seems tunctl is totally ignored at boot and iproute2 is somehow used to create the node.

I also tried to use tun as a module (It was compiled in previously) but no change.

For now, I give up.   :Embarassed: 

----------

## Hu

For me, /dev/net/tun remains root:root even when tunctl has successfully made a specific device accessible to my unprivileged user.  I am not aware of a way to test this other than to try starting the qemu process and let it try to access the device.

----------

## sdauth

You're right.

I experimented a little bit and went back to the previous working /etc/conf.d/net config without the custom udev rules (to set root:kvm on /dev/net/tun)

```
modules="dhclient"

config_eth0="null"

config_br0="192.168.1.19/24"

routes_br0="default via 192.168.1.1"

bridge_br0="eth0"

bridge_forward_delay_br0=0

bridge_hello_time_br0=1000

bridge_stp_state_br0=0   
```

So as you can see, here only br0 is created, then when I fire up a vm (as a user), qemu automatically create a tap device without requesting any root password for /dev/net/tun, which indeed stays as root:root, I don't even need to have tunctl installed for this to work.

```
crw-rw-rw- 1 root root 10, 200 25 mai   09:52 /dev/net/tun
```

In my /etc/qemu/bridge.conf (-rw-r-----   1 root kvm   472 25 mai   09:39 bridge.conf)

I have :

```
allow br0
```

which allows me to add devices to br0.

The network part of the qemu command line is :

```
-net nic,macaddr="$macaddr" -net bridge,br=br0
```

To summarize, the issue seems that if I create tap* devices upfront in /etc/conf.d/net, then for some reason, qemu cannot access them. (unless I use the udev "trick" to set owner root:kvm on /dev/net/tun of course)

Here is the network part of the qemu command line used :

```
-net nic,macaddr="$macaddr" -net tap,ifname=tap1,script=no,downscript=no
```

I also tried :

```
-device e1000,netdev=tap1,macaddr="$macaddr" -netdev tap,id=lan,ifname=tap1,script=no,downscript=no
```

----------

## sdauth

Since I was almost certain the issue was caused by iproute2, I checked again the conf and noticed one last thing I hadn't tried yet.

config_tap1="null"

tuntap_tap1="tap"

iproute2_tap1="user sdauth group kvm"

Bingo. With these iproute2 options passed to the tap, qemu doesn't complain anymore and I can start my vm with my tap1 device without sudo.   :Smile:  (also, tunctl is not needed, neither the udev trick)

network part of qemu command line (here with tap1 device as defined in /etc/conf.d/net)

```
-net nic,macaddr="$macaddr" -net tap,ifname=tap1,script=no,downscript=no
```

I guess the benefit of using tap instead of plain br0 (and qemu-bridge-helper) is that it allows you to define custom option like, for example, MAC addresses for each tap in /etc/conf.d/net in a more unified way. And to avoid to have them in the scripts I use to launch my VMs for example (so no need to use macaddr option on qemu command line), it is much cleaner to have them in one place.

EDIT : Well, if you don't set the macaddr on qemu command line, then qemu creates a new one for the VM.. instead of using one set in mac_tap*

So below example is valid, the MAC address is set for the tap* device created but qemu doesn't use the MAC unless you pass it to the qemu command line.

I will end my experimentation here since the initial issue is resolved and this one is rather minor.

```
modules="dhclient"

config_eth0="null"

config_br0="192.168.1.19/24"

routes_br0="default via 192.168.1.1"

bridge_br0="eth0 tap1 tap2"

rc_net_br0_need="net.eth0 net.tap1 net.tap2"

mac_br0="mac address from eth0"

config_tap1="null"

tuntap_tap1="tap"

iproute2_tap1="user sdauth group kvm"

mac_tap1="mac for tap1 device"

config_tap2="null"

tuntap_tap2="tap"

iproute2_tap2="user sdauth group kvm"

mac_tap2="mac for tap2 device"

# [etc..]

bridge_forward_delay_br0=0

bridge_hello_time_br0=1000

bridge_stp_state_br0=0
```

----------

