How to prevent client-side internet connection of selfhosted apps?
Hi all, most of my selfhosted apps are running in isolated docker networks without any internet connection. To limit the attack vector in case of supply chain attacks etc., I want to prevent any unnecessary internet connections, and only whitelist domains…
Hi all, most of my selfhosted apps are running in isolated docker networks without any internet connection. To limit the attack vector in case of supply chain attacks etc., I want to prevent any unnecessary internet connections, and only whitelist domains selfhosted-apps are allowed to connect to. Still, I get notifications like "New version available" of some apps nevertheless. I assume because they are using client-side requests, that bypass the server-side restrictions. Any chance to also prevent these outgoing connections?
Collected discussion
Expand the replies to this comment to learn how AI was used in this post/project.
That's what I'm doing already, but it seems not to prevent the apps to call home client-side via e.g. javascript.
yes, via another browser. I believe it incapsulates it to VNC or some other RDP protocol under the hood. But in the end you will have firefox window in web page. Its not ideal from usability point of view(since utilize extra cpu\gpu to encode, mac\win clients require some tweaking regarding screen scaling and keybindings), but from security point of view it is very good.
🙄
That's server-side isolation, but is not preventing client-side home calling via javascript.
Thank you, overriding the security-policies via reverse proxy seems the best solution, will look into it.
To expand on this slightly, you can add or override CSP headers using your reverse proxy, I do this with Caddy for instance. OWASP also has some good guides on CSP headers, and some apps have decent baselines that you can use for reference too (Vaultwarden has a good default that restricts outbound connections to only the services that they explicitly mention using for password leak checks and such, gives a good general sense of how they work). A catch here is that some frontends use online resources more than you might expect so it can take a bit of troubleshooting per app, you can use your browser's inspect source tooling to get more info about denials when doing this (just ignore Chromium complaining about how allow list CSPs aren't as secure, the alternative ones they recommend are for developers and would take a lot more effort to implement than merely injecting the header using your reverse proxy, and the difference is probably not enough to matter in a self hosted environment)
I'm not terribly convinced these actually improve security, running in Docker disables some of the sandboxing features of the containerised browser which makes it easier to escape into the rest of the container, and a malicious site that does that can then just add the attack code to the web front-end that's being served to your main browser so you're still relying on your main browser and just hoping that the obscurity of your setup helps. That last part is going to provide diminishing returns too as people start using AI agents for automated exploits. The only cases I can think of where this might actually be helpful are multi container setups like Kasm (the full stack, not the single containers) where the web front-end isn't being served from the container (but then I'm skeptical of the rootful Docker setup as a robust isolation boundary), or using completely different browsers, e.g. running Firefox in Docker while accessing it through Chromium.
For OP use-case that is okay, because he is not going to open anything except local stuff, his problem is client side js code escaping to the internet, and will be solved 100%. Back to the topic - Its very unlikely you will get auto-attacked by some random shitty malware, unless you target very specific content. Regular pron torrent trackers will be safe for you, because most of shit is a windows encryptors\password stealers and unlikely will target docker sandbox escaping. If very paranoic, kata containers or firecracker - adds kvm layer on top + some windows/linux sandbox with empty browser to use that other browser, obviously everything is vpned. Obviously, everything can be escaped and all depends on how you are interesting for this or that persons. I bet the one who diving in absolutely dangerous content or use-cases either know what he is doing, or will screw somewhere else regardless :)
yep — if JavaScript in the browser makes the call, it comes from the user's device, not the container. Docker networking can't touch it. for web apps, the cleanest control you can push from the server is a CSP response header at the reverse proxy. connect-src limits fetch/XHR/WebSocket destinations, for example: Content-Security-Policy: connect-src 'self' https://allowed.example; i'd start with Content-Security-Policy-Report-Only and watch the browser console/network tab first. a strict policy can break APIs or websockets the app actually needs. this only covers the web UI; native clients need client- or network-level blocking.
This comment was deleted.
Thanks for this. I forgot JS could do this nonsense. 🦧🦧
To control the browser side of things, you need to set / override the browsers csp https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP Or modify the app to remove the update check from the frontend
those update-check notifications are almost certainly coming from your browser, not the container. the app ships a client-side version check that runs in your tab, so it never touches the isolated docker network you locked down - which is why the server-side rules miss it. you can only kill it at the client: block the version-check domain in your dns/pihole, or disable the update check in the app config if it exposes one.
Btw, not directly answering your question, but still might be helpful- run browser in docker as well. Use linuxserver/firefox, with hardware accel. That will give max protection, almost no way to escape accidently because of miss configuration or js side clients.
Lots of ways to do it, but personally I run Unifi equipment so I'd just deny internet access by default for the host and then allowlist only what I want.
uMatrix even if it's not in development anymore. Or uBlock with the correct settings.
docker compose with network_mode: none then use a reverse proxy for the few that actually need to phone home, that's how i do it for most of my stuff
Docker internal networks are the cleanest fix. Create one with docker network create --internal and nothing on it can reach the internet. For bare-metal apps, nftables OUTPUT drop rules keyed on the process UID work the same way.
I'm running renovate to get new updates as pull requests and I limit ingress and egress with cilium network policies and cilium clusterwide network policies. Hubble can help you to find incoming and outgoing connection attempts.
Bro the version is just hardcoded it's not that deep