You can choose to mark packets to be accepted as a safe conduct in following chains of the same hook.
each accept rule should mark the packet
Rules doing an explicit accept should mark the packet right before accepting it. Any occurence of:
... accept
should be replaced with:
... meta mark set 0xf00 accept
The value isn't important as long it's not 0 if there's no other role to the mark.
each chain should accept a marked packet since that's the safe conduct
by using this rule early in the chain:
meta mark != 0 accept
That's the general idea. Adaptations and exceptions can still be made if it makes more sense.
Here is the revisited ruleset following this approach. The mark is accepted after the ct ... invalid drop
rule which is an important rule that should not be bypassed (and could actually have been done in an earlier chain once and for all since it's a drop rule). If below, input is the last chain in the filter/input hook it's not really needed to mark accepted packets, but it doesn't hurt to do so.
/etc/nftables.conf:
:
flush ruleset
table inet filter {
counter input_ssh {}
set my_admin_ipv4 {
type ipv4_addr
flags interval
counter
elements = {
10.0.0.0/8,
172.16.0.0/12,
192.168.0.0/16
}
}
chain input {
type filter hook input priority filter; policy drop;
iifname lo meta mark set 0x1 accept comment "Allow loopback traffic";
ct state established,related meta mark set 0x1 accept comment "Allow established/related connections";
ct state invalid drop comment "Deny invalid connections";
meta mark != 0 accept
# SSH
tcp dport ssh ip saddr @my_admin_ipv4 counter name input_ssh meta mark set 0x1 accept comment "Allow IPv4 SSH from Admin";
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
include "/etc/nft/*.conf"
}
/etc/nft/http.conf
(replaced counter_nginx
with counter_http
). The meta mark != 0 accept
rule is probably not needed here since there might not be any other chain before anyway, but it doesn't hurt to have it too.
counter input_http {}
chain http {
type filter hook input priority filter - 1; policy accept;
meta mark != 0 accept
# HTTP #
tcp dport {80,443} counter name input_http meta mark set 0x2 accept comment "Allow HTTP";
}
This method uses marks so will be harder to integrate with other firewall rules that were already using marks for other purposes. It's still possible by reserving a few bits of the mark with bitwise operations.