首页  /  Linux 进阶  /  正文

iptables 封端口与 filter 实战

Linux 进阶 2026-10-02📖 11 分钟👁 —
🛡️ Linux 进阶 · iptables 防火墙第 2 / 4 页1234📖 完整导航 →

一、封端口和常用参数

1. 先来个最简单的例子

配置前要清空:

iptables -F # 清空默认规则
iptables -X # 清空自定义链的规则
iptables -Z # 清空统计与计数

[root@localhost ~]# iptables -F
[root@localhost ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination    

# 拒绝所有人访问22端口(不要真的执行啊!)
# 添加规则(指定表、链、规则)
# 涉及端口必须指定 协议和端口
iptables -t filter -I INPUT -p tcp --dport 22 -j DROP
# 网络中端口有两种:源端口和目标端口

# 删掉规则(-F 肯定慎用)
iptables -t filter -D INPUT 1 
# 1 表示删第一条,查看行数:
iptables -nL --line-number

建议顺手配个定时任务,隔几分钟把防火墙关掉,免得自己进不去。

2. 三段参数总结

iptables 的命令我习惯拆成三段看:前面是表、中间是条件、尾端是动作。

中间这一段是匹配条件:

中间参数:-p 协议、--dport/--sport 端口、-s/-d 地址、-m 模块、-i/-o 网卡

尾端这一段是匹配上之后干什么:

尾端操作:-j 后面跟 DROP、REJECT 还是 ACCEPT

考虑到安全性,一般用 DROP。这里要注意 DROP 和 REJECT 在客户端那头的表现完全不一样:DROP 什么都不回,客户端只会一直等到超时或者自己重试;REJECT 会把拒绝信息返回给客户端,客户端立刻收到"连接被拒绝"。

对链本身进行操作的是另外几个参数,记住 -A -I -D 都是对链动手就很好理解了:

对链的操作:-L 看、-n 不解析、-t 选表、-A 追加、-I 插入、-D 删除

补一句:-P 是修改链的默认规则,跟 -A/-I/-D 不是一回事。

顺带把常用的"层"也理一下,写规则的时候心里要清楚自己在拦哪一层:

常用层:L2 管 MAC、L3 管 IP、L4 管端口、L7 才看协议内容

二、filter 表案例 1

1. 屏蔽指定 IP

clone 一台机器出来:128 当操作机,129 当测试机。在 128 上操作,在 129 上看效果。

# 在129测试ping
[root@localhost ~]# ping 192.168.73.128
PING 192.168.73.128 (192.168.73.128) 56(84) 字节的数据。
64 字节,来自 192.168.73.128: icmp_seq=1 ttl=64 时间=0.363 毫秒
64 字节,来自 192.168.73.128: icmp_seq=2 ttl=64 时间=1.46 毫秒
64 字节,来自 192.168.73.128: icmp_seq=3 ttl=64 时间=1.14 毫秒
64 字节,来自 192.168.73.128: icmp_seq=4 ttl=64 时间=1.53 毫秒


# 屏蔽129的IP(对于128,129是原IP)
# 端口需要加协议,只有IP不用
iptables -t filter -I INPUT -s 192.168.73.129 -j DROP
root@localhost ~]# iptables -t filter -I INPUT -s 192.168.73.129 -j DROP
[root@localhost ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  192.168.73.129       0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

# 在129 ping没有显示毫秒而且卡住,失败了
[root@localhost ~]# ping 192.168.73.128
PING 192.168.73.128 (192.168.73.128) 56(84) 字节的数据。


# 删除规则(ping成功了)
iptables -D INPUT 1

# 如果是reject会提示
[root@localhost ~]# ping 192.168.73.128
PING 192.168.73.128 (192.168.73.128) 56(84) 字节的数据。
来自 192.168.73.128 icmp_seq=1 目标端口不可达
来自 192.168.73.128 icmp_seq=2 目标端口不可达
来自 192.168.73.128 icmp_seq=3 目标端口不可达

# 如果是屏蔽指定网段--CIDR表示法(屏蔽了256个)
# 注意这里会把自己也踢出去,因为ssh走的是双向通信
# win(客户端)的IP发起ssh连接,服务器INPUT放行才能连
iptables -t filter -I INPUT -s 192.168.73.0/24 -j DROP
# win和虚拟机能连上,肯定在一个内网,如果屏蔽了win所在网段,就断ssh

所以如果是屏蔽网段,要先放行 ssh 连接的 IP。如果是屏蔽指定 IP,通常是从访问日志、错误日志、请求次数太多的记录里把那个 IP 揪出来的。

2. 屏蔽网段和端口

禁止 192.168.73.0/24 访问 8848 端口:

# 使用 netcat (nc) 工具,在 8848 端口上启动一个 TCP 服务器
 #用来持续监听并接收网络连接
nc -kl 8848

# tcp通信:连接远程主机
telnet 192.168.73.129 8848
[root@localhost ~]# telnet 192.168.73.129 8848
Trying 192.168.73.129... # 尝试连接
Connected to 192.168.73.129. # 连接成功
Escape character is '^]'. # Ctrl + ] 退出连接(没连上就是Ctrl + C)

# 此时输入,对方能收到

# 之后输入quit才能退出
telnet> exit
?Invalid command
telnet> quit
Connection closed.
[root@localhost ~]# 

# 在129屏蔽128的端口
iptables -t filter -I INPUT -s 192.168.73.0/24 -p tcp --dport 8848 -j DROP

# 再开启8848,隔壁telnet发送数据,发现无法连接/超时

3. 类似白名单的方式(只允许指定网段访问)

如果只屏蔽一个网段,其他网段还是能访问;如果只想让某些网段访问,就只能反过来配允许规则,也就是白名单:

# 1. 利用 ! 先拒绝后加叹号
iptables -I INPUT -s 192.168.73.0/24 -j DROP
# 在中段参数前加叹号:拒绝不在该网段的IP
iptables -I INPUT ! -s 192.168.73.0/24 -j DROP

# 局限性就是,如果允许的网段多了,也需要写好多

# 2. 调整默认规则(ACCEPT变为DROP),然后添加允许规则
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT 
# OUTPUT 通常保持 ACCEPT(本机对外访问不受限)

这么写有点类似于 nginx 里的:

allow 网段
deny all

4. 一次指定多个端口(逗号和冒号)

可以写多条规则,也可以用 -m 指定功能模块 multiport,端口之间用逗号分隔:

-m multiport -p tcp --dport 80,443

iptables -I INPUT -m multiport -p tcp --dport 80,443 -j DROP

# 如果端口有规律,可以用 冒号(1~1024)
# 注意先允许22,而且22在前面,先匹配放行
iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -I INPUT -m multiport -p tcp --dport 1:1024 -j DROP

5. 禁 ping:限制 ICMP 类型

服务器不想让外网 ping,怕被扫,那就把 ping 禁掉。两条路:改内核参数,或者加 iptables 规则。

用 -p 指定 icmp 协议,--icmp-type 指定 icmp 类型为 8(和 ping 有关);也可以不指定类型,直接禁掉所有 icmp。

防火墙规则禁止:

# 指定icmp类型
iptables -I INPUT -p icmp --icmp-type 8 -j DROP

# 禁止所有icmp
iptables -I INPUT -p icmp -j DROP
# 效果和之前一样不演示了

内核参数禁止:

# 先删除之前的icmp防火墙规则
iptables -D INPUT 1

# 内核参数写入
vim /etc/sysctl.conf

[root@localhost ~]# vim /etc/sysctl.conf

net.ipv4.icmp_echo_ignore_all = 1


# 加载 /etc/sysctl.conf 文件下的所有参数,使配置生效
# 看到输出,测试ping确实不通
sysctl -p
[root@localhost ~]# sysctl -p
net.ipv4.icmp_echo_ignore_all = 1

# 恢复直接改为 0 即可、ping通
[root@localhost ~]# sysctl -p
net.ipv4.icmp_echo_ignore_all = 0

补充:sysctl -a 看所有的内核参数。

想让改动临时生效(上面那种是永久的):

# 所有的内核参数在 /proc/sys
[root@localhost ~]# ll /proc/sys
总计 0
dr-xr-xr-x. 1 root root 0  8月29日 20:04 abi
dr-xr-xr-x. 1 root root 0  8月29日 12:30 crypto
dr-xr-xr-x. 1 root root 0  8月29日 20:04 debug
dr-xr-xr-x. 1 root root 0  8月29日 20:04 dev
dr-xr-xr-x. 1 root root 0  8月29日 12:30 fs
dr-xr-xr-x. 1 root root 0  8月29日 12:30 kernel
dr-xr-xr-x. 1 root root 0  8月29日 12:30 net
dr-xr-xr-x. 1 root root 0  8月29日 20:04 user
dr-xr-xr-x. 1 root root 0  8月29日 12:30 vm

# -d 只查看目录本身的信息
[root@localhost ~]# ll -d /proc/sys
dr-xr-xr-x. 1 root root 0  8月29日 12:30 /proc/sys

# 配置临时的,直接在目录后把参数的 . 换成 / 即可
# 先看一下
ll -d /proc/sys/net/ipv4/icmp_echo_ignore_all
[root@localhost ~]# ll -d /proc/sys/net/ipv4/icmp_echo_ignore_all
-rw-r--r--. 1 root root 0  8月29日 20:07 /proc/sys/net/ipv4/icmp_echo_ignore_all

cat /proc/sys/net/ipv4/icmp_echo_ignore_all

0

# 0 是默认值,改为 1 禁止icmp(临时,重启恢复)
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all

# 覆盖写入,改回
echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_all

改 /etc/sysctl.conf 里的参数,本质上改的就是 /proc/sys 下深层目录里的那些文件。另外 > 是覆盖,>> 是追加,别写错。