First version
This commit is contained in:
commit
243e92a9dd
84 files changed
+4012
No files matched your search
Executable
+90
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
# Base nftables ruleset: inbound traffic is dropped, outbound traffic is rejected
|
||||
# except loopback, established connections, the local proxy (web), the local
|
||||
# DNS filter and the time servers that /refresh_rules.sh adds.
|
||||
# Web traffic (ports 80 and 443) of every program is redirected to the local
|
||||
# proxy (contest-proxy.service), which checks the site name. Only the proxy
|
||||
# may connect to the outside on port 443.
|
||||
|
||||
CONF=/etc/contest-firewall
|
||||
|
||||
# Remove any persisting nftables rules
|
||||
rm -f /etc/nftables.rules
|
||||
touch /etc/nftables.rules
|
||||
|
||||
# Configuration of the proxy: the allowed names and the DNS resolver
|
||||
mkdir -p /run/contest-firewall
|
||||
for name in $(sed -e 's/#.*//' -e 's/[[:space:]]//g' "$CONF/allowed_domains.txt"); do
|
||||
echo "$name $name:443;"
|
||||
done > /run/contest-firewall/proxy_names.conf
|
||||
# The proxy resolves the names through the DNS filter below
|
||||
echo "resolver 127.0.0.1 ipv6=off valid=30s;" > /run/contest-firewall/proxy_resolver.conf
|
||||
|
||||
# Local DNS filter (contest-dns.service): the allowed domains and the time
|
||||
# servers are forwarded to the DNS resolvers, every other name gets no answer.
|
||||
# Programs on the machine ask it through /etc/resolv.conf, and only the proxy
|
||||
# account (which also runs the filter) may reach the DNS resolvers. This
|
||||
# closes DNS as a way to exchange data with a server outside.
|
||||
{
|
||||
echo "listen-address=127.0.0.1"
|
||||
echo "bind-interfaces"
|
||||
echo "no-resolv"
|
||||
echo "no-hosts"
|
||||
echo "user=contest-proxy"
|
||||
echo "group=nogroup"
|
||||
echo "cache-size=1000"
|
||||
echo "log-queries"
|
||||
echo "server=/#/"
|
||||
for name in $(sed -e 's/#.*//' -e 's/[[:space:]]//g' "$CONF/allowed_domains.txt" "$CONF/ntp_servers.txt"); do
|
||||
for dns in $(sed -e 's/#.*//' -e 's/[[:space:]]//g' "$CONF/dns_servers.txt"); do
|
||||
echo "server=/$name/$dns"
|
||||
done
|
||||
done
|
||||
} > /run/contest-firewall/dnsmasq.conf
|
||||
# /run/resolvconf is one of the places the AppArmor profiles (dig, ...) accept,
|
||||
# and the resolvconf package that would also use it is not installed
|
||||
mkdir -p /run/resolvconf
|
||||
echo "nameserver 127.0.0.1" > /run/resolvconf/resolv.conf
|
||||
ln -sfn /run/resolvconf/resolv.conf /etc/resolv.conf
|
||||
|
||||
# Flush all rules, then create the table, chains and address sets
|
||||
nft flush ruleset
|
||||
nft add table inet filter
|
||||
nft add chain inet filter input '{ type filter hook input priority 0 ; policy drop ; }'
|
||||
nft add chain inet filter forward '{ type filter hook forward priority 0 ; policy drop ; }'
|
||||
nft add chain inet filter output '{ type filter hook output priority 0 ; policy accept ; }'
|
||||
nft add set inet filter ntp_ips '{ type ipv4_addr ; flags interval ; }'
|
||||
|
||||
# Redirect web traffic to the proxy, except the proxy's own connections and
|
||||
# the local sites of the image (DevDocs)
|
||||
nft add table inet nat
|
||||
nft add chain inet nat output '{ type nat hook output priority -100 ; }'
|
||||
nft add rule inet nat output meta skuid contest-proxy return
|
||||
nft add rule inet nat output ip daddr 127.0.0.0/8 return
|
||||
nft add rule inet nat output meta nfproto ipv4 tcp dport 443 redirect to :8443
|
||||
nft add rule inet nat output meta nfproto ipv4 tcp dport 80 redirect to :8080
|
||||
|
||||
# Established/related connections and loopback
|
||||
nft add rule inet filter input ct state related,established accept
|
||||
nft add rule inet filter output ct state related,established accept
|
||||
nft add rule inet filter input iif lo accept
|
||||
nft add rule inet filter output oif lo accept
|
||||
# Connections redirected to the proxy (they still show the network interface here)
|
||||
nft add rule inet filter output ip daddr 127.0.0.1 tcp dport '{ 8080, 8443 }' ct status dnat accept
|
||||
|
||||
# Web: only the proxy connects to the outside, by name, to the allowed sites
|
||||
# it resolves itself through the DNS filter (no list of addresses to keep up
|
||||
# to date, content delivery networks change them all the time)
|
||||
nft add rule inet filter output meta skuid contest-proxy tcp dport 443 accept
|
||||
|
||||
# Time servers, for chrony only (addresses filled by /refresh_rules.sh)
|
||||
nft add rule inet filter output meta skuid _chrony ip daddr @ntp_ips udp dport 123 accept
|
||||
|
||||
# DNS resolvers, for the proxy and the DNS filter only
|
||||
for dns in $(sed -e 's/#.*//' -e 's/[[:space:]]//g' "$CONF/dns_servers.txt"); do
|
||||
nft add rule inet filter output meta skuid contest-proxy ip daddr "$dns" udp dport 53 accept
|
||||
nft add rule inet filter output meta skuid contest-proxy ip daddr "$dns" tcp dport 53 accept
|
||||
done
|
||||
|
||||
# Reject any other outgoing connection
|
||||
nft add rule inet filter output reject
|
||||
Reference in new issue
Block a user