在Debian服务器上面对DDoS扫描和恶意端口探测,最直接有效的方案就是用iptables或nftables对特定端口做精细化访问控制,结合连接速率限制、SYN防护和黑名单机制,把攻击流量在内核层面直接丢弃。核心思路不是"装个防火墙就完事",而是针对你实际开放的业务端口(比如80、443、22、3306等),逐条制定规则:谁能连、连多少次、异常行为怎么处理。下面我把整套流程从安装到调优全部讲透。
一、Debian防火墙工具选择:iptables还是nftables
Debian 10及以上版本默认使用nftables作为底层框架,但iptables命令通过兼容层仍然可用。对于运维来说,iptables规则更直观、教程更多、排错更方便,所以本文以iptables为主线讲解,同时在关键处说明nftables的对应写法。如果你是全新安装的Debian 12,建议直接用nftables,语法更简洁。不管选哪个,核心逻辑完全一样:默认拒绝、按需放行、限制速率、日志记录。
二、安装和确认防火墙工具状态
Debian最小化安装通常不自带iptables管理工具,需要手动装:
apt update apt install iptables iptables-persistent netfilter-persistent
安装过程中会问你是否保存当前规则,选"Yes"。netfilter-persistent这个包的作用是让iptables规则在重启后自动加载,不然每次重启都得重新配。装完之后确认状态:
iptables -L -n -v nft list ruleset
三、制定默认策略:先堵后放
防火墙配置的黄金法则就是"默认丢弃,白名单放行"。先把所有入站、转发、出站全部设为DROP,然后只开放你真正需要的端口:
iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT
OUTPUT设为ACCEPT是因为服务器正常出站请求(比如DNS查询、系统更新)不能被拦。如果你的服务器是纯被动服务,也可以把OUTPUT设为DROP再单独放行必要的出站端口,但那样维护成本高,一般不推荐。
四、保留基础通行规则
在严格限制之前,必须先放行本地回环和已建立的连接,否则SSH一断你就进不去了:
iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
这两条规则的意思是:本机内部通信全部放行,已经建立的连接(比如你SSH登录后的会话)和相关联的数据包(比如FTP的数据通道)也放行。顺序很重要,这两条必须放在最前面。
五、针对特定端口的精细化限制
假设你的Debian服务器开放了以下端口:22(SSH)、80(HTTP)、443(HTTPS)、3306(MySQL)。每个端口的风险等级和限制策略完全不同。
5.1 SSH端口(22)防暴力破解
SSH是DDoS扫描和暴力破解的重灾区。建议只允许特定IP段访问,或者至少限制连接速率:
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -m conntrack --ctstate NEW -m limit --limit 3/min --limit-burst 5 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP
这条规则的含义是:来自192.168.1.0/24网段的新SSH连接,每分钟最多3个,突发最多5个,超出的直接丢弃。如果你没有固定IP,可以把-s参数去掉,但这样防护效果会弱很多。更好的做法是配合fail2ban做动态封禁。
5.2 Web端口(80/443)防CC攻击和扫描
Web端口是公开的,不能像SSH那样限制来源IP,但可以限制单个IP的连接速率和SYN包频率:
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m limit --limit 25/sec --limit-burst 100 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -m limit --limit 25/sec --limit-burst 100 -j ACCEPT
这里的参数意思是每秒最多25个新连接,突发100个。正常用户浏览网页完全够用,但自动化扫描工具每秒几百上千的请求会被直接卡住。如果你的网站流量大,可以把数值调高,比如50/sec、200/burst,根据实际情况来。
5.3 数据库端口(3306)严格白名单
MySQL端口绝对不能对公网开放,这是铁律。只允许应用服务器的IP访问:
iptables -A INPUT -p tcp --dport 3306 -s 10.0.0.5 -j ACCEPT iptables -A INPUT -p tcp --dport 3306 -j DROP
如果你有多台应用服务器,就多加几条-s规则。千万不要图省事把3306对0.0.0.0/0开放,那等于把数据库裸奔在互联网上。
六、SYN Flood防护:内核层面抗DDoS
SYN Flood是最常见的DDoS攻击类型,攻击者发送大量SYN包但不完成握手,耗尽服务器连接资源。Debian内核自带SYN Cookie和SYN Proxy机制,需要手动开启:
echo 1 > /proc/sys/net/ipv4/tcp_syncookies echo 1 > /proc/sys/net/ipv4/tcp_synack_retries echo 2 > /proc/sys/net/ipv4/tcp_max_syn_backlog
要让这些设置永久生效,编辑/etc/sysctl.conf:
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_syn_retries = 2 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1
执行sysctl -p使其生效。tcp_max_syn_backlog设为2048意味着内核可以同时处理2048个半开连接,对于一般服务器足够了。如果你面对的是大规模攻击,可以设到4096甚至更高,但要注意内存消耗。
七、ICMP限制:防止Ping扫描和Smurf攻击
很多人忽略ICMP,但Ping扫描是DDoS前哨侦察的常用手段。建议限制ICMP的频率和类型:
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/sec -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
每秒只允许1个Ping请求,超出的丢弃。如果你的服务器需要被监控系统Ping,可以把limit参数调高或者直接放行监控IP。注意不要完全禁止ICMP,因为路径MTU发现需要ICMP,全禁会导致某些连接异常。
八、配合fail2ban实现动态封禁
iptables的静态规则只能做基础防护,真正的智能封禁要靠fail2ban。它会监控日志文件,发现异常行为(比如SSH多次登录失败、Web页面频繁404)就自动把对方IP加入iptables黑名单:
apt install fail2ban cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
编辑jail.local,配置SSH和Web防护:
[sshd] enabled = true port = 22 filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 3600 [apache-badbots] enabled = true port = 80,443 filter = apache-badbots logpath = /var/log/apache2/access.log maxretry = 50 bantime = 7200
fail2ban会在/etc/fail2ban/filter.d/目录下创建对应的过滤规则。重启fail2ban服务后,它会每隔几秒扫描一次日志,自动把恶意IP封掉。这和iptables的速率限制形成双重防护。
九、日志记录和监控:知道谁在打你
防火墙规则里一定要加日志,不然被攻击了你都不知道。在每条DROP规则前面加一条LOG规则:
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4 iptables -A INPUT -j DROP
limit参数是为了防止日志爆满,每分钟最多记录5条。查看日志用:
tail -f /var/log/kern.log | grep IPTABLES-DROP
如果你想做更专业的流量分析,可以装iftop、nethogs或者vnStat,实时查看哪个IP在占带宽、哪个端口被扫描最多。这些信息对调整防火墙规则非常有价值。
十、nftables写法对照(Debian 12推荐)
如果你用的是Debian 12,可以直接用nftables,语法更现代:
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add rule inet filter input iif "lo" accept
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input tcp dport 22 ip saddr 192.168.1.0/24 limit rate 3/minute accept
nft add rule inet filter input tcp dport 22 drop
nft add rule inet filter input tcp dport 80 limit rate 25/second accept
nft add rule inet filter input tcp dport 443 limit rate 25/second accept
nft add rule inet filter input tcp dport 3306 ip saddr 10.0.0.5 accept
nft add rule inet filter input tcp dport 3306 dropnftables的优势是规则集是原子性的,要么全部生效要么全部不生效,不会出现iptables那种规则加载一半出错的情况。保存规则用:
nft list ruleset > /etc/nftables.conf systemctl enable nftables
十一、常见误区和实操建议
很多人配防火墙犯的最大错误是规则顺序乱放。iptables是从上到下逐条匹配的,一旦命中就停止,所以DROP规则必须放最后,ACCEPT规则放前面。另外不要盲目把所有端口都限速,业务端口限速太低会误杀正常用户,需要根据实际流量做压测调整。
还有一点:防火墙只是第一道防线。如果你面对的是真正的大流量DDoS(比如几十Gbps),单靠服务器本地防火墙根本扛不住,需要在上游网络层面做清洗。但对于绝大多数中小规模的端口扫描和小流量DDoS,本文这套方案足够应对。
最后提醒:每次改完iptables规则,先用iptables-save备份当前规则,确认没问题再应用新规则。如果配错了把自己锁在外面,只能通过控制台或者物理访问来救。生产环境建议先在测试机上验证,再上线。
