CentOS服务器在公网环境中最先要处理的不是复杂攻击,而是流量层面的失控。很多运维人员习惯把注意力放在系统补丁和密码强度上,却忽略了网卡上每一个异常的数据包都可能正在消耗带宽、暴露服务指纹或者为后续入侵做踩点。流量管控的核心思路只有一条:先限制不必要的通信,再对合法流量做精细化限速和审计。

检查当前服务器的流量走向是第一步。不要急着配置防火墙规则,先确认系统本身有没有被植入异常进程在对外发包。执行以下命令可以快速查看占用带宽的进程:

nethogs eth0

如果系统没有安装nethogs,可以用yum直接安装。这个工具能实时显示每个进程占用的上传和下载速率,比单纯看iftop更直观。一旦发现陌生进程名或者高流量进程与业务无关,立即用lsof -p PID查看它打开了哪些文件和网络连接。很多时候服务器变成肉鸡后,攻击者会运行一个伪装成系统服务的程序持续对外发包,nethogs能直接暴露它。

确认进程层面干净之后,再进入iptables规则设计。CentOS 7及之后版本默认使用firewalld作为前端管理工具,但底层依然是iptables。对于流量管控,建议直接使用iptables-save和iptables-restore来持久化规则,避免firewalld的富规则语法在复杂场景下难以维护。先设置默认策略:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

INPUT链默认丢弃意味着所有入站流量默认拒绝,只放行明确需要的端口。OUTPUT链默认允许是因为大多数服务器需要主动向外请求更新、DNS解析和业务回调。但这里有一个细节:如果服务器已经被入侵,恶意进程可以随意向外连接,所以更严格的做法是对OUTPUT也做限制,只允许特定用户或特定目的端口出站。不过初期运维可以先从INPUT入手,降低配置复杂度。

放行SSH管理端口时不要直接开放22。如果条件允许,把SSH端口改到高位端口,比如22022,并在iptables中只放行这个端口。同时配合ipset对管理IP做白名单,避免密码爆破流量持续消耗服务器资源。创建ipset集合:

ipset create adminip hash:ip
ipset add adminip 203.0.113.5
iptables -A INPUT -p tcp --dport 22022 -m set --match-set adminip src -j ACCEPT

这样即使有人扫描到SSH端口,非白名单IP的流量在进入SSH服务之前就被丢弃,连密码验证的机会都没有。ipset的匹配效率远高于逐条iptables规则,当白名单IP数量达到数百个时性能差异非常明显。

对于Web服务的流量管控,单纯放行80和443端口远远不够。CC攻击和慢速连接会占满Apache或Nginx的工作进程,导致正常用户无法访问。iptables的limit模块可以限制单个IP对80端口的并发连接数和新建连接速率:

iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j DROP
iptables -A INPUT -p tcp --dport 80 -m limit --limit 30/s --limit-burst 50 -j ACCEPT

第一条规则限制每个源IP对80端口的并发连接数不超过30个,超过的直接丢弃。第二条规则限制新建连接速率为每秒30个,突发容量50个。这两个规则组合起来能有效缓解CC攻击造成的连接耗尽。需要注意的是,connlimit模块在某些VPS内核中可能未加载,需要先确认lsmod | grep connlimit是否有输出。

Nginx层面也可以做流量控制,而且比iptables更灵活。在http块中定义limit_req_zone和limit_conn_zone:

limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;

然后在server或location中引用:

limit_req zone=req_per_ip burst=30 nodelay;
limit_conn conn_per_ip 20;

这样每个IP每秒最多20个请求,突发30个,超过的直接返回503。Nginx的限速基于请求数而不是数据包数,对HTTP层的攻击更精准。但Nginx限速不能替代iptables,因为如果攻击流量是TCP SYN洪水,Nginx根本看不到完整请求,必须由内核层面的iptables来丢弃。

SYN洪水防护需要开启内核的SYN Cookie机制。编辑/etc/sysctl.conf加入:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

然后执行sysctl -p生效。tcp_syncookies开启后,内核在SYN队列满时不再直接丢弃新连接,而是返回带有Cookie的SYN-ACK,只有收到合法ACK才建立连接。这能有效防御伪造源IP的SYN洪水。tcp_synack_retries和tcp_syn_retries降低重试次数,减少半连接占用时间。

对于UDP流量的管控容易被忽视。很多服务依赖UDP,比如DNS查询、NTP时间同步、某些游戏服务。但UDP没有连接状态,攻击者可以伪造源IP发送大量UDP包,服务器很难区分合法与非法流量。如果服务器不对外提供UDP服务,最直接的做法是在INPUT链中丢弃所有UDP:

iptables -A INPUT -p udp -j DROP

如果需要开放DNS服务,只放行53端口并限制单IP速率:

iptables -A INPUT -p udp --dport 53 -m limit --limit 50/s --limit-burst 100 -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j DROP

但要注意,如果服务器本身需要向外发起DNS查询,OUTPUT链放行UDP 53端口是必须的,同时要允许对应的响应回来。这里可以用状态匹配:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

这条规则放在INPUT链的最前面,允许所有已建立连接和关联连接的入站流量。这样服务器主动发起的DNS查询响应、HTTP请求响应都能正常回来,不需要为每个出站连接单独开放入站规则。

流量审计方面,iptables的LOG目标可以把被丢弃的包记录到系统日志,但直接记录所有丢弃包会产生大量日志,反而影响性能。建议只对特定可疑流量做日志,比如对22端口的连接尝试:

iptables -A INPUT -p tcp --dport 22 -m limit --limit 5/min -j LOG --log-prefix "SSH_ATTEMPT: "

这样每分钟最多记录5条SSH连接尝试日志,既能发现暴力破解行为,又不会淹没/var/log/messages。日志分析可以用简单的grep统计来源IP:

grep "SSH_ATTEMPT" /var/log/messages | awk '{print $NF}' | sort | uniq -c | sort -rn | head

这个命令能快速列出尝试连接SSH最多的IP,配合ipset自动封禁可以形成简单的动态防御。不过手动分析日志效率太低,生产环境建议使用fail2ban。在CentOS上安装fail2ban后,配置/etc/fail2ban/jail.local监控SSH和Nginx错误日志,自动将恶意IP加入iptables拒绝列表。fail2ban的核心价值在于自动化,它根据日志中的失败次数动态调整封禁策略,封禁时间可以设置为指数递增,比如第一次封禁10分钟,第二次1小时,第三次24小时。

流量管控还有一个重要维度是出站流量限制。如果服务器被植入挖矿程序,它会持续向外连接矿池,消耗大量出站带宽。即使INPUT链配置得再严格,出站流量不受控也会导致业务中断。限制出站流量的思路是只允许必要的目标端口和协议。例如服务器只需要向外访问HTTP和HTTPS,可以设置:

iptables -P OUTPUT DROP
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

这样任何试图连接非标准端口的进程都会被内核拒绝。但要注意,如果业务需要连接外部数据库、消息队列或第三方API的非标准端口,必须逐一放行。建议先在一台测试机上完整跑一遍业务,用tcpdump抓取所有出站连接的目标端口,确认清单后再应用到生产环境。

对于大流量业务,还需要考虑流量整形。tc命令可以限制网卡的总出站速率,防止单个服务占满带宽影响其他服务。例如限制eth0出站总带宽为100Mbps:

tc qdisc add dev eth0 root handle 1: htb default 10
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 100mbit

更精细的做法是按端口或IP做分类限速。比如限制某个IP的下载速度不超过10Mbps,可以用iptables打标记配合tc:

iptables -t mangle -A POSTROUTING -d 192.168.1.100 -j MARK --set-mark 10
tc filter add dev eth0 parent 1: protocol ip handle 10 fw flowid 1:10

这种组合配置相对复杂,但对于多租户环境或需要保证核心业务带宽的场景非常有效。不过tc规则在重启后会丢失,需要写入启动脚本或使用systemd服务持久化。

最后要强调流量监控的持续性。iptables规则配置完成后不是一劳永逸,需要定期检查规则是否生效、是否有新的异常流量模式。vnstat是一个轻量级的流量统计工具,可以按小时、天、月查看网卡流量趋势:

vnstat -i eth0 -h
vnstat -i eth0 -d

如果发现某个时间段流量突然暴增,结合当时的访问日志和系统日志排查原因。iftop可以实时查看哪些IP在与服务器通信,流量最大的连接一目了然。这些工具组合使用,才能在问题发生时快速定位是正常业务增长还是攻击流量。

CentOS的流量管控不是单一工具能解决的,需要内核参数、iptables规则、应用层限速和监控工具协同工作。每个层面解决不同维度的问题:内核处理SYN洪水,iptables处理连接数和包速率,Nginx处理请求级限速,监控工具提供决策依据。把这几层都配置到位,服务器才能在公网环境中稳定运行。