首先是发现域名无法访问, 能ping通IP和域名,那就是nginx未正确工作 使用
tailf /var/log/nginx/error.log |grep "accept4() failed (24: Too many open files)"
发现有大量的 accept4() failed (24: Too many open files) 被输出,这很不正常 vim /etc/nginx/nginx.conf
worker_rlimit_nofile 10000;
events {
worker_connections 9999;
}
配置的容量是满足日常需求的,
#keepalive_timeout 0;
keepalive_timeout 65;
#keepalive_timeout 15;
#keepalive_requests 100; # 单连接最大请求数
client_header_timeout 3m;
client_body_timeout 3m;
#client_header_timeout 10s; # 读取请求头超时
#client_body_timeout 10s; # 读取请求体超时
send_timeout 3m;
proxy_connect_timeout 60s; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 60s; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_send_timeout 60s;
# proxy_buffer_size 64k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
# proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
# proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
# proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传递请求,而不缓冲到磁盘
尝试调整转发等待时间效果也不明显
精确统计所有 TCP 状态
# 获取 worker PID
PID=$(pgrep -f "nginx: worker")
# 列出该进程所有 TCP 连接的状态分布(精确!)
ss -tnp | awk -v pid="pid=$PID" '$7 ~ pid {print $2}' | sort | uniq -c
监控 fd 数量变化(每 2 秒刷新)
PID=$(pgrep -f "nginx: worker")
watch -n 2 "ls /proc/$PID/fd | wc -l"
监控 TIME_WAIT 数量
watch -n 2 'ss -tan state time-wait | grep ":80\|:443" | wc -l'
查看请求nginx的IP链接
PID=$(pgrep -f "nginx: worker")
echo $PID
ss -tnp | grep "pid=40358" | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -20
查询登录系统IP
grep "Failed password" /var/log/secure | tail -100 | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head -20
把异常IP加入黑名单
1. 安装 iptables-services(如果尚未安装)
yum install -y iptables-services
2. 停用 firewalld(避免冲突)
systemctl stop firewalld
systemctl disable firewalld
3. 启用并启动 iptables 服务
systemctl enable iptables
systemctl start iptables
4. 添加黑名单规则
4.1.1 直接单条添加规则(例如封禁 220.202.27.51 和 192.168.10.100)
# 单个 IP
iptables -I INPUT -s 220.202.27.51 -j DROP
# 多个 IP(逐条加)
iptables -I INPUT -s 192.168.10.100 -j DROP
iptables -I INPUT -s 10.0.0.5 -j DROP
使用 -I INPUT(插入到链开头)比 -A(追加)更安全,确保规则优先匹配。
4.1.2. 保存规则(关键!否则重启丢失)
service iptables save
4.1.3. 验证
iptables -L INPUT -n --line-numbers
cat /etc/sysconfig/iptables | grep DROP
4.2 使用 ipset + iptables(适合大量 IP)
如果你要封 几十、几百甚至上万个 IP,用 ipset 性能更好(iptables 逐条匹配很慢)。
4.2.1. 安装 ipset
yum install -y ipset
4.2.2. 创建一个 IP 集合(名为 blacklist)
ipset create blacklist hash:ip hashsize 4096
4.2.3. 添加 IP 到集合
ipset add blacklist 220.202.27.51
ipset add blacklist 192.168.10.100
ipset add blacklist 10.0.0.5
# 或从文件批量导入
# while read ip; do ipset add blacklist $ip; done < /root/blacklist.txt
ipset add blacklist 220.202.27.51
ipset add blacklist 192.168.10.100
ipset add blacklist 10.0.0.5
# 或从文件批量导入
# while read ip; do ipset add blacklist $ip; done < /root/blacklist.txt
4.2.4. 让 iptables 引用这个集合
iptables -I INPUT -m set --match-set blacklist src -j DROP
4.2.5. 保存 iptables 和 ipset 规则
保存 iptables:
service iptables save
4.2.6.保存 ipset 规则到文件
ipset save > /etc/ipset.conf
正确完整流程(使用 ipset + iptables)
# 1. 安装所需软件(只需一次)
yum install -y iptables-services ipset
# 2. 停用 firewalld(避免冲突)
systemctl stop firewalld
systemctl disable firewalld
# 3. 启用 iptables 服务
systemctl enable --now iptables
# 4. 创建 ipset 集合
ipset create blacklist hash:ip
# 5. 添加黑名单 IP
ipset add blacklist 220.202.27.51
ipset add blacklist 192.168.10.100
# ... 或批量添加
# 6. 让 iptables 封禁该集合中的 IP
iptables -I INPUT -m set --match-set blacklist src -j DROP
# 7. 保存 iptables 规则(关键!)
service iptables save
# 8. 保存 ipset 规则到文件
ipset save > /etc/ipset.conf
# 9. 配置开机自动加载 ipset
echo "ipset restore < /etc/ipset.conf" >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
报错说明:
[root@localhost ~]# ipset create blacklist hash:ip
ipset v7.1: Set cannot be created: set with the same name already exists
[root@localhost ~]# ipset add blacklist 220.202.27.51
ipset v7.1: Element cannot be added to the set: it's already added
| 提示是 正常现象,说明:
| 名为 blacklist 的 ipset 集合 已经存在
| IP 220.202.27.51 已经被加入该集合
| 这其实是个好消息 —— 说明你之前已经配置过 ipset 黑名单,只是没意识到!
4.3 创建支持网段的集合
# 创建支持 CIDR 的集合
ipset create blacklist hash:net
# 添加你要封的网段(示例)
ipset add blacklist 112.96.222.0/24
ipset add blacklist 223.104.80.0/20
ipset add blacklist 223.72.47.0/24
# ... 其他网段
# 只添加**一条** iptables 规则(用 -I 插入到最前面)
iptables -I INPUT -m set --match-set blacklist src -j DROP
4.3.1保存配置
# 保存 iptables
service iptables save
# 保存 ipset
ipset save > /etc/ipset.conf
# 确保开机加载 ipset
grep -q "ipset restore" /etc/rc.d/rc.local || echo "ipset restore < /etc/ipset.conf" >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
持久化 ipset(防止重启丢失)
即使你之前创建过 blacklist,ipset 默认不会开机自动恢复!
1. 保存当前 ipset 到文件
ipset save > /etc/ipset.conf
2. 确保 /etc/rc.d/rc.local 能开机加载它
# 检查是否已有加载命令
grep -q "ipset restore" /etc/rc.d/rc.local || echo "ipset restore < /etc/ipset.conf" >> /etc/rc.d/rc.local
# 确保 rc.local 有执行权限
chmod +x /etc/rc.d/rc.local
CentOS 7 默认启用 rc-local.service,所以这样配置即可开机自动恢复 ipset。
4.4 ✅ 验证结果
# 应只有一条规则
iptables -S | grep blacklist
# 应显示新集合类型为 hash:net
ipset list blacklist
🔄 如果你想“重置”重新开始
可以先清空再重建:
# 删除旧集合(会丢失所有 IP!)
ipset destroy blacklist
# 重新创建
ipset create blacklist hash:ip
# 添加 IP
ipset add blacklist 220.202.27.51
# 添加 iptables 规则
iptables -I INPUT -m set --match-set blacklist src -j DROP
# 保存
service iptables save
ipset save > /etc/ipset.conf
规则不要重复导入否则会
[root@localhost ~]# ipset destroy blacklist
ipset v7.1: Set cannot be destroyed: it is in use by a kernel component
✅ 解决方法:先删除 iptables 中引用该集合的规则 步骤 1:查看哪些 iptables 规则在使用 blacklist
iptables -S | grep blacklist
输出如下:
[root@localhost ~]# iptables -S | grep blacklist
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
-A INPUT -m set --match-set blacklist src -j DROP
解决:
iptables -D INPUT -m set --match-set blacklist src -j DROP
# 重复执行 9 次
步骤 2:销毁旧的 ipset 集合
ipset destroy blacklist
🛡️ 防止未来重复添加的建议
方法 1:添加前先检查是否存在
# 如果规则不存在,才添加
if ! iptables -C INPUT -m set --match-set blacklist src -j DROP 2>/dev/null; then
iptables -I INPUT -m set --match-set blacklist src -j DROP
fi
🛡️ 长期加固:启用 Fail2Ban(强烈推荐)
即使你手动封了大网段,仍有新 IP 不断扫描。 Fail2Ban 能自动封禁新出现的暴力破解者:
yum install -y epel-release fail2ban
cat > /etc/fail2ban/jail.local <<EOF
[sshd]
enabled = true
maxretry = 3
bantime = 86400
findtime = 600
EOF
systemctl enable --now fail2ban
分析历史日志(如 SSH 暴力破解)
只匹配合法 IPv4
ss -tn state established | awk 'NR>1 {print $5}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort | uniq -c | sort -nr | head -20
🛠️ 建议操作
1. 立即封禁新出现的高频攻击 IP
# 创建支持网段的 blacklist(如果还没重建)
ipset create blacklist hash:net 2>/dev/null || echo "blacklist already exists"
# 封单个 IP(这些 IP 没有明显网段特征,先封单个)
ipset add blacklist 112.54.172.45
ipset add blacklist 220.196.248.130
ipset add blacklist 45.78.206.27
ipset add blacklist 45.78.219.121
ipset add blacklist 14.103.55.226
ipset add blacklist 14.103.179.212
ipset add blacklist 8.218.202.59
ipset add blacklist 176.65.151.22
ipset add blacklist 171.231.177.200
ipset add blacklist 125.76.228.194
ipset add blacklist 89.47.53.19
🔍 验证当前真实连接 IP
运行这个命令看真正的外部攻击者:
ss -tn state established | awk 'NR>1 {print $5}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort | uniq -c | sort -nr | head -10
如果输出如下:
[root@localhost ~]# ss -tn state established | awk 'NR>1 {print $5}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort | uniq -c | sort -nr | head -10
[root@localhost ~]# grep "Failed password" /var/log/secure | tail -50
Jan 29 15:47:55 localhost sshd[4128]: Failed password for root from 192.142.25.95 port 33454 ssh2
Jan 29 15:48:08 localhost sshd[4207]: Failed password for invalid user admin from 171.231.193.170 port 45308 ssh2
Jan 29 15:48:09 localhost sshd[4241]: Failed password for invalid user ubuntu from 130.12.181.59 port 37684 ssh2
Jan 29 15:48:10 localhost sshd[4259]: Failed password for root from 112.54.172.45 port 63158 ssh2
Jan 29 15:48:12 localhost sshd[4259]: Failed password for root from 112.54.172.45 port 63158 ssh2
Jan 29 15:48:14 localhost sshd[4259]: Failed password for root from 112.54.172.45 port 63158 ssh2
Jan 29 15:48:16 localhost sshd[4259]: Failed password for root from 112.54.172.45 port 63158 ssh2
Jan 29 15:48:16 localhost sshd[4265]: Failed password for invalid user ftpadmin from 45.78.219.121 port 50716 ssh2
Jan 29 15:48:18 localhost sshd[4312]: Failed password for invalid user admin from 130.12.181.59 port 37698 ssh2
Jan 29 15:48:19 localhost sshd[4259]: Failed password for root from 112.54.172.45 port 63158 ssh2
Jan 29 15:48:25 localhost sshd[4375]: Failed password for root from 220.196.248.130 port 43854 ssh2
Jan 29 15:48:26 localhost sshd[4368]: Failed password for invalid user admin from 130.12.181.59 port 59226 ssh2
Jan 29 15:48:29 localhost sshd[4402]: Failed password for invalid user guobin from 220.196.248.130 port 50140 ssh2
Jan 29 15:48:30 localhost sshd[4388]: Failed password for invalid user travel from 45.78.206.27 port 34060 ssh2
Jan 29 15:48:33 localhost sshd[4418]: Failed password for invalid user admin from 130.12.181.59 port 34084 ssh2
Jan 29 15:48:34 localhost sshd[4432]: Failed password for invalid user test from 171.231.177.200 port 49834 ssh2
Jan 29 15:48:39 localhost sshd[4468]: Failed password for invalid user solv from 195.178.110.26 port 55150 ssh2
Jan 29 15:48:41 localhost sshd[4466]: Failed password for invalid user user from 130.12.181.59 port 47998 ssh2
Jan 29 15:48:47 localhost sshd[4529]: Failed password for root from 112.54.172.45 port 55911 ssh2
Jan 29 15:48:49 localhost sshd[4529]: Failed password for root from 112.54.172.45 port 55911 ssh2
Jan 29 15:48:49 localhost sshd[4536]: Failed password for invalid user user from 130.12.181.59 port 47940 ssh2
[root@localhost ~]# ss -tn state established | awk 'NR>1 {print $5}' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort | uniq -c | sort -nr | head -10
[root@localhost ~]#
你遇到的情况非常典型: ✅ /var/log/secure 中有大量 SSH 暴力破解记录(说明攻击正在进行) ❌ 但 ss -tn state established 提取不到对应的 IPv4 地址
🔍 为什么 ss 看不到这些 IP?
因为 SSH 暴力破解连接通常是“短连接”:
攻击者发起 TCP 连接 → 发送错误密码 → 立即断开 而 ss -tn state established 只显示“已建立且未关闭”的连接 所以当你的命令运行时,那些攻击连接已经断开了,自然看不到 📌 结论: 不能依赖 ss 实时抓攻击 IP,而应直接从日志(如 /var/log/secure)分析!
✅ 正确做法:从 /var/log/secure 提取攻击 IP
1. 提取最近 100 条失败登录的 IP 并统计
grep "Failed password" /var/log/secure | tail -100 | \
awk '{print $(NF-3)}' | \
sort | uniq -c | sort -nr | head -20
grep "Failed password" /var/log/secure | tail -100 | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head -20
✅ $ (NF-3) 是日志中 IP 的固定位置(倒数第 4 个字段)
手动添加到 ipset(推荐先做)
# 确保 blacklist 是 hash:net 类型
ipset create blacklist hash:net 2>/dev/null
# 封高频 IP(单个 IP 自动视为 /32)
ipset add blacklist 112.54.172.45
ipset add blacklist 130.12.181.59
ipset add blacklist 220.196.248.130
ipset add blacklist 45.78.219.121
ipset add blacklist 192.142.25.95
✅ 验证是否封禁成功
# 检查 IP 是否在 blacklist 中
ipset test blacklist 112.54.172.45 && echo "✅ 已封禁" || echo "❌ 未封禁"
如果想删除规则
✅ 正确停用步骤
第一步:删除 iptables 中引用 ipset 的规则
# 先查看规则在 INPUT 链的第几行
iptables -L INPUT --line-numbers
# 假设输出中该规则是第 3 行(通常是你刚插入的那条),则删除第 3 行
iptables -D INPUT 3
🔍 更安全的方式(按内容匹配删除):
iptables -D INPUT -m set --match-set blacklist src -j DROP
iptables -D INPUT -m set --match-set 列表名称 src -j DROP
这条命令会 精确删除匹配的规则,无需知道行号。 第二步:销毁 ipset 集合(可选但推荐)
# 删除名为 'blacklist' 的 ipset 集合
ipset destroy blacklist
💡 如果你还想保留集合但清空内容,可用:
# 先查看规则在 INPUT 链的第几行
iptables -L INPUT --line-numbers
# 假设输出中该规则是第 3 行(通常是你刚插入的那条),则删除第 3 行
iptables -D INPUT 3
但既然你不想拦截了,直接 destroy 更干净。
注意:本文归作者所有,未经作者允许,不得转载