rootless-containers / slirp4netns

User-mode networking for unprivileged network namespaces
GNU General Public License v2.0
729 stars 82 forks source link

Q: Connect rootless slirp4netns interface to a bridge / Open vSwitch (by root) #252

Closed ben-tiky closed 3 years ago

ben-tiky commented 3 years ago

Hi Everybody,

I moved from LXC to Podman on a VPS and it works great. Thank you for amazing slirp4netns.

On VPS the networking requirements are simple, I publish Podman pod to 127.0.0.1:8080 and then I can use iptables/nftables PREROUTING to send traffic from public IP port 80 to 127.0.0.1:8080.

On physical server the requirements are more complicated since the physical server is connected to a trunk port and has LXC containers connected to different VLANs. I'd like to kindly ask you if you can help me figure out how to do that with slirp4netns (Podman rootless containers).

In LXC, I can configure a container with lxc.net.0.link = mybridge123 and then I start rootless (aka unprivileged) LXC container and the container interface is added to mybridge123. In logs I can see for example ovs-vsctl add-port mybridge123 vethVGME73 which I believe is done by lxc-net.service so LXC is not completely daemonless. Later I can execute sudo ovs-vsctl set port vethVGME73 tag=100 and the interface will be tagged by a VLAN tag.

Same thing works with a normal Linux bridge. lxc-net.service will make sure that container running under non-root user has interface in that bridge (that is done by lxc-net.service which means by root).

Could you please tell me is it possible to create and start rootless (without sudo) Podman pod and then execute sudo something that will move/recreate slirp4netns interface to that bridge? If I know how to do this then I can figure out the rest (Open vSwitch, VLAN tagging...).

Thank you.

Ben

AkihiroSuda commented 3 years ago
$ podman run --net=none -d IMAGE
$ sudo ln -s /proc/CONTAINERPID/ns/net /var/run/netns/NSNAME
$ sudo ip link set VETHNAME netns NSNAME

This may work for you (untested)

ben-tiky commented 3 years ago

Thank you very much @AkihiroSuda for the quick answer. This is what I've just tried:

sudo -su otheruser podman run --net=none -d nginx
Completed short name "nginx" with unqualified-search registries (origin: /etc/containers/registries.conf)
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
Copying blob a076a628af6f done
Copying blob f72584a26f32 done
Copying blob 0732ab25fa22 done
Copying blob 7125e4df9063 done
Copying blob d7f36f6fe38f done
Copying config f6d0b4767a done
Writing manifest to image destination
Storing signatures
5fd4a263c9d077d47a2d3d49a267f630c42f6dfe9ba86f837be3473190e1c80e
sudo -su otheruser podman ps
ONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS             PORTS   NAMES
5fd4a263c9d0  docker.io/library/nginx:latest  nginx -g daemon o...  29 seconds ago  Up 27 seconds ago          optimistic_ishizaka
sudo -su otheruser podman inspect -f '{{.State.Pid}}' 5fd4a263c9d0
11455
sudo ls -l /proc/11455/ns/net
lrwxrwxrwx 1 otheruser otheruser 0 Jan 26 19:22 /proc/11455/ns/net -> 'net:[4026532599]'
sudo mkdir -v /var/run/netns
mkdir: created directory '/var/run/netns'
sudo ln -sfTv /proc/11455/ns/net /var/run/netns/5fd4a263c9d0
'/var/run/netns/5fd4a263c9d0' -> '/proc/11455/ns/net'
ip netns list
5fd4a263c9d0
sudo ip netns exec 5fd4a263c9d0 ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

The only problem is the last command ip link set VETHNAME since there is no interface to set. Podman didn't add a new interface. Would you be so kind and tell me, should I use something like ip link add to create the interface?

Thank you.

Ben

AkihiroSuda commented 3 years ago

Yes, for net=none, you need to create and manage veth entirely by yourself. (Slirp4netns is not involved at all)

ben-tiky commented 3 years ago

Again thank you very much @AkihiroSuda for the quick answer.

I tried:

sudo ip link set veth12345B netns 5fd4a263c9d0

* add it into bridge
    * following is Open vSwitch specific, `ip link set veth12345A master bridgename` should work for Linux Bridge (I didn't test it)
``` sh
sudo ovs-vsctl add-port bridgename veth12345A

sudo ip link set dev veth12345A up

sudo ip netns exec 5fd4a263c9d0 ip addr add 172.16.0.55/24 dev veth12345B

``` sh
sudo ip netns exec 5fd4a263c9d0 ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
39: veth12345B@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 8a:74:40:39:12:6e brd ff:ff:ff:ff:ff:ff link-netnsid 0
sudo ip netns exec 5fd4a263c9d0 ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
39: veth12345B@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 8a:74:40:39:12:6e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.16.0.55/24 scope global veth12345B
       valid_lft forever preferred_lft forever
    inet6 fe80::8874:40ff:fe39:126e/64 scope link
       valid_lft forever preferred_lft forever

Which means it's working ;-). Thank you!