rootless-containers / slirp4netns

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

Filtering Connections with iptables requires root? #265

Open KCSesh opened 3 years ago

KCSesh commented 3 years ago

I have followed the example: https://github.com/rootless-containers/slirp4netns/blob/master/slirp4netns.1.md#example

Terminal 1:

(host)$ unshare --user --map-root-user --net --mount
(namespace)$ echo $$ > /tmp/pid

Terminal 2:

(host)$ slirp4netns --configure --mtu=65520 $(cat /tmp/pid) tap0
starting slirp, MTU=65520

Terminal 1:

(namespace)$ echo "nameserver 10.0.2.3" > /tmp/resolv.conf
(namespace)$ mount --bind /tmp/resolv.conf /etc/resolv.conf
(namespace)$ curl https://example.com
<works>

But then when I add a new step, I get a permission denied error when attempting to setup Filtering connections with iptables.

Terminal 3:

(host) nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n
(namespace)$root@tegra-ubuntu:~# iptables --list
iptables v1.6.1: can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
(namespace)$root@tegra-ubuntu:~# iptables -A OUTPUT -d 10.0.2.3 -p udp --dport 53 -j ACCEPT
iptables v1.6.1: can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.

So here is my error in the namespace:

iptables v1.6.1: can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.

Is this a kernel issue? Or is something else wrong?

root@tegra-ubuntu:~# uname -mrs
Linux 4.9.140 aarch64
<user>@tegra-ubuntu:~$ slirp4netns --version
slirp4netns version 1.1.9
commit: 4e37ea557562e0d7a64dc636eff156f64927335e
libslirp: 4.4.0
SLIRP_CONFIG_VERSION_MAX: 3
libseccomp: 2.3.3
AkihiroSuda commented 3 years ago

modprobe iptable_filter (requires real root)

KCSesh commented 3 years ago

I am trying to understand the filtering connections section. How can I enter the namespace with real root? There is no context around how the example creates the namespace: https://github.com/rootless-containers/slirp4netns/blob/master/slirp4netns.1.md#filtering-connections

My goal from a container perspective is to enable host loopback so my container can communicate to the host. However, I only want to allow the container to be able to connect to a specific port on the host machine.

So for that I need iptable rules, and I am trying to understand a few things:

Do I need root => seems yes.

Trying to understand where the iptables rules can be executed. Do I need to do it in the namespace with root? Or can I do it on the host machine? And how do I enter the namespace with root?

I have tried this:

<user>@tegra-ubuntu:~$ sudo nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n
nobody@tegra-ubuntu:~$ iptables --list
iptables v1.6.1: can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.

If there is a way to do this, which I am hoping there is. Does it work for running multiple containers? Each having a specific port they can connect to.

Also thanks for the help so far @AkihiroSuda!

AkihiroSuda commented 3 years ago

You don't need root after modprobbing

KCSesh commented 3 years ago

I see, I misunderstood you were telling me to unload the iptable_filter module.

I tried doing this, and seems I am still seeing an issue.

I can't modprobe iptable_filter due to:

(host) <user>@tegra-ubuntu:~$ sudo modprobe -r iptable_filter
modprobe: FATAL: Module iptable_filter is in use.

So I tried a few methods, but this one worked:

(host) <user>@tegra-ubuntu:~$ cat /etc/modprobe.d/netfilter.conf
alias iptable_filter off
(host) <user>@tegra-ubuntu:~$ sudo reboot

On next startup:

(host) <user>@tegra-ubuntu:~$ lsmod | grep iptable_filter
(host) <user>@tegra-ubuntu:~$

Another verification:

(host) <user>@tegra-ubuntu:~$ sudo iptables --list
iptables v1.6.1: can't initialize iptables table `filter': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.

Now the test:

(host) <user>@tegra-ubuntu:~$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n
(namespace) root@tegra-ubuntu:~# iptables -A OUTPUT -d 10.0.2.3 -p udp --dport 53 -j ACCEPT
iptables v1.6.1: can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.

Seems I am still seeing a permission denied error.

Let me know what else I can try.

Is it possible to create the iptable rule for my user network namespace with root? I might be able to create a workaround for this. Please let me know how if it possible.

estesp commented 3 years ago

Just as a comparison, I can get that example to work on kernel 5.4.0 with iptables 1.8.4 with one modification; running iptables commands once nsentered into the namespace(s) gets a file perm error on /run/xtables.lock and I have to touch and chmod 0666 that file for the unprivileged/remapped root to be able to use the iptables lock. After that the rest of the example commands work properly. Seemingly related: https://patchwork.ozlabs.org/project/netdev/patch/2ef2150d-7149-cf39-0ea8-78edfc2c8d92@virtuozzo.com/

KCSesh commented 3 years ago

Well I tried upgrading to 1.8.4 iptables on Ubuntu 18.04, 4.9.140 and still see an issue:

(namespace) root@tegra-ubuntu:~# iptables -A OUTPUT -d 10.0.2.3 -p udp --dport 53 -j ACCEPT
iptables v1.8.4 (legacy): can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.

Even though on the host I don't even have iptable_filter loaded:

(host) user1@tegra-ubuntu:~$ sudo iptables --list
iptables v1.8.4 (legacy): can't initialize iptables table `filter': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.
AkihiroSuda commented 3 years ago

If you can't even run sudo iptables on the host, your issue is not relevant to this repo. Stackoverflow would be better place to ask your questions.

KCSesh commented 3 years ago

@AkihiroSuda I can run iptables on the host with sudo. I was showing that if I remove the module iptable_filter as per your suggestion, I am still getting an issue in the network namespace. If I load the module, sudo iptables --list works.

Right now the only way I can run iptables is on the host with sudo. It seems this could have a kernel dependency would be my guess? Since it is working for @estesp.

By updating my iptables to 1.8.4 I also see the /run/xtables.lock error, but when I fix it chmod 0666 I get the error shown above.

I attempted multiple versions of iptables just as a sanity check.

1.6.2/1.8.2/1.8.4