Створити конфіг /etc/nftables.conf:
#!/usr/sbin/nft -f
# Hook order is: ingress -> prerouting -> input/output/forward -> postrouting
# see also https://xdeb.org/post/2019/setting-up-a-server-firewall-with-nftables-that-support-wireguard-vpn/
# Start by flushing all the rules.
flush ruleset
# Define variables
define ext_if = eno1
define lo_if = lo
define home_ip = 80.80.80.80
define vps_ip = 81.81.81.81
# include all files in a given directory using an absolute path
#include "/etc/nftables/*"
# Setting up a table, simple firewalls will only need one table but there can be multiple.
# The "inet" say that this table will handle both ipv4 (ip) and ipv6 (ip6).
# The name is "firewall" you can name it anything you like.
table inet firewall {
set tcp_accepted {
comment "Grant TCP access to these ports"
type inet_service;
elements = { http, https, smtp, submission }
}
set udp_accepted {
comment "Grant UDP access to these ports"
type inet_service;
elements = { ntp }
}
set trusted_ips {
comment "Grant all access from these IPs"
type ipv4_addr
flags interval
elements = { $home_ip, $vps_ip }
}
set blocked_ips {
comment "Deny access from these IPs"
type ipv4_addr
flags interval,timeout
}
counter cnt_ssh_blocked {
}
chain ssh {
limit rate over 3/minute counter name cnt_ssh_blocked log prefix "[nftables] ssh connection limit exceeded: " drop
accept
}
chain input {
# This line set what traffic the chain will handle, the priority and default policy.
# The priority comes in when you in another table have a chain set to "hook input" and want to specify in what order they should run.
# Use a semicolon to separate multiple commands on one row.
type filter hook input priority 0; policy drop;
# Drop invalid packets.
ct state invalid drop
# Drop none SYN packets.
tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop
# Limit ping requests.
ip protocol icmp icmp type echo-request limit rate over 1/second burst 5 packets drop
ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 1/second burst 5 packets drop
# Allow from specific ips
iifname $ext_if ip saddr @trusted_ips accept
# Deny from specific IPs
iifname $ext_if ip saddr @blocked_ips drop
# !!! Rules with "limit" need to be put before rules accepting "established" connections.
# Allow all incoming established and related traffic.
ct state established,related accept
# Allow loopback.
# Interfaces can by set with "iif" or "iifname" (oif/oifname). If the interface can come and go use "iifname", otherwise use "iif" since it performs better.
iif $lo_if accept
# With these allowed you are a good network citizen.
ip protocol icmp icmp type { destination-unreachable, echo-reply, echo-request, source-quench, time-exceeded } accept
# Without the nd-* ones ipv6 will not work.
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, echo-reply, echo-request, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert, packet-too-big, parameter-problem, time-exceeded } accept
# Allow needed tcp and udp ports.
iifname $ext_if tcp dport ssh ct state new jump ssh
iifname $ext_if tcp dport @tcp_accepted ct state new accept
iifname $ext_if udp dport @udp_accepted ct state new accept
}
chain forward {
type filter hook forward priority 0; policy drop;
# Drop invalid packets.
ct state invalid drop
# Deny from specific IPs
ip saddr @blocked_ips drop
# Forward all established and related traffic.
ct state established,related accept
}
chain output {
type filter hook output priority 0; policy accept;
# Deny from specific IPs
ip daddr @blocked_ips drop
}
}
sudo systemctl is-enabled nftables
sudo systemctl reload nftables
Цей релоад перевірить коректність правил і видасть помилку, якщо конфіг невалідний