首页 / 帮助文档 / centos服务器防端口扫描安全防护配置

centos服务器防端口扫描安全防护配置

CentOS服务器暴露在公网时,端口扫描几乎是每分钟都在发生的事。攻击者用自动化工具批量探测22、3306、6379、8080等常见端口,一旦发现服务版本过旧或未授权访问,就会直接尝试爆破或利用漏洞。防端口扫描的核心思路不是让扫描完全“看不见”,而是让扫描行为变得成本极高、信息极难获取,同时保证正常业务连接不受影响。

下面从系统内核参数、防火墙策略、服务伪装、入侵检测和自动化封禁五个层面,给出一套可以直接落地的配置方案。以下操作以CentOS 7/8为主,部分命令在Rocky Linux和AlmaLinux同样适用。

一、先收紧内核网络参数,降低被扫描时的响应特征

扫描器判断端口是否开放,依赖的是目标主机返回的TCP响应包。如果系统内核默认响应过于“配合”,扫描器就能快速确认端口状态。修改/etc/sysctl.conf中的相关参数,可以显著增加扫描难度。

# 开启SYN Cookie保护,防止半连接队列被填满
net.ipv4.tcp_syncookies = 1

# 减少SYN-ACK重试次数,让扫描器更难判断端口是否真正开放
net.ipv4.tcp_synack_retries = 1

# 缩短TIME_WAIT状态时间,降低被用于指纹识别的连接残留
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1

# 禁止响应ICMP重定向,防止被用于路由探测
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# 开启反向路径过滤,丢弃伪造源地址的数据包
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# 记录并丢弃martian包(源地址不合法的包)
net.ipv4.conf.all.log_martians = 1

执行sysctl -p让参数立即生效。这些参数不会影响正常TCP连接,但会让nmap等工具的探测结果变得不稳定,尤其是SYN扫描和FIN扫描的准确率会明显下降。

二、用firewalld或iptables建立“白名单+限速”的访问控制

很多人防扫描的第一反应是“关闭所有不用的端口”,但更有效的做法是:对必须对外开放的端口做访问来源限制,对不需要对外开放的端口直接DROP而不是REJECT。DROP会让扫描器等待超时,大幅拖慢扫描速度。

如果使用firewalld,先移除所有默认放行规则,只开放必要服务,并绑定来源IP。

# 启动并启用firewalld
systemctl enable --now firewalld

# 默认区域设为drop,所有未明确允许的流量全部丢弃
firewall-cmd --set-default-zone=drop

# 仅允许特定IP访问SSH,例如办公室固定IP
firewall-cmd --permanent --zone=drop --add-rich-rule='rule family="ipv4" source address="203.0.113.50" port protocol="tcp" port="22" accept'

# 允许所有来源访问Web服务(80和443)
firewall-cmd --permanent --zone=drop --add-port=80/tcp
firewall-cmd --permanent --zone=drop --add-port=443/tcp

# 重载规则
firewall-cmd --reload

如果服务器必须对全网开放SSH端口,至少要用firewalld的限速功能,限制单个IP在单位时间内的新建连接数。

# 对22端口新建连接限速:每10秒最多3个新连接
firewall-cmd --permanent --zone=drop --add-rich-rule='rule family="ipv4" port port="22" protocol="tcp" accept limit value="3/m"'

使用iptables的服务器,可以这样配置:

# 默认策略:INPUT链DROP,OUTPUT链ACCEPT
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许回环接口
iptables -A INPUT -i lo -j ACCEPT

# 对SSH端口做连接频率限制:每60秒最多5个新连接,超出则丢弃
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name sshscan
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --name sshscan -j DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

# 开放Web端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

注意:DROP策略会让扫描器认为端口被过滤,而不是关闭。这比REJECT更有效,因为REJECT会立即返回ICMP不可达,等于直接告诉扫描器“这个IP存在,但端口关了”。

三、修改默认端口与服务指纹,增加扫描结果误判率

扫描器识别服务类型,靠的是端口号和服务返回的banner信息。把SSH从22改到高位端口(如22022),同时修改SSH服务的banner,可以让自动化扫描工具直接跳过你的服务器。

修改SSH端口:

# 编辑/etc/ssh/sshd_config
Port 22022
# 同时禁止root直接登录
PermitRootLogin no
# 关闭密码登录,改用密钥
PasswordAuthentication no

修改后执行systemctl restart sshd。如果服务器上有MySQL或Redis,同样建议修改默认端口。Redis尤其危险,默认6379端口经常被扫描后直接写入SSH公钥或挖矿脚本。

对于必须保留默认端口的服务,可以修改banner信息。以Apache为例,在httpd.conf中添加:

ServerTokens Prod
ServerSignature Off

这样Apache返回的响应头中不会包含详细版本号。Nginx则在nginx.conf的http块中设置:

server_tokens off;

对于SSH,可以在sshd_config中通过Banner指令指定一个自定义的登录提示文件,但更关键的是确保OpenSSH版本保持最新,因为旧版本的指纹特征非常明显,扫描器可以直接通过TCP握手特征判断出具体版本。

四、部署fail2ban实现自动化动态封禁

手动配置防火墙规则只能应对已知的固定来源IP,对于大规模分布式扫描,必须用fail2ban这类工具动态识别并封禁扫描源。fail2ban通过监控日志文件,匹配预设的失败模式,自动调用防火墙规则封禁来源IP一段时间。

安装fail2ban:

yum install -y epel-release
yum install -y fail2ban
systemctl enable --now fail2ban

创建自定义配置文件/etc/fail2ban/jail.local:

[DEFAULT]
# 封禁时间:24小时
bantime = 86400
# 查找时间窗口:10分钟
findtime = 600
# 最大失败次数:3次
maxretry = 3
# 忽略本机IP
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = 22022
logpath = /var/log/secure
backend = systemd

# 自定义端口扫描检测规则
[port-scan]
enabled = true
filter = port-scan
action = iptables-multiport[name=port-scan, port="1:65535", protocol=tcp]
logpath = /var/log/messages
maxretry = 5
findtime = 60
bantime = 86400

创建对应的过滤器文件/etc/fail2ban/filter.d/port-scan.conf:

[Definition]
failregex = ^.*TCP_IN Block.*SRC=.*$
ignoreregex =

这个过滤器会匹配内核日志中记录的TCP_IN Block事件。当内核的rp_filter或防火墙规则丢弃了大量来自同一IP的异常包时,fail2ban就会自动封禁该IP。重启fail2ban后,可以用fail2ban-client status port-scan查看封禁情况。

fail2ban的优势在于动态响应,不需要人工干预。对于持续扫描的IP,封禁24小时后自动解封,如果对方继续扫描,会再次被封禁。这种方式比永久封禁更灵活,避免误伤动态IP池中的正常用户。

五、利用psad检测端口扫描并主动告警

psad(Port Scan Attack Detector)是专门用于检测端口扫描的轻量级工具。它通过分析iptables日志,识别SYN扫描、FIN扫描、UDP扫描等多种扫描模式,并可以通过邮件发送告警。

安装psad:

yum install -y psad

编辑/etc/psad/psad.conf,设置告警邮箱和检测灵敏度:

EMAIL_ADDRESSES root@localhost;
HOSTNAME yourserver.example.com;
ENABLE_AUTO_IDS Y;
AUTO_IDS_DANGER_LEVEL 3;

同时需要确保iptables规则中加入了日志记录,psad才能读取到扫描日志。在INPUT链的DROP规则之前添加:

iptables -A INPUT -j LOG --log-prefix "TCP_IN Block: "
iptables -A INPUT -j LOG --log-prefix "UDP_IN Block: " -p udp

注意日志规则要放在DROP规则之前,否则被丢弃的包不会进入日志。psad运行后,会持续监控日志,当检测到某个IP在短时间内触发了大量DROP记录时,会根据危险等级自动将该IP加入临时封锁列表,或发送邮件告警。

psad和fail2ban可以同时使用,两者侧重点不同:fail2ban关注应用层认证失败,psad关注网络层的扫描行为。两者结合能覆盖大部分攻击场景。

六、关闭不必要的系统服务与ICMP响应

CentOS默认安装后,可能有一些不必要的服务在监听端口。用ss -tulnp命令查看当前所有监听端口,逐个确认哪些是业务必需的。

# 查看所有监听端口及对应进程
ss -tulnp

# 关闭并禁用不需要的服务,例如avahi-daemon
systemctl disable --now avahi-daemon

# 关闭rpcbind(如果不需要NFS)
systemctl disable --now rpcbind

# 关闭postfix(如果不需要本地邮件投递)
systemctl disable --now postfix

对于ICMP协议,建议直接丢弃所有外部ICMP请求。虽然这会让ping不通,但能有效隐藏主机存活状态。在/etc/sysctl.conf中添加:

net.ipv4.icmp_echo_ignore_all = 1

如果业务需要允许ping,至少限制ICMP速率:

# 每秒最多处理1个ICMP echo请求
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 2 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
七、定期审计与日志监控

安全配置不是一次性的工作。建议每周检查一次防火墙规则、fail2ban封禁列表和系统日志,确认是否有新的扫描来源或异常连接。

# 查看当前防火墙规则
firewall-cmd --list-all

# 查看fail2ban封禁状态
fail2ban-client status

# 查看最近被封禁的IP
fail2ban-client status sshd | grep "Banned IP"

# 查看系统认证日志中失败的登录尝试
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20

对于高频扫描IP,可以进一步分析其来源ASN和地理位置,如果确认是恶意扫描源,可以在防火墙中永久封禁整个IP段。但要注意不要误封CDN节点或云服务商的正常IP段。

最后强调一点:防端口扫描的本质是提高攻击者的时间成本和信息获取难度。没有任何单一方案能完全阻止扫描,但通过内核参数调整、防火墙DROP策略、服务端口修改、fail2ban动态封禁和psad检测告警的组合,可以让绝大多数自动化扫描工具在探测你的服务器时无功而返。正常用户通过白名单或正确的端口和密钥认证,完全不会感受到这些防护措施的存在。