# 1. 清空所有规则iptables -F iptables -X iptables -Z# 2. 设置默认策略(拒绝所有,按需开放)iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT# 3. 允许本地回环接口iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT# 4. 允许已建立的连接和相关的连接iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT# 5. 开放SSH服务(限制源IP)iptables -A INPUT -p tcp --dport22-s192.168.1.0/24 -j ACCEPT# 6. 开放Web服务(HTTP/HTTPS)iptables -A INPUT -p tcp --dport80-j ACCEPT iptables -A INPUT -p tcp --dport443-j ACCEPT# 7. 允许ping(ICMP)iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT# 8. 记录被拒绝的数据包(最后一条规则)iptables -A INPUT -j LOG --log-prefix"IPTABLES-DROP: "详细解释这个iptables防火墙脚本
一、脚本解析
第1部分:初始化清空
# 1. 清空所有规则iptables -F# 清空所有链中的所有规则iptables -X# 删除所有用户自定义的链iptables -Z# 将所有链的计数器归零作用:相当于"重置"防火墙,从干净状态开始配置
第2部分:设置默认策略
# 2. 设置默认策略(拒绝所有,按需开放)iptables -P INPUT DROP# 默认丢弃所有进入本机的数据包iptables -P FORWARD DROP# 默认丢弃所有转发的数据包iptables -P OUTPUT ACCEPT# 默认允许所有从本机出去的数据包白名单思想:
先禁止所有,再逐个开放需要的服务
为什么OUTPUT默认允许?
- 大多数情况下,本机主动发起的连接应该允许
- 如果需要更严格,可以设置
OUTPUT DROP,然后开放特定端口
第3部分:允许本地回环
# 3. 允许本地回环接口iptables -A INPUT -i lo -j ACCEPT# 允许进入lo网卡的数据iptables -A OUTPUT -o lo -j ACCEPT# 允许从lo网卡出去的数据回环接口(lo):
- 虚拟网卡,地址是127.0.0.1
- 用于本机程序间的通信
- 必须开放,否则很多服务无法正常运行
参数解释:
-i lo:input interface,进入的网卡是lo-o lo:output interface,出去的网卡是lo-j ACCEPT:jump to ACCEPT,接受这个数据包
第4部分:允许已建立的连接
# 4. 允许已建立的连接和相关的连接iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT这是最关键的一条规则!
作用:允许响应数据包回来
举例说明:
你访问百度网站: 1. 你:发送请求到百度(OUTPUT链允许) 2. 百度:发送网页数据回来 3. 这条规则:允许百度的响应数据进入(因为是已建立的连接)连接状态:
ESTABLISHED:已建立的连接RELATED:相关的连接(比如FTP的数据连接)NEW:新的连接请求
第5部分:开放SSH服务
# 5. 开放SSH服务(限制源IP)iptables -A INPUT -p tcp --dport22-s192.168.0.0/16 -j ACCEPT作用:只允许特定网络的用户SSH登录
参数解释:
-p tcp:协议是TCP--dport 22:目标端口是22(SSH默认端口)-s 192.168.0.0/16:源IP地址范围(192.168.0.0-192.168.255.255)-j ACCEPT:允许通过
安全考虑:
限制SSH访问来源,防止全网被暴力破解
第6部分:开放Web服务
# 6. 开放Web服务(HTTP/HTTPS)iptables -A INPUT -p tcp --dport80-j ACCEPT# HTTPiptables -A INPUT -p tcp --dport443-j ACCEPT# HTTPS作用:允许所有人访问网站
- 80端口:普通HTTP网站
- 443端口:加密HTTPS网站
注意:这里没有限制源IP,意味着任何人都可以访问
第7部分:允许ping
# 7. 允许ping(ICMP)iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT作用:允许别人ping通本机
参数解释:
-p icmp:ICMP协议(ping使用的协议)--icmp-type echo-request:只允许ping请求(ping本机)- 不允许其他ICMP类型(如redirect、timestamp等)
为什么需要:
- 网络诊断和监控
- 如果不允许,别人无法ping通你的服务器
第8部分:记录被拒绝的数据包
# 8. 记录被拒绝的数据包(最后一条规则)iptables -A INPUT -j LOG --log-prefix"IPTABLES-DROP: "作用:记录所有被拒绝的连接尝试
重要:这是INPUT链的最后一条规则!
因为前面都没有匹配的数据包,才会走到这里
日志查看:
# 查看被拒绝的连接dmesg|grep"IPTABLES-DROP"# 或tail-f /var/log/kern.log|grep"IPTABLES-DROP"日志内容示例:
IPTABLES-DROP: IN=eth0 OUT= MAC=... SRC=1.2.3.4 DST=5.6.7.8 ...二、规则执行顺序图解
数据包进入 → INPUT链检查 ↓ 规则1:来自lo网卡? → 是 → 允许 ✓ ↓ 否 规则2:已建立的连接? → 是 → 允许 ✓ ↓ 否 规则3:访问22端口且来自192.168.x.x? → 是 → 允许 ✓ ↓ 否 规则4:访问80端口? → 是 → 允许 ✓ ↓ 否 规则5:访问443端口? → 是 → 允许 ✓ ↓ 否 规则6:ping请求? → 是 → 允许 ✓ ↓ 否 规则7:记录日志并丢弃 ✗关键点:
iptables规则从上到下匹配,第一次匹配后就不再检查后面的规则
三、这个脚本实现的防火墙效果
允许的:
- ✅ 本机内部通信(127.0.0.1)
- ✅ 本机发起的连接响应(比如浏览网页的回复)
- ✅ 192.168.x.x网络的SSH连接
- ✅ 任何人的HTTP/HTTPS访问
- ✅ 任何人的ping请求
拒绝的:
- ❌ 非192.168.x.x网络的SSH连接
- ❌ 其他所有端口的访问(如MySQL的3306、FTP的21等)
- ❌ 非ping的ICMP请求
四、实际应用注意事项
1. 防止把自己锁在外面
# 危险!如果SSH规则写错了,就再也连不上了# 解决方法:先设置一个临时规则,给自己留后门iptables -A INPUT -p tcp --dport22-s 你的IP -j ACCEPT2. 测试建议
# 1. 先不要设置默认DROP,而是用默认ACCEPT测试# 2. 配置好所有规则后,最后再设置默认策略# 3. 使用cron定时任务,5分钟后恢复默认规则(crontab -l;echo"*/5 * * * * iptables -P INPUT ACCEPT")|crontab-3. 保存规则
# CentOS/RHELserviceiptables save# Ubuntu/Debianiptables-save>/etc/iptables/rules.v4五、脚本的潜在问题
问题1:OUTPUT链过于宽松
# 当前:允许所有出去的数据# 风险:如果服务器被入侵,黑客可以随意向外连接# 更安全的做法:iptables -P OUTPUT DROP iptables -A OUTPUT -o lo -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -p tcp --dport53-j ACCEPT# DNSiptables -A OUTPUT -p udp --dport53-j ACCEPT# DNS# 再开放其他需要的端口问题2:缺少对异常数据包的防护
# 可以添加:# 阻止无效的TCP标志位iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP# Christmas包iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP# Null扫描# 阻止分片包(常用于攻击)iptables -A INPUT -f -j DROP