evilsocket / opensnitch

OpenSnitch is a GNU/Linux interactive application firewall inspired by Little Snitch.
GNU General Public License v3.0
10.81k stars 505 forks source link

docker as root not handled #385

Closed ReleaseStandard closed 3 years ago

ReleaseStandard commented 3 years ago

Hi thanks first i would like thanks you for this amazing study tool (toy?).

Describe the bug This is more a feature request/open question. When using docker as root packets do not use INPUT/OUTPUT chains. With iptables they use the FORWARD chains of filter table. So they are not handled by opensnitch. Rootless mode of docker is well handled.

To Reproduce

sudo docker run --rm -ti ubuntu bash -c "<>/dev/tcp/github.com/443"

Expected: TCP is maid without notice user.

sudo bash -c "<>/dev/tcp/github.com/443"

Expected: user is noticed about the connexion (unless you've allowed github.com).

Steps to reproduce the behavior:

  1. Install docker as root.
  2. From a terminal run : sudo docker run --rm -ti ubuntu bash -c "<>/dev/tcp/github.com/443"

OS (please complete the following information):

ReleaseStandard commented 3 years ago

We can track new connexions with following rules (from documentation):

iptables -t mangle -I FORWARD -m conntrack --ctstate NEW -j LOG --log-prefix "[opensnitchtest]"
iptables -t mangle -I FORWARD -m conntrack --ctstate NEW,RELATED -j NFQUEUE --queue-num 0 --queue-bypass

Informations on processes that run in docker container are avaliable in /proc/fd (on the host running opensnitch).

gustavo-iniguez-goya commented 3 years ago

Hi @ReleaseStandard , thank you for the report!

I'll take a look at this again, but I'm afraid that it's the same problem than #378

When we receive a new connection we only know the src port + src ip + dst ip + dst port. In order to get the inode, we ask the kernel for it using the network parameters. For example:

[2021-03-29 15:14:51]  DBG  new connection udp => 38424:172.17.0.4 -> 8.8.8.8:53 uid: 4294967295
[2021-03-29 15:14:51]  DBG  netlink socket error: Warning, no message nor error from netlink - 38424:172.17.0.4 -> 8.8.8.8:53

If the kernel doesn't answer with the inode, we parse /proc/net/*:

[2021-03-29 15:14:51]  DBG  Searching for udp6 netstat entry instead of udp
[2021-03-29 15:14:51]  DBG  <== no inodes found, applying default action.

And if it either doesn't exist there, we apply the default action, as the log shows.

We need to know the inode, in order to get the PID from /proc/. Why the kernel doesn't dump the inode in this case is probably due to the connection being made from a namespace/container/cgroup/etc.

gustavo-iniguez-goya commented 3 years ago

using auditd to monitor connections and processes detects these executions from inside containers:

type=SYSCALL msg=audit(1617061842.133:12436972): arch=c000003e syscall=42 success=yes exit=0 a0=3 a1=7f6f37fbe914 a2=10 a3=fffffffffffffe55 items=0 ppid=1253 pid=1256 auid=4294967295 uid=100 gid=65534 euid=100 suid=100 fsuid=100 egid=65534 sgid=65534 fsgid=65534 tty=pts0 ses=4294967295 comm="http" exe="/usr/lib/apt/methods/http" subj=system_u:system_r:initrc_t:s0 key="opensnitchd"ARCH=x86_64 SYSCALL=connect AUID="unset" UID="uuidd" GID="nogroup" EUID="uuidd" SUID="uuidd" FSUID="uuidd" EGID="nogroup" SGID="nogroup" FSGID="nogroup"
type=SOCKADDR msg=audit(1617061842.133:12436972): saddr=02000035080808080000000000000000SADDR={ saddr_fam=inet laddr=8.8.8.8 lport=53 }
type=PROCTITLE msg=audit(1617061842.133:12436972): proctitle="/usr/lib/apt/methods/http"
type=EOE msg=audit(1617061842.133:12436972):

and the connection can be redirected to us, but we still need the inode to link a connection to a PID. That's the missing part. or the {source port + source ip + dest ip + dest port}, that many times is also missing.

ReleaseStandard commented 3 years ago

You're right of course, docker use runc as backend. The file network_linux use netlink lib. And here is the current implementation. Switching to the other issue lol

raboof commented 3 years ago

If we can't find the process, perhaps it might already be helpful to find the name of the container that creates the connection? (might take a larger refactor, of course - I'm not familiar with the code yet ;) )

gustavo-iniguez-goya commented 3 years ago

I've just found where these connections are reported. They're written to /proc/$PID/net/{tcp,udp,...}

let me do some tests.

ReleaseStandard commented 3 years ago

Yeah that seem to be the best option unless you want to run into netfilter.

But if we can't get pid of connexion parsing /proc/*/net/{stuff} can produce overhead. Maybe restrict processes search to thoses which are not in the current network namespace.

Good luck men

gustavo-iniguez-goya commented 3 years ago

yeah, as a workaround we could look there, but it's basically the same problem than #343 . I hope this be fixed when we add eBPF as interception method.

gustavo-iniguez-goya commented 3 years ago

Working with latest changes. We still need to improve it.... but it's a good start. Edited: screenshort deleted, wrong screenshot.

raboof commented 3 years ago

very cool!

gustavo-iniguez-goya commented 3 years ago

wop, I added a wrong screenshot. Here's the good one, working as expected.

image

As @ReleaseStandard said, we need a rule to intercept FORWARD connections.

gustavo-iniguez-goya commented 3 years ago

Ok, this issue is partially fixed with the latest release: https://github.com/evilsocket/opensnitch/releases/tag/v1.4.0-rc.2

The FORWARD rule is still needed. I didn't add it as part of the ebpf setup because I've ran into some problems because of intercepting forwarded connections, mainly popups of connections that are not part of the system.

If you want this feature, you need to select in the Preferences->Nodes->Process monitor method: ebpf, and add the following rule to /etc/opensnitchd/system-fw.json:

        {
            "Rule": {
                "Enabled": true,
                "Description": "",
                "Table": "mangle",
                "Chain": "FORWARD",
                "Parameters": "-m conntrack --ctstate NEW",
                "Target": "NFQUEUE",
                "TargetParameters": "--queue-num 0 --queue-bypass"
            }
        }
gustavo-iniguez-goya commented 3 years ago

fixed in v.1.4.0