Wener Notes

nftables 规则

约 6 分钟阅读

表达式

bash
# 翻译 iptables 规则为 nftables
sudo iptables-save > legacy-rules.txt
iptables-restore-translate -f legacy-rules.txt

nft list ruleset   # dump nftables 规则
nft -c -f rule.nft # check
nft -f rule.nft    # load  - 原子操作
  • accept、drop、queue、continue、return、jump chain、goto chain
  • masquerade - 源地址自动设置为出口地址

Table

  • chain 容器
    • 同一个 table 的 chain 不能有相同名字
  • name
    • 避免使用名称 inet, filter, nat, mangle
    • 不同 family 可以有相同名字的 table
  • family=ip, arp, ip6, bridge, inet, netdev
  • 建议大多数时候只用 table inet 作为 filter
  • 目前 NAT 相关规则主要支持 IPv4
    • 因此 masquerade 相关可以放到单独的 table ip 表
    • 例如 chain prerouting, postrouting, forward
  • 如果不考虑 IPv6 可以只用 table ip

地址类型

familydesc
ipIPv4 - 默认
ip6IPv6
inetIPv4/IPv6
arpIPv4 ARP
bridge经过桥接设备的包
netdev入口设备
bash
nft list tables # [<family>]
# nft [-n] [-a] list table [<family>] <name>
# nft (add | delete | flush) table [<family>] <name>

单文件 reload

text
flush table ip wode
flush table inet wode

table ip wode {
}

table inet wode {
}

或者 replace 也是安全的

text
replace table ip mytable {
}
bash
nft -f /etc/nftables/wode.nft

Chain

  • rule 容器
  • type=filter, route, nat
    • filter - 过滤
      • 支持 arp, bridge, ip, ip6, inet
    • route
      • 支持 ip, ip6
    • nat
      • 支持 ip, ip6
  • hook
    • ip, ip6, inet 支持 prerouting, input, forward, output, postrouting
    • arp 支持 input, output
    • bridge
    • netdev 支持 ingress, egress
  • priority - 优先级
  • policy - 默认规则
    • accept, drop, queue, continue, return, jump chain, goto chain
  • base chain
    • 指的是直接与内核数据包处理钩子(hook)关联的链。
    • 不是通过 jump 调用的链,而是内核在数据包进入网络栈时直接调用的入口点。
    • input、output、forward、prerouting、postrouting
    • 必须指定默认策略
bash
# nft (add | create) chain [<family>] <table> <name> [ \{ type <type> hook <hook> [device <device>] priority <priority> \; [policy <policy> \;] \} ]
# nft (delete | list | flush) chain [<family>] <table> <name>
# nft rename chain [<family>] <table> <name> <newname>

hook

hookdesc
prerouting所有进入系统的包,在路由之前处理,可用于过滤和修改属性
input进入 本地 系统的包
forward转发到其他 host 的包
output本地 发出的包
postrouting所有离开系统的包
ingress
egress

priority

PRInamedefdesc
-400NF_IP_PRI_CONNTRACK_DEFRAGpriority of defragmentation
-300rawNF_IP_PRI_RAWtraditional priority of the raw table placed before connection tracking operation
-225NF_IP_PRI_SELINUX_FIRSTSELinux operations
-200NF_IP_PRI_CONNTRACKConnection tracking operations
-150mangleNF_IP_PRI_MANGLEmangle operation
-100dstnatNF_IP_PRI_NAT_DSTDNAT
0filterNF_IP_PRI_FILTERfiltering operation, the filter table
50securityNF_IP_PRI_SECURITYPlace of security table where secmark can be set for example
100srcnatNF_IP_PRI_NAT_SRCSNAT
225NF_IP_PRI_SELINUX_LASTSELinux at packet exit
300NF_IP_PRI_CONNTRACK_HELPERconnection tracking at exit

bridge priority

NameValueHooks
dstnat-300prerouting
filter-200all
out100output
srcnat300postrouting

Rule

  • 定义 action
  • handle - 内部标识, 序号
bash
# nft add rule [<family>] <table> <chain> <matches> <statements>
# nft insert rule [<family>] <table> <chain> [position <handle>] <matches> <statements>
# nft replace rule [<family>] <table> <chain> [handle <handle>] <matches> <statements>
# nft delete rule [<family>] <table> <chain> [handle <handle>]

匹配

  • meta (元属性,如接口)
    • oif、iif、oifname、iifname
  • icmp (ICMP 协议)
    • type
  • icmpv6 (ICMPv6 协议)
    • type
  • ip (IP 协议)
    • protocol
    • daddr
    • saddr
  • ip6 (IPv6 协议)
    • daddr
    • saddr
  • tcp (TCP 协议)
    • dport
    • sport
  • udp (UDP 协议)
    • dport
    • sport
  • sctp (SCTP 协议)
    • dport
    • sport
  • ct (链接跟踪)
    • state new | established | related | invalid
bash
# 查看端口
nft describe tcp dport

nft

  • \ 续行
  • # 注释
  • 标识符 ^[a-zA-Z][a-zA-Z0-9/\_.]*
    • 可使用双引号避免冲突
  • nft.8
text
# 引入文件
# -I/--includepath
# 忽略 . 开头文件
include filename

# 定义变量
define variable = expr
# 使用变量
$variable

nft cli

bash
# 描述信息
nft describe tcp flags
nft describe ct_state
nft describe icmp type

主要操作对象

  • rulset - 所有的 table 和 chain
    • {list | flush} ruleset [family]
  • table
    • chain 容器
    • 通过 地址类型和名字标识
text
{add | create} table [family] table [{ flags flags ; }]
{delete | list | flush} table [family] table
list tables [family]
delete table [family] handle handle
  • chain
    • rule 容器
    • 区分 base chian 和 regular chain
    • base - entry point for packets from the networking stack
      • 支持 policy - 默认 accept
    • regular - may be used as jump target and is used for better rule organization
    • chain type
typefamilieshooks
filterallall
natip, ip6, inetprerouting, input, output, postrouting
routeip, ip6output
  • nat 通过做 NAT 处理,只处理第一个包 - 用于 created conntrack entry
text
{add | create} chain [family] table chain [{ type type hook hook [device device] priority priority ; [policy policy ;] }]
{delete | list | flush} chain [family] table chain
list chains [family]
delete chain [family] table handle handle
rename chain [family] table chain newname
  • rule
    • 实际操作规则
text
{add | insert} rule [family] table chain [handle handle | index index] statement ... [comment comment]
replace rule [family] table chain handle handle statement ... [comment comment]
delete rule [family] table chain handle handle
  • set - {80,443}
    • 区分匿名集合和有名字的集合
    • 用于辅助定义
    • 用过 @set_name 引用
text
add set [family] table set { type type | typeof expression ; [flags flags ;] [timeout timeout ;] [gc-interval gc-interval ;] [elements = { element[, ...] } ;] [size size ;] [policy policy ;] [auto-merge ;] }
{delete | list | flush} set [family] table set
list sets [family]
delete set [family] table handle handle
{add | delete} element [family] table set { element[, ...] }
  • map
  • element
  • flowtable
    • accelerate packet forwarding in software
    • layer 3/4
  • 状态对象
    • counter
    • quota
  • ct helper
    • 定义 connection tracking helper
    • 用于 ct helper set
  • ct timeout
    • update connection tracking timeout
  • ct expectation
    • create connection expectations
    • 用于 ct expectation set
  • counter
  • quota

默认规则

bash
# 清空
flush ruleset

# 基础 IPv4/IPv6 有状态的防火墙 - 用户服务器或工作站
table inet filter {
	chain input {
    # 默认 drop input
		type filter hook input priority 0; policy drop;

    # 允许本地流量
		iifname lo accept \
		comment "Accept any localhost traffic"

    # 允许出去的流量
		ct state { established, related } accept \
		comment "Accept traffic originated from us"

    # 丢弃无效连接
		ct state invalid drop \
		comment "Drop invalid connections"

    # 113 端口返回端口不可达
    # https://en.wikipedia.org/wiki/Ident_protocol
    # https://github.com/janikrabe/oidentd
    # apk add oidentd
		tcp dport 113 reject with icmpx type port-unreachable \
		comment "Reject AUTH to make it fail fast"

		# ICMPv4
    # 接受指定类型的 icmp 类型
		ip protocol icmp icmp type {
			echo-reply,  # type 0
			destination-unreachable,  # type 3
			time-exceeded,  # type 11
			parameter-problem,  # type 12
		} accept \
		comment "Accept ICMP"

    # 限制 ping 速率
		ip protocol icmp icmp type echo-request limit rate 1/second accept \
		comment "Accept max 1 ping per second"

		# ICMPv6

		ip6 nexthdr icmpv6 icmpv6 type {
			destination-unreachable,  # type 1
			packet-too-big,  # type 2
			time-exceeded,  # type 3
			parameter-problem,  # type 4
			echo-reply,  # type 129
		} accept \
		comment "Accept basic IPv6 functionality"

		ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 1/second accept \
		comment "Accept max 1 ping per second"

    # IPv6 SLAAC 协议
		ip6 nexthdr icmpv6 icmpv6 type {
			nd-router-solicit,  # type 133
			nd-router-advert,  # type 134
			nd-neighbor-solicit,  # type 135
			nd-neighbor-advert,  # type 136
		} ip6 hoplimit 255 accept \
		comment "Allow IPv6 SLAAC"

    # IPv6 多播链路发现
		ip6 nexthdr icmpv6 icmpv6 type {
			mld-listener-query,  # type 130
			mld-listener-report,  # type 131
			mld-listener-reduction,  # type 132
			mld2-listener-report,  # type 143
		} ip6 saddr fe80::/10 accept \
		comment "Allow IPv6 multicast listener discovery on link-local"
	}

	chain forward {
    # 默认不允许转发
		type filter hook forward priority 0; policy drop;
	}

	chain output {
    # 默认允许 output
		type filter hook output priority 0; policy accept;
	}
}
# 包含自定义规则
include "/etc/nftables.d/*.nft"

masquerade

bash
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 100;
    # 源地址自动设置为出口地址
    oifname "enp0s2" masquerade
  }
}

允许常用端口

bash
table inet filter {
  chain input {
    type filter hook input priority 0;
    # allow ssh,http
    tcp dport {ssh,http,https} accept
    # http3 use udp
    udp dport {https} accept
  }
}

限定来源地址

bash
define ALLOWED_NETS = {
  192.168.0.0/16,
  1.2.3.4
}

table inet firewall {
  chain inbound {
    type filter hook input priority 0; policy drop;
    # 限定来源访问
    tcp dport { http, https } ip saddr $ALLOWED_NETS accept
    udp dport { http, https } ip saddr $ALLOWED_NETS accept
  }
}

所有端口重定向到 22

text
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
    tcp dport != 22 redirect to 22
  }
  chain postrouting {
    type nat hook postrouting priority 0;
  }
}

参考

关联信息

反向链接、本文链接的其他页面和外部资料。

References

其他外链5 条
最近更新commit 26f39a6Edit

On this page