Last active
June 16, 2026 06:38
-
-
Save torgeir/2a5d94b76b4a2a9debcdb53ea0e34a2e to your computer and use it in GitHub Desktop.
Domain-allowlist network sandbox for docker compose (nftables + dnsmasq sidecar)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| FROM ubuntu:24.04 | |
| RUN apt-get update && apt-get install -y \ | |
| curl \ | |
| dnsutils \ | |
| iputils-ping \ | |
| netcat-openbsd \ | |
| && rm -rf /var/lib/apt/lists/* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| no-resolv | |
| no-hosts | |
| listen-address=127.0.0.1 | |
| bind-interfaces | |
| cache-size=500 | |
| # log all queries | |
| log-queries | |
| log-facility=- # "-" = stderr -> docker logs | |
| # strip AAAA answers — the nft set is v4-only, so without this curl | |
| # may try an (unfiltered, blocked) IPv6 address first and stall | |
| filter-AAAA | |
| # example allow dns and connections | |
| #server=/nrk.no/1.1.1.1 | |
| # format: 4#<table family>#<table>#<set> | |
| #nftset=/nrk.no/4#inet#sandbox#allowed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # usage: | |
| # docker compose down | |
| # docker compose build firewall | |
| # docker compose up -d --remove-orphans | |
| # docker compose run app bash | |
| # see logs: | |
| # docker compose logs firewall -f | |
| # works: | |
| # dig nrk.no | |
| # curl https://www.nrk.no | |
| # fails: | |
| # dig google.no | |
| # curl https://www.google.no # fails | |
| # curl http://www.nrk.no # fails | |
| services: | |
| firewall: | |
| build: | |
| context: . | |
| dockerfile: ./firewall.Dockerfile | |
| cap_add: | |
| - NET_ADMIN | |
| healthcheck: | |
| test: ["CMD-SHELL", "nft list table inet sandbox >/dev/null && getent hosts localhost >/dev/null"] | |
| interval: 1s | |
| timeout: 2s | |
| retries: 30 | |
| start_period: 5s # grace period before failures count | |
| #start_interval: 1s # fast polling during startup only (compose 2.22+) | |
| app: | |
| build: | |
| context: . | |
| dockerfile: ./app.Dockerfile | |
| network_mode: "service:firewall" | |
| depends_on: | |
| firewall: | |
| condition: service_healthy |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| nft delete table inet sandbox 2>/dev/null || true | |
| nft -f /etc/nftables-sandbox.conf | |
| echo "nameserver 127.0.0.1" > /etc/resolv.conf | |
| # allow list | |
| for d in nrk.no \ | |
| aftenposten.no \ | |
| pypi.org \ | |
| files.pythonhosted.org \ | |
| registry.npmjs.org; do | |
| echo "server=/$d/1.1.1.1" | |
| echo "nftset=/$d/4#inet#sandbox#allowed" | |
| done >> /etc/dnsmasq-sandbox.conf | |
| # -k = keep in foreground; exec makes dnsmasq PID 1 so the | |
| # container lives exactly as long as the resolver does. | |
| exec dnsmasq -k --conf-file=/etc/dnsmasq-sandbox.conf --user=dnsmasq |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| FROM ubuntu:24.04 | |
| RUN apt-get update && apt-get install -y --no-install-recommends nftables dnsmasq \ | |
| && rm -rf /var/lib/apt/lists/* | |
| COPY nftables.conf /etc/nftables-sandbox.conf | |
| COPY dnsmasq.conf /etc/dnsmasq-sandbox.conf | |
| COPY entrypoint.sh /entrypoint.sh | |
| RUN chmod +x /entrypoint.sh | |
| ENTRYPOINT ["/entrypoint.sh"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| table inet sandbox { | |
| set allowed { | |
| type ipv4_addr | |
| } | |
| chain input { | |
| type filter hook input priority 0; policy drop; | |
| iifname lo accept | |
| ct state established,related accept | |
| } | |
| chain output { | |
| type filter hook output priority 0; policy drop; | |
| ip daddr 127.0.0.11 drop | |
| oifname lo accept | |
| ct state established,related accept | |
| meta skuid "dnsmasq" ip daddr 1.1.1.1 udp dport 53 accept | |
| meta skuid "dnsmasq" ip daddr 1.1.1.1 tcp dport 53 accept | |
| # HTTP(S) to IPs that dnsmasq resolved for allowlisted domains | |
| ip daddr @allowed tcp dport { 443 } accept | |
| reject with tcp reset | |
| } | |
| chain forward { | |
| type filter hook forward priority 0; policy drop; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment