我想限制在 Linux 服务器上运行的给定服务的并发连接数。我的理解是,这可以iptables
使用connlimit
模块来实现。例如,如果我想限制到我的 SSH 服务器的并发连接数(假设默认策略是拒绝),那么这应该允许 10 个并发连接,第 11 个被拒绝(从内存中写入):
iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-upto 10 -j ACCEPT
问题是,在我正在构建的新服务器上,我想使用 来实现防火墙nftables
。虽然我connlimit
在手册页中可以找到提及的内容,但它只是说consider native interface. Refer to Meters
。我搜索了有关 Meters 的信息,虽然它看起来非常适合速率限制,但我找不到任何建议我可以做 的等效内容connlimit
。
因此,如果我想使用nftables
,我该如何创建一个仅匹配最多 X 个并发连接的规则?
答案1
有一个新的扩展nft_connlimit那是添加自Linux内核4.18以来,提供了一种ct count
表达方式。
对于这种情况,等效规则(从头开始)将是:
nft flush ruleset
nft add table ip filter
nft add chain ip filter input '{ type filter hook input priority 0; }'
nft add rule ip filter input tcp dport 22 ct count 10 counter accept
# nft add rule ip filter input tcp dport 22 counter reject with tcp reset
一些评论:
像往常一样
counter
是可选的,用于获取计数器以nft list ruleset
了解规则触发的次数。将上述所有出现的 替换
ip
为ip6
将获得 IPv6 的等效值。现在更有趣的是使用inet
来获得合并由于 IPv4 和 IPv6 SSH 连接由 conntrack 一起统计,因此将它们合并在一起。必须避免使用 4.19.0 和 4.19.9 之间的内核,因为使用此功能可能会导致主机崩溃。(即将推出)内核 4.20 和内核 4.19.10 包含几个与 conncount 相关的补丁,可修复崩溃和错误计数。内核 4.18.x 的状态未知。
更新:限制每个网络,而不仅仅是每个 IP,相当于 iptables'--connlimit-mask
重读netfilter-devel 邮件列表中的初始补丁文档稀少,ct count
并不局限于单独使用(或仅限于上述示例)。它可以在meter
表达式/列表用于更复杂的用法。
如果想要拒绝每个随机 /24 网络源 IP 上超过 3 个连接数的到端口 2222(某个进程正在监听)的连接,则应使用以下规则(从 nft 0.9.0 / 内核 4.19.10 开始):
nft add rule ip filter input tcp dport 2222 meter test-2222-count-meter '{ ip saddr & 255.255.255.0 ct count over 3 }' counter reject with tcp reset
这将创建一个仪表列表test-2222-count-meter
将动态添加相关的“映射”数据(针对每个匹配连接的不同 /24 网络)。我不确定过时的数据(即不再有任何连接的 /24 网络)是否会通过垃圾收集被删除。
可以列出计量表的内容(它不会显示已达到的计数,只会显示发现新网络时动态添加的“地图”)。例如,在10.0.3.1
、10.0.3.66
和10.0.4.5
的一些连接之后172.31.4.5
:
# nft list meter ip filter test-2222-count-meter
table ip filter {
meter test-2222-count-meter {
type ipv4_addr
size 65535
elements = { 10.0.3.0 : ct count over 3 , 10.0.4.0 : ct count over 3 , 172.31.4.0 : ct count over 3 }
}
}