2

I am building a system with a read-only rootfs.

This rootfs is shared between the host and created containers.

The host cannot have any network related service or file and that means I cannot bridge the host connection.

I am currently using an USB network adapter.

How can I start this device and the network service inside the container only?

Any container can have new RW mount points for /etc /var and so on, that way, any file needed will be reachable in another partition. But the host continues to be RO and with limited files.

2 Answers2

4

Forget the network card as a specific hardware. Just consider you have a network interface and it has to be moved to a container. This is not USB or PCI pass-through. Let's call it interface pass-through and it's specifically handled by the network namespace logic using for example ip link:

netns NETNSNAME | PID

move the device to the network namespace associated with name NETNSNAME or process PID. Some devices are not allowed to change network namespace: loopback, bridge, ppp, wireless. These are network namespace local devices. In such case ip tool will return "Invalid argument" error. It is possible to find out if device is local to a single network namespace by checking netns-local flag in the output of the ethtool:

ethtool -k DEVICE

To change network namespace for wireless devices the iw tool can be used. But it allows to change network namespace only for physical devices and by process PID.

The interface has to appear initially on the host, but you can move it to the container. There's no option to have it directly appear in a container when plugged (of course at container start, with a specific configuration for the container, the interface can be moved, see later), but it's probably scriptable with udev. Moreover, the kernel being unique across host and containers, the host, even if not using network at all, must of course have all required network options compiled-in and is still in charge of loading relevant kernel modules if needed (it's usually transparently done).

So if in the end your card is called eth0 on the host and is really ethernet (not wireless), this command will move it to the target namespace:

ip link set eth0 netns NETNSNAME

Where NETNSNAME can be either a pid of a process in the target network namespace or a network namespace "mounted" and handled by ip netns add NETNSNAME as described above.

For two common container technology, LXC and Docker, here's how to replace NETNSNAME with a target container named containername:

LXC:

ip link set eth0 netns $(lxc-info -H -p -n containername)

Docker:

ip link set eth0 netns $(docker inspect --format '{{.State.Pid}}' containername)

For wireless the (not very well documented) command would be if there's only one wireless interface, then clearly associated with phy0:

iw phy phy0 set netns $(lxc-info -H -p -n containername)

But this will work only if the driver supports it, displaying this:

# iw phy0 info|grep netns
     * set_wiphy_netns

This should probably not be done manually with the commands above, but with the specific container's configuration (LXC, Docker...). Eg, for LXC 3.0 (syntax changed from LXC 2.x) the configuration file would include lines like:

lxc.net.1.type = phys
lxc.net.1.link = eth0

Same config will handle ethernet or wireless.

and whenever the container is started, the interface would be swallowed by the container. When the container (more precisely its network namespace) stops, the interface is returned to the host (there's no way to return it to an other container directly).

Wireguard describes some use cases.

A.B
  • 36,364
  • 2
  • 73
  • 118
2

To, elaborate on frostschutz's comment.

  • You could allow the container access to the USB device with or without --privileged mode by following the instruction here: Instructions. (However as this is a network device it most likely needs drivers)

  • If you are using USB pass-through, and can see the device inside the container, it should just be a matter of doing a modprobe of that device's kernel module inside the container, and restarting the container. Then of course setting up the network.

  • Information found in the discussion on the following page should help you, when adapted to your use case. Page (Keep in mind that the last statement about it not showing up on fresh boot is because it was was not yet setup to do so, you should have it from there though as the drivers should now be working.)