I put some efforts in a working nftables configuration to migrate from iptables. Was more of a hassle than expected.
If anyone interested her my initial config (to be nailed down further):
Incorporated @Christophe_Saelens excellent suggestions from post 2 of this thread.
Install webmin
sudo apt-get update -y
sudo apt-get install webmin -y
# start it:
sudo service webmin start
sudo service webmin status
sudo service webmin restart
Test it (with your root credentials)
http://run-core.local:10000
Security
Now install nftables:
sudo apt-get install nftables -y
start it
sudo systemctl enable nftables.service
sudo systemctl start nftables
sudo systemctl status nftables
This is not my final hardened version, however the first one that works. Coming from IPTABLES it was more hassle than expected
# let´s start fresh
sudo nft flush ruleset
# and now the fun begins
sudo nft add table inet filter
sudo nft add chain inet filter input { type filter hook input priority 0 \;policy drop\; }
sudo nft add chain inet filter output { type filter hook output priority 0 \; }
# as our system should not route anything, we do not need a forward chain
sudo nft add rule inet filter input ct state established,related accept
# ROON needs the loopback to work, check the loopback Interface Name
sudo nft add rule inet filter input iifname lo counter accept
# We need Broadcasting and Multicasting
sudo nft add rule inet filter input pkttype multicast counter accept
sudo nft add rule inet filter input pkttype broadcast counter accept
# SSH secure shell is alway needed
sudo nft add rule inet filter input tcp dport {ssh} accept
# WEBMIN access
sudo nft add rule inet filter input tcp dport 10000 accept
sudo nft add rule inet filter input ip saddr 192.168.1.1/24 udp dport 9003 counter accept
sudo nft add rule inet filter input ip saddr 192.168.1.1/24 tcp dport 9300-9339 counter accept
# logging
sudo nft add rule inet filter input log prefix "droping "
Let´s see if it worked:
sudo nft -s list ruleset
should look like:
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iifname "lo" counter accept
meta pkttype multicast counter accept
meta pkttype broadcast counter accept
tcp dport { 22 } accept
tcp dport 10000 accept
ip saddr 192.168.1.0/24 udp dport 9003 counter accept
ip saddr 192.168.1.0/24 tcp dport 9300-9339 counter accept
log prefix "droping"
}
chain output {
type filter hook output priority filter; policy accept;
}
}
And store it
sudo nft -s list ruleset | sudo tee /etc/nftables.rules
start it when booting:
sudo vim /etc/nftables.conf
should look like:
#!/usr/sbin/nft -f
flush ruleset
include "/etc/nftables.rules"
and finaly test it by restarting
sudo systemctl restart nftables
sudo nft -s list ruleset
3 Likes
Nice write-up, this will help a lot of people using Linux!
I think you can simplify your rules quite a bit.
Set policy to drop, so that any traffic that s isn’t explicitly allowed gets dropped.
You can leave out the rule for accepting 127.0.0.1, since you already accept interface lo0. lo0 should have the 127.0.0.1 and ::1 ip addresses. You can check the loopback interface name and ip using ip addr Sometimes this is just lo and not lo0
IYou should be able to leave these out too, since you allow them with meta pkttype multicast counter accept
If you check, the counter for multicast should stay at zero the way you have configured it.
For tcp 9100-9400: 9330-9339 should be sufficient.
Don’t think forwarding is used by Roon, you can change the policy to drop.
I think you should be able to get everything working using only these (just add your own rules for ssh and webmin)
chain input {
type filter hook input priority filter; policy drop;
iifname "lo0" accept
ct state invalid drop
ct state established,related accept
meta pkttype multicast counter accept
meta pkttype broadcast counter accept
ip saddr 192.168.1.0/24 udp dport 9003 counter accept
ip saddr 192.168.1.0/24 tcp dport 9330-9339 counter accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
1 Like
Christophe,
thanks for you valuable input which I incoporated! You were correct that the loopback interface name was wrong (the reason for the SADDR rule, and I completely dropped the not used forward chain.
Everything works fine (Roon native and USB, only DEVIALET AIR and Airplay is not working yet). So I will tweak further.
Christophe,
thanks for you valuable input which I incoporated! You were correct that the loopback interface name was wrong (the reason for the SADDR rule, and I completely dropped the not used forward chain.
One Question , the only reason I used a policy accept and dropped verything at the End was the Log rule. How do you log dropped packet (for troubleshhooting) in a “policy drop” chain?
Everything works fine (Roon native and USB, only DEVIALET AIR and Airplay is not working yet). So I will tweak further.
You should still be able to put the log rule last if you want to do some debugging. You can comment it out using a # if you don’t need it.
log flags all
I thnk (but unsure since i don’t use Airplay) you’ll have to allow the udp ports 32768-65535
ip protocol udp ip saddr 192.168.1./24 udp dport 32768-65535 counter accept
Don’t know what ports or protocols are used by Devialet Air, you’re on your own with that one 
Maybe it uses the same ports as Airplay, but you’ll have to look at your logs for that.
PS: If your devices have fixed IP’s, and you feel bold you can close down your firewall even more with some sets. These go just above your input chain. If you add a device, just add it to the set and the rules are updated. It’s also nicer to look at than a list of ip’s.
set Roon {
type ipv4_addr
flags interval
elements = { 192.168.1.100, 192.168.1.101, 192.168.1.102 }
}
set Airplay {
type ipv4_addr
flags interval
elements = { 192.168.1.100, 192.168.1.101 }
}
For the rules, you can then use
ip saddr @Roon udp dport 9003 counter accept
ip saddr @Roon tcp dport 9330-9339 counter accept
ip saddr @Airplay udp dport 32768-65535 counter accept
EDIT:
This post on Reddit from a few years back mentions udp 6002 and 49152-65535, but strangely enough as source ports.
If I were you, I’d start with these, and if it doesn’t work, you can swich to source ports.
ip saddr @Airplay udp dport { 6002, 49152-65535 } counter accept
This is my working configuration. Now supports:
ROON native
Apple Airplay
Devailet AIR
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
# let´s be statefull:
ct state established,related accept
# check the neame of you loopback before !
iifname "lo" counter accept
# ROON needs to receive Multicasts and Broadcasts !
meta pkttype multicast counter accept
meta pkttype broadcast counter accept
# SSH is always a good idea
tcp dport { 22 } accept
# Webmin
tcp dport 10000 accept
# Needed for Roon
ip saddr 192.168.1.0/24 udp dport 9003 counter accept
ip saddr 192.168.1.0/24 tcp dport 9300-9339 counter accept
# Apple Airplay
ip saddr 192.168.1.0/24 udp dport 32768-65535 counter accept
# Devialet Air
ip saddr 129.168.1.0/24 udp dport 6002 counter accept
# comment out logging for production use
log prefix "droping " flags all
}
chain output {
type filter hook output priority filter; policy accept;
}
}
1 Like
Looking good, glad you got it working!