我面临一些主机向我的网络服务器发送大量请求的情况(NGINX)。我尝试通过 iptables 来阻止它们,ipset和一条古老的优良DROP
规则。
该规则对于连接有效NEW
,但是一旦小偷可以进入并建立ESTABLISHED
或RELATED
连接,我的 DROP 规则就会失败,因为我的防火墙也有iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
规则。
我的防火墙配置的相关部分是:
# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
DROP all -- 0.0.0.0/0 0.0.0.0/0 match-set Blacklist src
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443
DROP all -- 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
该Blacklist
ipset 包含有问题的 IP:
# ipset list Blacklist | grep <attacking-server-ip>
<attacking-server-ip>
问题是:我怎样才能终止所有 TCP 连接,即使是已建立或相关的连接?
我尝试过的事情:
停止-等待-30 秒-启动网络服务器(service nginx stop && sleep 30 && service nginx start
) - 值得一试,但由于连接已经建立,因此它会持续存在。
conntrack --flush
和conntrack -F
。无影响
tcpkill
:只要我保持进程运行,它就可以正常工作。但是一旦我关闭进程,连接就会恢复。我真的无法解释
conntrack -D --orig-src <attacking-server-ip>
:连接被删除,但随后又立即出现。
要检查连接,我使用:
netstat -putan | grep '<attacking-server-ip>'
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60763 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60807 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60545 ESTABLISHED 2372190/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59785 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59730 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59841 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60578 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60941 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59390 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59849 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60744 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59766 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59819 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60679 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59603 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60134 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60907 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59732 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60128 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60437 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59623 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59356 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60502 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59414 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60592 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59370 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60861 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59783 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59858 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59769 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60817 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59393 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60479 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60450 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59401 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60838 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60123 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60854 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59445 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59419 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60111 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60934 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60510 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60832 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60922 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60447 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60171 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60536 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59344 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59394 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59369 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60601 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59754 TIME_WAIT -
tcp 0 5534 <my-server-ip>:443 <attacking-server-ip>:60954 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60895 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60236 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60099 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:59460 TIME_WAIT -
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60570 ESTABLISHED 2372191/nginx: work
tcp 0 0 <my-server-ip>:443 <attacking-server-ip>:60555 ESTABLISHED 2372191/nginx: work
还:
# conntrack -L --orig-src <attacking-server-ip>
tcp 6 431977 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=62907 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=62907 [ASSURED] mark=0 use=1
tcp 6 431989 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63062 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63062 [ASSURED] mark=0 use=1
tcp 6 431976 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=62882 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=62882 [ASSURED] mark=0 use=1
tcp 6 299 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63215 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63215 [ASSURED] mark=0 use=1
tcp 6 431975 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=62869 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=62869 [ASSURED] mark=0 use=1
tcp 6 271 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=62800 dport=443 [UNREPLIED] src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=62800 mark=0 use=1
tcp 6 299 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63211 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63211 [ASSURED] mark=0 use=1
tcp 6 431977 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=62902 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=62902 [ASSURED] mark=0 use=1
tcp 6 431987 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63038 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63038 [ASSURED] mark=0 use=1
tcp 6 431999 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63195 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63195 [ASSURED] mark=0 use=1
tcp 6 431976 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=62887 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=62887 [ASSURED] mark=0 use=1
tcp 6 431988 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63050 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63050 [ASSURED] mark=0 use=1
tcp 6 431999 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63201 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63201 [ASSURED] mark=0 use=1
tcp 6 431998 ESTABLISHED src=<attacking-server-ip> dst=<my-server-ip> sport=63181 dport=443 src=<my-server-ip> dst=<attacking-server-ip> sport=443 dport=63181 [ASSURED] mark=0 use=1
conntrack v1.4.5 (conntrack-tools): 14 flow entries have been shown
答案1
您必须在状态接受规则之前测试黑名单,否则您的测试将永远无法达到,因为它是短路。
代替:
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m set --match-set Blacklist src -j DROP
颠倒它们的顺序:
iptables -A INPUT -m set --match-set Blacklist src -j DROP
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
您现在可以通过在第一个位置插入规则来执行此操作:
iptables -I INPUT -m set --match-set Blacklist src -j DROP
您也可以这样做,而不是上面的操作:
conntrack
使用命令及其-D
/--delete
命令删除 conntrack 条目一旦删除该条目,连接将通过 NEW 状态恢复(因为 Netfilter 已将 TCP 设置为恢复模式默认情况下),并且仍应被黑名单阻止,处于第二位,除非服务器先回复,从而重新建立连接。因此必须执行以下其中一项操作:
终止套接字(不终止进程,但显然让进程在此套接字上获取错误
ECONNABORTED
)较新的 Linux 内核可以
ss --kill
使用其内置的过滤逻辑强制终止套接字。示例(源和目标始终从本地系统查看,因此反转。还请注意括号之间的空格):ss --kill -tn 'dst == 192.0.2.2 and ( sport == 80 or sport == 443 )'
(或者仅仅是目的地,无论如何它都与攻击者有关)。
与此不同
tcpkill
,它不涉及向任何地方发送自定义数据包,而是直接使用内核 API 对套接字执行。
例如,如果黑名单是单个 IP 地址的列表,则可以这样做以从 conntrack 状态中删除所有攻击者 IP 地址和套接字状态。
ipset save Blacklist | awk '/^add/ { print $3 }' |
while read ip; do
conntrack -D -s $ip
ss -K -n dst $ip
conntrack -D -s $ip # again: in case of race between two previous
done
如果脚本将条目添加到黑名单(通常类似于失败2ban和actionban = ipset ...
中的/etc/fail2ban/action.d/iptables-ipset-proto4.conf
)被更改为每次运行conntrack
和ss
命令时也运行,那么您不必反转 INPUT 规则,并且可以节省一些 CPU 和内存(防火墙中节省一点,而nginx)。
如果不关闭套接字,服务器迟早会发射处于连接跟踪状态 NEW 的数据包(尽管没有 TCP SYN 标志),它将重新建立连接跟踪一旦攻击者回复(仍然处于已建立的 TCP 连接中),则进入 ESTABLISHED 状态。这取决于此切换默认情况下是宽松的:
nf_conntrack_tcp_loose
- 布尔值
- 0 - 已禁用
- 非 0-启用(默认)
如果将其设置为零,我们将禁用拾取已经建立的连接。
这就是 OP 案例中连接被“恢复”的原因。为了避免这种情况发生(并改为获取 INVALID 状态):
sysctl -w net.netfilter.nf_conntrack_tcp_loose=0
这将阻止连接在之后恢复conntrack -F
(包括远程 SSH!,因此最好-D
按上述方式使用)。启用此功能可能仅对重新启动的防火墙路由器最有用。