Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
EBPFSnitch: An eBPF based Linux Application Firewall (github.com/harporoeder)
290 points by harporoeder on March 14, 2021 | hide | past | favorite | 70 comments


If you're interested in this, you may be interested in this as well: https://github.com/evilsocket/opensnitch

It has a GUI interface as well.


From https://github.com/evilsocket/opensnitch/wiki/Why-OpenSnitch...:

> Why OpenSnitch does not intercept application XXX

>

> tl;dr

>

> - because we don't use eBPF.

> - a process is opening connections too fast (nmap for example, firefox sometimes...).

> - the system has a high load and we're unable to find the process in time.

> ...


They're both pretty bad for something so simple. Tons of dependencies, complexity that shouldn't be there and perplexing code.

evilsocket/opensnitch is worse but EBPFSnitch could also be a lot better.


If they're both "pretty bad for something so simple"... then it seems like a classic example of a problem that you could just release a solution for; then there would be a non-sucky solution available!

Unless it's actually not that simple?

You could at least make constructive criticism instead of just dismissively saying that all solutions suck. ("Tons of dependencies", "complexity", and "perplexing" are not actionable criticisms... they're highly subjective opinions.)


> Unless it's actually not that simple?

Recognising that given sufficient domain knowledge you could minimise and optimise dependencies and actually having that domain knowledge for this specific field are not the same thing. For the former, you just need to be a professional. For the latter, you need to be in luck for this specific subject.

You don't fix that by being snarky. Ironic, because in the last paragraph you do ask for constructive criticism! The least you could do is materially reciprocate in doing so.


I don't know anything about this project, but it's okay to criticize large dependency trees and complexity. It sounds like you're looking for suggestions on how to fix that or the other. Neither of those things is trivially fixable, they're pretty fundamental problems. Sometimes a rewrite can do it.


evilsocket/OpenSnitch is one of the cleaner code bases I have seen, especially for the functionality it implements. What other complexity are you alluding to?


This looks spectacular! Finally! This is functionality I've desperately wanted on Linux desktop. Link that up with with some of the SELinux on-demand tools and you have a plausible way to run untrusted binaries without the overhead of completely containerizing them up front.


Be careful with that one, this isn't as capable as the HIDS solutions available on Windows - it's not going to do things like detect exfiltration using other executables or modification of other files on your system.

For example, if you allowed curl or Firefox, another executable can simply call one of them and send/receive whatever data they need to. It also can't do things like filter ptrace calls which could easily be used to modify another process to perform exfiltration or just spawn another thread and inject a whole new dynamic library to them, a common practice to bypass detection on Windows.


Windows app firewalls had similar problems, most common was to use explorer.exe


Just block explorer.exe with windows firewall - if really needed just enable out going access for internal subnet only.

There is not need for explorer to access internet!

I only allow windows defender, firefox and chrome to access internet in my home computer setup all other apps are blocked unless truly needed.

If you block svchost.exe from internet access with windows firewall, it will block the windows update. Enable it once in a while to allow the windows update to go thru when you feel the need.


How does Windows prevent this type of bypass? It seems extremely hard to prevent in an unsandboxed environment.


Windows itself does not, 3rd party firewall/HIDS software (ZoneAlarm, Outpost, etc) for Windows has done this by intercepting APIs to do things like call executables with internet access, OpenProcess calls, raw disk IO, registry writes to startup entries, etc.


I'm not sure what they are talking about, but windows comes with a built-in sandbox now. Adds a little bit of overhead, but besides that works very well.


I guess one might try to check the path through the process tree to see if a blacklisted application is the parent (or gp, ggp, etc.) of the process trying to communicate with the outside world.


I considered that but IIRC browsers like firefox will accept to load an URL without creating a new child process.

For instance if I type "firefox 'http://google.com'" in my terminal my already-running firefox instance loads the URL in a new tab, so I assume that some kind of IPC is used behind the scenes to ask the main instance to load the URL. Of course that's harder to exploit nefariously than spawning wget from the same process but when there's a will there's a way...


without the overhead of completely containerizing them up front.

What overhead? `docker run --rm -it -v $PWD/untrustedprogram:/untrustedprogram:ro ubuntu:latest`, done. Use x11docker if needed.


> `docker run --rm -it -v $PWD/untrustedprogram:/untrustedprogram:ro ubuntu:latest`

Not sure if running a program as root in a container is the best approach to "fully sandbox" - depends on what the goal is, obviously.


This isn't upvoted enough. I use that trick verbatim to just wrap a container's execution environment around my $PWD. It's useful way beyond just isolating a program.


I've used `alias shit='docker run --rm -it --entrypoint /bin/sh -v $PWD:/workdir -w /workdir'` for a long time. This way, whenever I need, I can just run `shit alpine` or `shit ubuntu` or whatever.


I have the same as dri (docker run interactive) and dri_cwd so current directory only mounts intentionally (with dri_cwd)


The overhead of keeping a separate copy of the OS, presumably.


Wouldn’t you need something like gvisor and or running under a different user or podman to make this really safe? If you don’t trust the binary they can still just break out the container.


Container escape isn't supposed to be that easy these days, but yes there is a tradeoff between security and convenience and performance. I was objecting to the claim of overhead in using a container; if you need more protection than you can get on the same kernel then you'll pay for it in virtualization costs (granted, that's not super high anymore either).


That's a lot of overhead if you don't already have docker installed, don't have the the ubuntu image installed, etc.


So Docker is a zero cost solution now?


What do you mean by "SELinux on-demand tools"?


I think AppArmor would be a better use-case for that.

With it you can write a security profile containing a rule like:

   network tcp src 192.168.1.1:80 dst 170.1.1.0:80
Networking access is just the start, you can restrict many other stuff, like access to dbus, files, signals, etc.


What overhead are you worried about?


firejail?


I don't see any port-based firewalling options in the firejail documentation from a quick look. So I'm not sure if firejail helps the same use case as EBPFSnitch.


It can isolate applications into separate network namespace (i.e. no access to host services) with or without internet access and also load separate netfilter rules. No convenience arguments for port filtering though.


For those who're unaware.

ebpf: extended berkeley packet filter

Unfortunately, even the website https://ebpf.io/what-is-ebpf doesn't mention this. Interestingly, I was unable to find the words packet filter used together as well or firewall. I might be wrong.

I know that if you know what it is you'd know but trying to explain that to my partner here just glancing at my screen wasn't easy.


The ebpf site doesn’t mention that because expanding the abbreviation is not helpful for understanding ebpf. The name is representative the past of ebpf, not its present use or future.


That’s not an excuse to not explain wtf the name means. It’s literally one of the first questions that always comes up when I explain ebpf to people.


Does literally everything that uses it need to expand the acronym? Even if it confuses people or gives them the false impression of what it actually does? "This product uses eBPF, or extended Berkeley Packet Filter. But forget all of that because it has no relation with Berkeley, and it doesn't filter packets."

In a sense eBPF as just some letters being a name is a better name than "extended Berkeley Packet Filter", just like DPRK is a better name than "Democratic People's Republic of Korea", since 75% of the words in the expanded acronym aren't even relevant or true.


Try reading the thread before you reply. It’s a complaint about the ebpf site itself not explaining what ebpf is. It has nothing to do with things that use ebpf.

> https://ebpf.io/what-is-ebpf


I really like eBPF, and I even know what the acronym stands for, but I'm still completely incapable of reading it as anything other than "e band pass filter"


Why does this need nf_queue? Wouldn't it be sufficient to directly filter the connect syscalls using eBPF?

Dropping packets using netfilter makes many applications wait for a timeout. I prefer reject to filter unwanted outbound connections so that applications don't wait.


This uses NFQUEUE to get real-time userspace access to the ability to decide which connections to allow. NFQUEUE users must return a verdict on the packet (skb? I don't recall) before the packet continues to flow through the system. Using seccomp you don't get the opportunity to pass that up to a user to decide which action to take. Using other eBPF consumers are similar (since it represents a risk).


only problem is that you can’t get the process ID for inbound packets like FreeBSD can, for that still remains Linux’s weakest feature.

— The said feature is critical to proper DEFAULT-DENY firewall configuration/modeling.


I have not attempted it but I believe this can be accomplished with eBPF https://elixir.bootlin.com/linux/v4.0/source/include/linux/s...


I don’t see a single parameter of the process ID.


Well yes you don't get it with a parameter you get it with this helper function while in those contexts `bpf_get_current_pid_tgid`.

Edit to provide link: https://elixir.bootlin.com/linux/v4.6/source/samples/bpf/bpf...


Using same bootlin search engine using your link, function nor variable not found.

Furthermore, the process ID is not yet identified at early inbound stage of EBPD. We would be talking about being past the pre-inbound stage, post-table-lookup stage, and specifically just during the input-to-user land stage.


Could you elaborate why that's critical to have?


IRL, we are unable to force systemd NOT to use any network ports for security reason due to absence of Linux firewall ability to deal with this process ID on inbound packets.

Hence, OpenRC enters the picture instead just to ensure that network port is not being used.

Also, premise of the DEFAULT-DENY firewall modeling is to pinhole open the port(s) on a per-process (or per-parent-process group) basis.


When I tested out eBPF a couple weeks ago I immediately had LittleSnitch in mind! Great to see that someone had the same idea and also the time to make it happen.

There's much more that can be done as well, I really highly recommend taking a look at eBPF!


This is awesome. I can't wait to dig into it. I was contemplating creating creating the same thing roughly. Maybe I can now leverage this instead :-)


Reminds me of good old Kerio Personal Firewall on Windows back in the 90s. If the UI gets some more love, I see ebpfsnitch take off like a rocket :)


On Windows, Malwarebytes (now BiniSoft) still maintains a decent free product called Windows Firewall Control that works in a similar way. It augments the existing firewall.

https://www.binisoft.org/wfc


WFC is an excellent Windows based firewall.

It also has the option to see the location of the executable trying to access the web and to also upload a hash of the file to VirusTotal.

I have been using this back before when it was a paid program (I think it was only $15 for lifetime use) and before it was purchased by MalwareBytes.

I no longer use any Windows computers but I install it on all my friends and families Windows PC’s.

I really wish there was something similar for Linux.


We are building the Portmaster, which can do some of these things already. Currently looking for testers: https://safing.io/portmaster/


> Reminds me of good old Kerio Personal Firewall on Windows back in the 90s.

That was my first thought as well. Back then Kerio Personal Firewall was a godsend, and seeing live how much software (which on windows was 99.9% closed) was attempting to phone home behind the user, became an eye opener to many of us.


If you'd like to try a modern version of that - we are looking for testers: https://safing.io/portmaster/


Doing that on my Debian rolling machine just now.

(Linux 5.7.0-1-amd64 #1 SMP Debian 5.7.6-1 (2020-06-24)

It installed flawlessly after satisfying the libnetfilter-queue1 dependency, currently I'm playing with it, I like the granularity that allows blocking/allowing different domains accesses from within a process, such as for example a tab in Firefox. I'm curious to test it in the next days with Windows closed software run under WINE to see what they do under the hood. So far it seems really well made, I believe it would deserve a full HN article.


This is very cool. Something like this can be a full blown commercial product.

>The control interface is implemented in Python 3 utilizing Qt5

I would recommend moving away from this and instead run the controls using a web interface. A small django/flask/fastapi app (maybe even running through docker).

U can see how that could run on a raspberry Pi and be accessible on the network through the browser.


This is pretty much what we are doing with the Portmaster: https://safing.io/portmaster/


Transmission the torrent daemon handles this nicely. Multiple frontends including gtk, cli and web.


Thanks for this, I was using something similar called Opensnitch, which is unfortunately buggy and not as capable as Little Snitch.


Hey, security guy here that has worked on something like this for about 2 years. This is cool but has some vulnerabilities upon a brief 10min code review. I'll see if I can circle back in about 2 weeks and make a list of what vulnerabilities EBPFSnitch has.


When you say vulnerabilities what do you mean? RCE? Privesc? Software can bypass the firewall?

Also, based on your recent HN comments you seem to have claimed to find vulns in several projects, but to date have provided no proof of such claims, so I'll have to admit I'm a little skeptical.


Software that can bypass the firewall for certain, and a possible local privesc (I don't want to promise the LPE yet, I've only looked for 10min). Some skepticism is understandable. I've followed up on a few of the replies here outside of HN (such as the Guix project, I found a root LPE they will be releasing a fix for in the coming weeks). For 10 years or so I've not disclosed any vulnerabilities I found. Publicly unverifiable claims are necessary in security, if I were to release the POC before Guix (for instance) can patch it it'll affect their users.


If you publish your findings somewhere, I'd love to read what you have found! We are also building a FOSS application firewall for Linux and I would like to see what problems you have found and how we are doing in that regard. Ref: https://safing.io/portmaster/


Hey there. I did a second 10 minute code review on Portmaster. First I want to say, well done on your modular source tree. It made it very easy for me to go through your open source project. Second, Portmaster is more vulnerable than EBPFSnitch. There's a firewall bypass like EBPFSnitch and a possible auth bypass in the API. I need to verify if the auth bypass is exploitable. A blog post sounds interesting but I'd need to coordinate disclosure with you so your end users aren't affected. I'll circle back in an email thread, expect it in ~1mo.


Wow, thank you for looking into it! I am very much looking forward to your email.


I get the point of it, but I think it's a distraction from the solutions we really need. The whole idea of app firewalls is "do/don't let an arbitrary network communication happen unless I know about it". The problem is, what if what you allow still involves an attacker? Say you allow some network connection from application A to site Z using protocols B,C. And say that you even inspect the connection using DLP. There will come a point where the attacker will position themselves to appear exactly like legitimate traffic.

Ultimately, all firewalls are just a very poor hack around a complex problem. The best solution to the problem is to ensure the connection is genuine and that the data being passed is genuine, and you can't do that with an arbitrary monitoring program. You need strong end to end authentication, authorization, and integrity, and sometimes also privacy. But we don't have the tools to do that right now because the protocols were designed for a different time.

Take DLP for example. Almost every major company in the world is starting to implement traffic inspection, because how the hell else are you going to ensure security of your IP with 10,000 employees using TLS 1.3? The inspection you force on the users is its own security hole, to say nothing of software bugs. And you can't even just lock down the network to only protocols that use OAuth or something. None of our security solutions are holistic.

We need a revolution in network security that takes each part of a network communication and its individual security needs into account, not just what we imagine is end-to-end (but never actually is). We can't rely solely on a facile "privacy or nothing" approach to internet security that the TLS mafia has been pushing. We need more flexible methods that allow us to fine-tune security at each level of the protocol stack, across multiple organizations and use cases. Nothing like that exists currently for the web.


Spot on. Firewall are becoming less and less useful in the time of cloud.

We need holistic solutions where we can control traffic by entity, domain, role, application, not IP address and port.

> There will come a point where the attacker will position themselves to appear exactly like legitimate traffic.

It's been happening for decades: botnet C&C servers use HTTPS and run on public clouds, mimicking legitimate websites.


What would you propose instead?


I'd start by making all network protocols stacked flat with metadata about their being joined together, rather than loosely embedded in one another like matryoshka dolls. This can be done using existing protocols by demarcating each stack layer in an existing stream and adding metadata to link the parts together as they are composed. The end result is that the entire network path is preserved and available for inspection at any point along the network path. By using the metadata, each layer can remain private, but also be directly accessed by any network node that has the proper authorization to view it. This solves service routing issues, middleware issues, application-service integration issues, and end to end security issues.

Wrt our current conversation, you could have a network filter which only allows network communications whose packets at a particular layer are authenticated by a particular identity provider, authorized by a particular service provider, encrypted by a particular standard, and pass only a particular set of data using a particular data standard.

But looking further, you could have much bigger impacts. For example, right now we have to use NAT for IPv4 because there's no way for a private network to route directly to public networks and vice versa. But with this new scheme, the route tables, host addresses, the DNS, TCP protocol, service address (the address of the service should not require numbering at all, it should just pass a URI and boxes along the way should translate how to route to it based on that local network's definitions), and the various data payloads and formats, all would be delivered to every hop along the way up to the app server. The server reply would be carried back the same way just by reversing the order of the path. And so you could actually route messages between multiple sets of public and private networks, and those networks would allow the traffic or not based on the authn+z protocols and policies at each segment.

(Particularly, the application on the user's device would be prompted by the OS whether to accept the packets, similar to how the application firewall works. Except it could actually verify that each data payload was not just signed by a key on a random load balancer, but that it's actually been passed by an application with a valid OAuth session (but not OAuth since much better protocols would be used))

None of this assumes backwards compatibility (again, it's a revolution, not an incremental change). But there are some hacks that could be used to implement some of these features with existing protocols, to make transition easier. However, it's been shown time and again that all we really need to implement breaking changes in internet infrastructure is for a sufficiently large company to force it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: