我看到许多关于暴力攻击、每 N 秒的连接数的文章,但我的情况不同,我有一个代理服务器,我只想将来自任何地方的连接限制为 1 个...再次,不是来自同一 IP,而是来自任何地方...我尝试使用 ufw 限制,但那是针对来自同一 IP 地址的连接,我只想要这样,如果有人当前连接到端口 3128,那么在当前连接完成之前,没有其他人可以连接。
答案1
UFW 正在使用iptables作为后端。 UFW 的限制规则基于 iptables'最近的match 不适合 OP 的用例。相关功能应该是连接限制匹配(并且对于nftables这CT计数表达)。
connlimit
允许您限制每个客户端 IP 地址与服务器的并行连接数(或客户端地址块)。
遗憾的是,该功能并非由 UFW 直接提供,UFW 称为简单防火墙是有原因的。相反,为了提供缺失的功能,UFW 提供 加载任何自定义 iptables 规则来自文件(只要它不在user.rules
/中user6.rules
)。所以这个答案实际上是一个iptables答案隐藏在 UFW 答案中。
独立iptables限制 TCP 端口 3128 上的并发连接数为 1 的规则可以这样写:
iptables -A INPUT -p tcp --dport 3128 -m conntrack --ctstate NEW -m connlimit --connlimit-upto 1 --connlimit-mask 0 --connlimit-saddr -j ACCEPT
-m conntrack --ctstate NEW
仅验证新连接,--connlimit-mask 0 --connlimit-saddr
将匹配任何源地址,并且--connlimit-upto 1
只允许一个连接跟踪符合条件的条目,结果才为真。
应将此规则放入iptables-save
格式为 (仅表示没有前导iptables
命令)的专用自定义链中,该ufw-after-input
链在 中定义/etc/ufw/after.rules
。因此它将使用-A ufw-after-input
而不是-A INPUT
。
的结尾/etc/ufw/after.rules
现在应该是这样的(至少对于 UFW 0.36 来说):
# don't log noisy broadcast
-A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
# allow only one established connection to port 3128
-A ufw-after-input -p tcp --dport 3128 -m conntrack --ctstate NEW -m connlimit --connlimit-upto 1 --connlimit-mask 0 --connlimit-saddr -j ACCEPT
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT
并重新加载防火墙规则:
ufw reload
笔记:
本地连接不会受到影响,并且由于多种原因,该规则无法在本地连接下正常工作。必须从远程验证此规则。
-A ufw6-after-input
IPv6:可以以相同的方式在 中插入相同的条目(这次以 开始)/etc/ufw/after6.rules
。请注意iptables和ip6tables不会将两个计数合并在一起:这将允许一个 IPv4 连接加一个 IPv6 连接。虽然示例中经常使用
--syn
,但如果需要,可以使用而不是-m conntrack --ctstate NEW
将 TCP 协议替换为 UDP 。-p udp
-p tcp
单个允许客户端的异常断开连接(例如:连接丢失)可能会导致套接字处于 FIN_WAIT 状态,并会导致延迟才能再次使用。此外,使用代理的浏览器可能会尝试通过它同时进行多个连接。仅允许一个连接可能会破坏浏览器的默认行为否定/降低规则。允许多个同时连接,使用反向iptables应该考虑以
-j REJECT
或政策结尾的规则。ufw default reject incoming