blastdoor
0.1.0blastdoor is the firewall tool of UraniumOS. The firewall is one nftables ruleset in /etc/nftables.conf, which /etc/rc loads at boot. blastdoor opens and closes ports by writing one-line files to /etc/nftables.d, which the ruleset includes, and loading the ruleset again. It is part of the uranium-tools package and needs root.
The ruleset
This is /etc/nftables.conf as installed:
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state established,related accept
ct state invalid drop
meta l4proto { icmp, icmpv6 } accept
udp sport 67 udp dport 68 accept
tcp dport 22 ct state new limit rate 10/minute accept
include "/etc/nftables.d/*.nft"
}
chain forward { type filter hook forward priority 0; policy drop; }
chain output { type filter hook output priority 0; policy accept; }
}
flush ruleset- Removes every table of every family before the new one is added, in the same transaction. Rules another tool put in nftables are removed by a load too.
table inet filter- One table for IPv4 and IPv6.
policy dropon input and forward- A packet that no rule accepts is dropped. The forward chain accepts nothing, so the machine does not route for others.
iif lo accept- Everything on the loopback interface. Services listening on
127.0.0.1or::1are not filtered, including sandboxes and containers that share the network. ct state established,related accept,ct state invalid drop- Replies to connections the machine opened, and related traffic, are accepted. Packets that connection tracking calls invalid are dropped.
meta l4proto { icmp, icmpv6 } accept- All ICMP and ICMPv6 is accepted, with no rate limit. The machine answers ping, and IPv6 neighbour and router messages get through.
udp sport 67 udp dport 68 accept- DHCP replies for the
dhcpservice. tcp dport 22 ct state new limit rate 10/minute accept- New ssh connections, at ten a minute counted over all sources together. nft adds a burst of 5 packets when it loads the rule. The limit is not kept per source, so one address can use up the allowance and keep other users out.
include "/etc/nftables.d/*.nft"- The files that
blastdoor allowwrites. The include is inside the input chain after the rules above, and the files load in the order the glob sorts them. - output chain
- Open. Outgoing traffic is not filtered.
A service is not reachable from the network until it's port is opened, whichever program listens on it.
Synopsis
blastdoor allow PORT[/tcp|/udp]
blastdoor deny PORT[/tcp|/udp]
blastdoor list
blastdoor reload
allow PORT[/PROTO]- Writes the line
PROTO dport PORT acceptto/etc/nftables.d/PORT-PROTO.nft, loads the whole ruleset again and says which port it allowed. The protocol istcpunless given. Allowing a port twice rewrites the same file. deny PORT[/PROTO]- Deletes
/etc/nftables.d/PORT-PROTO.nft, loads the ruleset again and says which port it closed. It only removes files named that way, so a rule you wrote under another name and the built-in ssh rule stay. list- Runs
nft list chain inet filter inputand shows the output. The exit status is 0 even when nft fails, for example when you are not root. reload- Runs
nft -f /etc/nftables.conf. Use it after you edit the ruleset or a file in/etc/nftables.d.
A port is a number from 1 to 65535 made of digits only, so 0, +80 and 70000 are refused. Leading zeros are dropped, so allow 080 writes 80-tcp.nft. The protocol is tcp or udp in lower case.
Examples
# blastdoor allow 8080
allowed 8080/tcp
# blastdoor allow 53/udp
allowed 53/udp
# blastdoor list
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
ct state invalid drop
meta l4proto { icmp, ipv6-icmp } accept
udp sport 67 udp dport 68 accept
tcp dport 22 ct state new limit rate 10/minute burst 5 packets accept
udp dport 53 accept
tcp dport 8080 accept
}
}
# blastdoor deny 8080
closed 8080/tcp
A longer rule goes in the same directory in any file that ends in .nft. This one limits a database to one network:
# echo 'ip saddr 10.0.0.0/24 tcp dport 5432 accept' > /etc/nftables.d/postgres.nft
# blastdoor reload
Remove that rule by deleting the file and running blastdoor reload.
nft loads a file as one transaction. When any line fails nothing changes and the rules loaded before stay in place. allow writes the file before it loads, so after a failed load the file is still there. A broken file in /etc/nftables.d makes every later load fail, and blastdoor reports cannot load until you remove the file:
In file included from /etc/nftables.conf:11:9-107:
/etc/nftables.d/bad.nft:1:11-16: Error: Could not resolve service: Servname not supported for ai_socktype
tcp dport banana accept
^^^^^^
blastdoor: cannot load /etc/nftables.conf
At boot
/etc/rc loads /etc/nftables.conf after it applies /etc/sysctl.conf and before it starts the network. A ruleset that fails to load at boot prints nothing and the machine runs with no firewall. geiger reports that as warn blastdoor is not loaded, so run it after you edit the ruleset by hand. Nothing is filtered between the start of the kernel and that line.
Files and variables
/etc/nftables.conf- The ruleset. Edit it for built-in rules.
/etc/nftables.d/*.nft- One file for each opened port or custom rule.
BLASTDOOR_CONF,BLASTDOOR_DIR- Replace the two paths above.
/etc is in the root frame, so scram brings back the firewall of the time of a frame when it flashes to it.
Limits
- Only incoming traffic is filtered. A program that is compromised can connect out to anywhere.
- Rules open a port for every source. Restrict by source address with a hand-written file as in the example above.
- Containers and sandboxes that share the host network are filtered like the host. With
silo -norhazmat -nthey have no network at all, see silo and hazmat. - Dropped packets are not logged.
- The kernel has connection tracking, NAT, masquerading, logging, rate limits and reject built in.