nftables:
tables:
example:
vars:
dns_servers: ['1.1.1.1', '1.1.0.0', '8.8.8.8', '8.8.4.4']
private_ranges: ['192.168.0.0/16', '172.16.0.0/12', '10.0.0.0/8']
sets:
blacklist:
flags: ['dynamic', 'timeout']
settings:
timeout: '3m'
counters:
invalid_packages:
comment: 'Invalid'
limits:
icmp_limit:
rate: '10/second'
chains:
incoming:
hook: 'input'
vars:
chain_var: '1.1.1.1'
rules:
- sequence: 1
raw: 'ct state invalid counter name invalid_packages log prefix "DROP invalid states" drop'
- seq: 2
raw: 'ct state {established, related} counter accept comment "Allow open sessions"'
- s: 3
raw: 'iifname "lo" accept comment "Allow loopback traffic"'
- {proto: 'icmp', type: 'echo-request', limit: 'icmp_limit', comment: 'Allow icmp-ping'}
- {proto: 'icmpv6', type: 'echo-request', limit: 'icmp_limit', comment: 'Allow icmp-ping'}
- {proto: 'icmp', code: 30, limit: 'icmp_limit', comment: 'Allow icmp-traceroute'}
- {proto: 'icmpv6', limit: 'icmp_limit', comment: 'Allow necessary icmpv6-types for ipv6 to work',
type: ['nd-neighbor-solicit', 'nd-router-advert', 'nd-neighbor-advert']}
- {proto: 'udp', port: 46251, counter: 'invalid_packages', action: 'drop'}
outgoing:
hook: 'output'
# policy: 'accept'
rules:
- {dest: '$dns_servers', proto: 'udp', port: 53}
- {dest: '$dns_servers', proto: 'tcp', port: [53, 853]}
- {proto: ['tcp', 'udp'], port: [80, 443]}
- {proto: ['icmp', 'icmpv6'], comment: 'Allow outbound icmp'}
translate:
hook: 'postrouting'
type: 'nat'
policy: 'accept'
rules:
- {'src': '$private_ranges', oif: 'eno2', masquerade: true} # dynamic outbound nat
- {'src': '$private_ranges', oif: 'eno3', snat: '192.168.0.1'} # static outbound nat
guy@ansible:~# nft list ruleset
> table inet example {
> counter invalid_packages {
> comment "Invalid"
> packets 0 bytes 0
> }
>
> limit icmp_limit {
> rate 10/second
> }
>
> set blacklist {
> type ipv4_addr
> flags dynamic,timeout
> counter
> timeout 3m
> }
>
> chain incoming {
> type filter hook input priority filter; policy drop;
> ct state invalid counter name "invalid_packages" log prefix "DROP invalid states" drop
> ct state { established, related } counter packets 0 bytes 0 accept comment "Allow open sessions"
> iifname "lo" accept comment "Allow loopback traffic"
> icmp type echo-request limit name "icmp_limit" accept comment "Allow icmp-ping"
> icmpv6 type echo-request limit name "icmp_limit" accept comment "Allow icmp-ping"
> icmp code 30 limit name "icmp_limit" accept comment "Allow icmp-traceroute"
> icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } limit name "icmp_limit" accept comment "Allow necessary icmpv6-types for ipv6 to work"
> udp dport 46251 log prefix "DROP" counter name "invalid_packages" drop
> counter packets 0 bytes 0 comment "COUNT example-incoming-drop"
> log prefix "DROP example-none "
> }
>
> chain outgoing {
> type filter hook output priority filter; policy drop;
> udp dport 53 ip daddr { 1.1.0.0, 1.1.1.1, 8.8.4.4, 8.8.8.8 } accept
> tcp dport { 53, 853 } ip daddr { 1.1.0.0, 1.1.1.1, 8.8.4.4, 8.8.8.8 } accept
> meta l4proto { 6, 17 } th dport { 80, 443 } accept
> meta l4proto { 1, 58 } accept comment "Allow outbound icmp"
> counter packets 0 bytes 0 comment "COUNT example-outgoing-drop"
> }
>
> chain translate {
> type nat hook postrouting priority filter; policy accept;
> oifname "eno2" ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } masquerade
> oifname "eno3" ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat ip to 192.168.0.1
> counter packets 0 bytes 0 comment "COUNT example-translate-accept"
> }
> }
guy@ansible:~# cat /etc/nftables.conf
> #!/usr/sbin/nft -f
>
># Ansible managed: Do NOT edit this file manually!
>
> flush ruleset
>
>
> # global vars
> define global_var_test = { 1.1.1.1 }
>
> include "/etc/nftables.d/*.nft"
guy@ansible:~# ls -l /etc/nftables.d/
> -rw-r----- 1 root root example.nft
guy@ansible:~# cat /etc/nftables.d/example.nft
> #!/usr/sbin/nft -f
>
> table inet example {
>
> # vars
> define private_ranges = { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
> define dns_servers = { 1.1.1.1, 1.1.0.0, 8.8.8.8, 8.8.4.4 }
>
> # sets
> set blacklist {
> type ipv4_addr;
> flags dynamic, timeout;
> timeout 3m;
> counter
> }
>
> # counters
> counter invalid_packages {
> comment "Invalid"
> }
>
> # limits
> limit icmp_limit {
> rate 10/second
> }
>
> chain incoming {
> type filter hook input priority 0; policy drop;
>
> # vars
> define chain_var = { 1.1.1.1 }
>
>
> # rules
> ct state invalid counter name invalid_packages log prefix "DROP invalid states" drop
> ct state {established, related} counter accept comment "Allow open sessions"
> iifname "lo" accept comment "Allow loopback traffic"
> icmp type echo-request limit name icmp_limit accept comment "Allow icmp-ping"
> icmpv6 type echo-request limit name icmp_limit accept comment "Allow icmp-ping"
> icmp code 30 limit name icmp_limit accept comment "Allow icmp-traceroute"
> icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } limit name icmp_limit accept comment "Allow necessary icmpv6-types for ipv6 to work"
> udp dport 46251 log prefix "DROP" counter name invalid_packages drop
>
> counter comment "COUNT example-incoming-drop"
> log prefix "DROP example-incoming"
> }
>
> chain outgoing {
> type filter hook output priority 0; policy drop;
>
>
> # rules
> udp dport 53 ip daddr $dns_servers accept
> tcp dport { 53, 853 } ip daddr $dns_servers accept
> meta l4proto { tcp, udp } th dport { 80, 443 } accept
> meta l4proto { icmp, icmpv6 } accept
>
> counter comment "COUNT example-outgoing-drop"
> log prefix "DROP example-outgoing"
> }
>
> chain translate {
> type nat hook postrouting priority 0; policy accept;
>
>
> # rules
> oifname "eno2" ip saddr $private_ranges masquerade
> oifname "eno3" ip saddr $private_ranges snat to 192.168.0.1
>
> counter comment "COUNT example-translate-accept"
> }
>
> }