Wren Linux

wren-linux / data / onion-site-firewall.nft

# Keeps the onion-site user off your computer and your local network
# (Wren Linux extras/onion-site.sh). Only that user's traffic is touched.
#
# onion-site runs the site's VM (one qemu-system-x86_64 process). After its
# first setup the VM runs with QEMU's restrict=on: the guest can't send a single
# packet out, so it can't give away this computer's address whatever the site
# does. This rule is the second wall, for the QEMU process itself: the internet
# (which the first setup needs, to install Debian), but not your router,
# printers, other machines or the services on this computer, except two on
# loopback:
#   127.0.0.1:2243  the VM's own SSH console, which the host logs in to
#   127.0.0.1:9050  Tor's SOCKS port, which "onion-site update" lends the VM
#                   for apt (through socat, one connection at a time)
# Tor reaches the site through 127.0.0.1:18080, which this user listens on;
# answers go out from that port and the console's, and from no other.
# DNS goes only to the resolver this computer uses: Unbound while secure DNS
# is on, the network's while it is off (parts/sandbox-dns.sh).

table inet wren_onion_site
delete table inet wren_onion_site

table inet wren_onion_site {
    # The resolver this computer uses (Unbound on 127.0.0.1 with secure DNS on, the
    # network's while it is off), kept up to date by wren-sandbox-dns
    # (parts/sandbox-dns.sh): DNS goes there only, not to any address
    set resolvers {
        type ipv4_addr
    }
    chain output {
        type filter hook output priority 0; policy accept;
        meta skuid "onion-site" jump onion_site
    }

    chain onion_site {
        # Answers only from the VM's console (2243) and the site (18080, which Tor
        # visits): nothing else, so it can't stand in for a service here
        # (only answers: from those ports alone it could start connections too)
        ct direction reply ip saddr 127.0.0.1 tcp sport { 2243, 18080 } accept
        ip daddr @resolvers udp dport 53 accept
        ip daddr @resolvers tcp dport 53 accept
        ip daddr 127.0.0.1 tcp dport { 2243, 9050 } accept
        # Anything addressed to this computer itself goes out through "lo",
        # whichever of its addresses is used, so this catches them all
        # (admin-prohibited: how bin/sandbox-net-check tells this from a closed port)
        oifname "lo" reject with icmpx admin-prohibited
        ip daddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8,
                   169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16,
                   224.0.0.0/4, 255.255.255.255 } reject
        # No IPv6 at all: on a network with global addresses, the router and other
        # computers have addresses no fixed rule can tell from the internet's.
        # Sites fall back to IPv4 at once (an IPv6-only network wouldn't work)
        meta nfproto ipv6 reject
    }
}