1、Iptables基本介绍

1.1 什么是防火墙

  • 过去,很长一段时期⾥,房屋都是草屋结构,如果一家失火,四邻也会跟着遭殃,所以为安全起见,古⼈就在自已居住地周围修筑高高的围墙,以阻挡外来的火势,保护自身的安全,这种墙就叫“防火墙”。

  • 如今,“因特网” 把世界各地的计算机都紧密地连接在一起。如果不严加防卫,一旦网络被侵害,可能会出现不可预计的损失。那么在互联网上,我们会采用类似防火墙的⽅法,来保护我们的网络不受侵害、为此我们需要设定防火墙规则,确定哪些类型的数据包允许通过,哪些不允许通过。

  • 那么具备这种功能的“设备或软件”就可以称之为“防火墙”。

1.2 防火墙的种类

从物理上讲,防火墙可以分为硬件防火墙和软件防火墙。

  • 硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高。

  • 软件防火墙:以软件的⽅式模拟防火墙功能,运行在操作系统上,性能不高,成本较低。

1.3 什么是iptables

iptables 其实不是真正的防火墙,就是一个代理程序,用户通过 iptables 这个代理程序,将安全规则执行到对应的"安全框架"中,这个"安全框架"才是真正的防火墙,这个安全框架叫 netfilter ,是内核代码中不可缺少的一部分; iptables 位于操作系统的用户空间,我们是通过 iptables 命令工具操作 netfilter 内核框架。

所以iptables的完整叫法应该是 netfilter/iptables ,它是 Linux 平台下的 “包过滤型防火墙”,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决⽅案,完成数据包的过滤、连接追踪、限速、网络地址转换 (NAT) 等功能。

1.4 什么是包过滤防火墙

包过滤防火墙它工作在 OSI 七层模型中的网络层和传输层,用来匹配对应数据包的 (header)

  • 1、将 Header 与预先定义好的防火墙规则进行比对;

  • 2、与规则相匹配的包会被放行;

  • 3、与规则不匹配的包则可能会被丢弃、也可能执行更复杂的动作;

由于包过滤防火墙工作在网络层,故也称”网络层防火墙“,它通过检查每一个数据包的:

  • 源地址、目的地址;

  • 源端口、目的端口;

  • 协议类型 (TCP、UDP、ICMP) 、等状态信息来判断是否符合规则;

1.5 包过滤防火墙如何实现

包过滤防火墙是由 Netfilter 来实现的,它是内核的一部分:

如果我们想要防火墙能够达到"防火"的目的,则需要在内核中设置关卡,所有进出的报文都要经过这些关卡进行检查:

  • 将符合条件的放行;

  • 不符合条件的阻止;

而这些关卡在 iptables 中不被称为"关卡",而被称为"链";

2、Iptables链的概念

2.1 什么是链

iptables 中的关卡为什么被称作"链"呢?

防火墙的作用就在于对经过的数据报文进行"规则"匹配,然后执行规则对应的"动作",所以当报文经过这些关卡的时候,则必须匹配这个关卡上的规则,但是,这个关卡上可能不止有一条规则,而是有很多条规则,当我们把这些规则串到一起的时候,就形成了"链"。

所以,每个经过这个"关卡"的报文,都要将这条"链"上的所有规则匹配一遍,如果有符合条件的规则,则执行规则对应的动作,如果没有则执行默认链的动作。

2.2 iptables有哪些链

当我们启用了防火墙功能时,报文需要经过很多关卡,也就是说,根据实际情况的不同,报文经过"链"可能不同,大体分为如下三类:

  • 请求本机会经过哪些链 (PREROUTING-->INPUT-->Local Process) ;

  • 经过本机又会经过哪些链 (PREROUTING-->FORWARD-->POSTROUTING) ;

  • 从本机发出又会经过哪些链 (Local Process-->OUTPU-->POSTROUTING) ;

了解 Iptables 链的数据包流向;后期在设定规则时,能很清晰的知道将规则设定在哪个链上;

我们根据数据包请求的流向,在不同的链上去设定不同的规则,以实现防火墙的目的。

数据包处理流程图解

1. 入站流量路径PREROUTING→ 路由 → INPUT→ 本地服务

2. 转发流量路径PREROUTING→ 路由 → FORWARDPOSTROUTING

3. 出站流量路径:本地进程 → OUTPUTPOSTROUTING


数据包根据流向经过不同链,优先级从高到低

链名称

触发时机

常用表

典型操作

PREROUTING

刚进入网络栈
(路由决策前)

raw, mangle, nat

DNAT、标记包

INPUT

包目标是本机进程
(路由后)

mangle, filter, security

过滤入站流量

FORWARD

包需要转发到其他主机

mangle, filter

路由防火墙规则

OUTPUT

本机进程发出的包

raw, mangle, nat, filter

过滤出站流量

POSTROUTING

离开网络栈前
(路由决策后)

mangle, nat

SNAT、IP伪装

3、Iptables表的概念

3.1 什么是表

我们对每个"链"上都放置了一串规则,但是这些规则有些很相似,比如:

  • A类规则都是对IP或者端口的过滤;

  • B类规则都是对报文进行修改的;

  • C类规则都是进行地址转换的;

那么这个时候,我们是不是可以将实现相同功能的规则放在一起?

当我们把具有相同功能的规则集合在一起叫做"表",所以说,不同功能的规则,我们可以放置在不同的表中进行管理,而 iptables 已经为我们定义了5种表,每种表对应了不同的功能。

3.2 表的功能

5个核心表(Tables),每个表负责特定类型的流量处理

表名称

核心功能

典型应用场景

包含的链

filter

默认表
• 包过滤(允许/拒绝流量)
• 管理 INPUT/OUTPUT/FORWARD链

负责过滤功能

防火墙基础规则
(如开放端口、IP黑白名单)

INPUTOUTPUTFORWARD

nat

网络地址转换
• SNAT(源地址转换)
• DNAT(目标地址转换)
• MASQUERADE(动态IP伪装)

负责网络地址转换功能

路由器网关
端口转发
负载均衡

PREROUTINGINPUT、OUTPUT、POSTROUTING

mangle

高级包修改
• 修改 IP 头信息(TTL、TOS)
• 设置 MARK 标记
• 连接跟踪(conntrack)干预

• 负责修改数据包内容

QoS流量标记
VPN隧道处理
特殊路由策略

INPUT,OUTPUT、 FORWARD、POSTROUTING、PREROUTING

raw

连接跟踪豁免
• 绕过 Netfilter 连接跟踪机制
• 最高优先级处理

• 关闭nat表上启用的连接追踪机制

高性能场景(如游戏服务器)
自定义跟踪逻辑

PREROUTING、OUTPUT

security

强制访问控制(MAC)
• 集成 SELinux 安全上下文标记

多级安全系统
合规性审计(如金融、政府)

INPUTOUTPUTFORWARD


实际使用中:filter 表和 nat 表占90%场景,mangle用于高级定制,raw/security较少使用。


3.3 表与链的关系

raw --> mangle --> nat --> filter

3.4 表与链相关问题

  • 问题1:来自 10.0.0.1 的地址,访问本机的 web 服务请求不允许,应该在哪个表的哪个链上设定规则?

  • 答案1:很多同学会觉得是 PREROUTING 链,但其实是 INPUT 链,因为我们要做的是过滤,而PREROUTING 不能做过滤,所以是 fliter 表中的 INPUT

  • 问题2:所有由本机发往 10.0.0.0/24 网段的 TCP 服务都不允许?

  • 答案2:由本地发出会经过 OUTPUTPOSTROUTING 、但由于 POSTROUTING 不⽀持做过滤,所以应该在 fliter 表中的 OUTPUT 规则链上配置。

  • 问题3:所有来自本地内部的网络主机,向互联网发送 web 服务器请求都允许?

  • 答案3:本地内部主机发送互联网经过 PREROUTINGFORWARDPOSTROUTING 而能做过滤的只有 FORWARD

4、Iptables规则管理

4.1 什么是规则

数据包的过滤是基于规则来实现的,而规则是由匹配条件+动作组成。那我们对规则的操作无非就是增删查改。

操作规则的语法: iptables [-t表名] 选项 [链名] [规则] [动作]

操作规则之前我们需要考量如下两个问题:

  • 1)要实现什么功能:判断添加到哪个表上;

  • 2)报文流经的路线:判断添加到哪个链上;

iptables选项

含义

示例

-t, --table

指定要操作的表(默认filter)

iptables -t filter

-A, --append

追加一条规则至链的末尾

iptables -t filter -A INPUT

-I, --insert

插入一条规则至链的顶部

iptables -t filter -I INPUT

-D, --delete

指定删除一条规则

iptables -t filter -D INPUT 1

-R, --replace

替换选定链中的规则

iptables -t filter -R INPUT

-S, --list-rules

打印选定链中的所有规则

iptables -t filter -S

-F, --flush

清空链中的所有规则

iptables -t filter -F

-Z, --zero

将所有链中的数据包和字节计数器归零

iptables -t filter -Z

-N, --new-chain

创建自定义名称规则链

iptables -N New_Rules

-E, --rename-chain

给自定义链修改名称

iptables -E Old_Rules New_Rules

-X, --delete-chain

删除自定义链

iptables -X Rules_Name

-P, --policy

给链设定默认策略

iptables -t filter -P DROP

4.2 如何查看规则

  • -t :指定要操作的表名称;

  • -L :查看该表的详细信息;

  • -n :对IP地址不进行反解;

  • -v :显示更为详细的指标;

  • --line-numbers :显示规则具体的编号;

4.3 如何添加规则————xx-p(指定规则所匹配的网络协议)-j(指定匹配规则后要执行的目标动作 ACCEPT DROP REJECT)

示例:允许其他任何主机 ping 通本机。

[root@route ~]# iptables -t filter -I INPUT -p icmp -j ACCEPT
[root@route ~]# iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     1    --  0.0.0.0/0            0.0.0.0/0           
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

4.4 如何修改规则————xx-R-xx

示例:修改规则,拒绝其他任何主机 ping 通本机。

[root@route ~]# iptables -t filter -R INPUT 1 -p icmp -j DROP
[root@route ~]# iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       1    --  0.0.0.0/0            0.0.0.0/0           
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

4.5 如何删除规则————xx-D-xx

⽅法一:根据规则的编号去删除规则

⽅法二:根据具体的匹配条件与动作删除规则

[root@route ~]# iptables -t filter -D INPUT 1
[root@route ~]# iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
# 具体的匹配条件与动作删除规则
[root@route ~]# iptables -t filter -D INPUT -p icmp -j DROP

4.6 如何保存规则————xx-save(保存) xx-restore(导入)

1、默认 iptables 属于临时生效,所以需要将编写的规则永久存储起来;

[root@route ~]# iptables -t filter -I INPUT -p icmp -j ACCEPT

[root@route ~]# iptables-save >/etc/iptables.rules

2、清空 iptables 规则,然后恢复规则测试;

[root@Route ~]# iptables -F
[root@route ~]# iptables-restore < /etc/iptables.rules
[root@route ~]# iptables -t filter -L -n

5、Iptables基本匹配

我们前面在练习规则操作时,使用的"匹配条件"比较少。下我们来了解下 iptables 匹配条件更多的用法。

5.1 iptables匹配参数

条件参数

含义

[!] -p, --protocol protocol

指明需要匹配的协议,如icmp、udp、tcp

[!] -s, --source address[/mask][,...]

指定匹配源地址,如有多个可以逗号分隔

[!] -d, --destination address[/mask][,...]

指定匹配目标地址,如有多个可以逗号分隔

[!] --source-port,--sport port[:port]

指定源端口

[!] --destination-port,--dport port[:port]

指定目标端口

[!] -i, --in-interface name

接收数据包的接口名称

[!] -o, --out-interface name

发送数据包的接口名称

-m, --match match

执行需要使用的匹配项,属于扩展匹配

-j, --jump target

执行匹配规则后的动作、ACCEPT、DROP、REJECT等

5.2 iptables匹配示例11、仅允许 10.0.0.100 访问 10.0.0.20 服务器的 80 端口、其他地址全部拒绝。

--dport 是一个目标端口(Destination Port)匹配选项,用于指定数据包要访问的目标服务器端口,仅在处理 TCP 或 UDP 协议的数据包规则时生效(因为端口是 TCP/UDP 协议的核心属性,ICMP 等协议无端口概念)。

[root@route ~]# iptables -t filter -I INPUT -s 10.0.0.100 -d 10.0.0.20 -p tcp --dport 80 -j ACCEPT

[root@route ~]# iptables -t filter -A INPUT -d 10.0.0.20 -p tcp --dport 80 -j DROP

2、测试结果

[root@route ~]# dnf -y install httpd

[root@route ~]# echo Hello > /var/www/html/index.html

[root@route ~]# systemctl stop firewalld

[root@route ~]# setenforce 0

[root@route ~]# systemctl start httpd

# 10.0.0.100的主机访问是正常的

[root@client ~]# curl 10.0.0.20:80

Hello

# 非10.0.0.100的访问

[root@web01 ~]# curl 10.0.0.20

^C

5.3 iptables匹配示例2

1、所有来访问本机的协议,属于 TCP 协议通通都放行;(像Chrony就不属于TCP)

[root@route ~]# iptables -F

[root@route ~]# dnf -y install nc
[root@route ~]# iptables -t filter -I INPUT -p tcp -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -j DROP

2、测试结果

# 在服务端上监听udp端口
[root@route ~]# nc -u -l 3344
#再开一个会话查看监听的端口
[root@route ~]# ss -nlu | grep 3344

# 客户端通过udp发送消息测试,目前无法收到
[root@rocky9 ~]# dnf -y install nc 
[root@rocky9 ~]# echo "test message" | nc -u <your_machine_ip> <port_number>
[root@rocky9 ~]# echo "test message" | nc -u 10.0.0.19 3344

5.4 iptables匹配示例3

1、凡是由本机发出的 TCP 协议报文,都允许出去,其他协议不行

[root@route ~]# iptables -F
[root@route ~]# iptables -t filter -I OUTPUT -p tcp -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -j DROP

2、测试

[root@route ~]# ping jd.com
ping: jd.com: 未知的名称或服务

[root@route ~]# ping baidu.com
ping: baidu.com: 未知的名称或服务

[root@route ~]# iptables -F

[root@route ~]# ping baidu.com -c1
PING baidu.com (39.156.70.37) 56(84) 比特的数据。
64 比特,来自 39.156.70.37 (39.156.70.37): icmp_seq=1 ttl=128 时间=55.6 毫秒

5.5 iptables匹配示例4

1、禁止其他主机从 eth0 向本机发送 ping 请求

[root@route ~]# dnf -y install net-tools 

# 查看网卡名
[root@route ~]# ifconfig

[root@route ~]# iptables -t filter -I INPUT -i eth0 -p icmp -j DROP

[root@route ~]# iptables -L -n -v --line-numbers

2、测试

# eth0无法正常ping通
[root@rocky9 ~]# ping 10.0.0.19 
PING 10.0.0.19 (10.0.0.19) 56(84) 比特的数据。
^C
--- 10.0.0.19 ping 统计 ---
已发送 1 个包, 已接收 0 个包, 100% packet loss, time 0ms

# eth1(如果和eth0同网段)可能也会受到影响,无法ping通
[root@rocky9 ~]# ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) 比特的数据。
^C
--- 10.0.0.19 ping 统计 ---
已发送 1 个包, 已接收 0 个包, 100% packet loss, time 0ms

# 或直接禁用其中一个接口
ip link set eth0 down

#查看路由表
[root@route ~]# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.1        0.0.0.0         UG    100    0        0 eth0
0.0.0.0         10.0.0.1        0.0.0.0         UG    101    0        0 eth1
10.0.0.0        0.0.0.0         255.255.255.0   U     100    0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     101    0        0 eth1

# 将 eth1的路由度量值设为比 eth0小,这样响应包会优先从 eth1发出:
# 删除现有默认路由
route del default gw 10.0.0.1
route del default gw 10.0.0.1

# 添加默认路由,eth1 的度量值更小
route add default gw 10.0.0.1 dev eth1 metric 50

# 确保 eth0 的默认路由度量值更大
route add default gw 10.0.0.1 dev eth0 metric 100

# 删除现有子网路由
route del -net 10.0.0.0/24 dev eth0
route del -net 10.0.0.0/24 dev eth1

# 添加子网路由,eth1 的度量值更小
route add -net 10.0.0.0/24 dev eth1 metric 50
route add -net 10.0.0.0/24 dev eth0 metric 100

====================================================

使用策略路由(生产环境推荐)
# 创建路由表
echo "100 eth0_table" >> /etc/iproute2/rt_tables
echo "200 eth1_table" >> /etc/iproute2/rt_tables

# 为每个接口配置独立路由
ip route add 10.0.0.0/24 dev eth0 src 10.0.0.19 table eth0_table
ip route add default via 10.0.0.1 dev eth0 table eth0_table

ip route add 10.0.0.0/24 dev eth1 src 10.0.0.2 table eth1_table  
ip route add default via 10.0.0.1 dev eth1 table eth1_table

# 添加策略规则
ip rule add from 10.0.0.19/32 table eth0_table
ip rule add from 10.0.0.2/32 table eth1_table

====================================================

# eth1(不在同网段)不受影响
[root@rocky9 ~]# ping 192.168.80.128
PING 192.168.80.128 (192.168.80.128) 56(84) 比特的数据。
64 比特,来自 192.168.80.128: icmp_seq=1 ttl=64 时间=0.217 毫秒

--- 192.168.80.128 ping 统计 ---
已发送 1 个包, 已接收 1 个包, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.217/0.217/0.217/0.000 ms

5.6 iptables匹配示例5

1、允许从本机向外发送 ping 请求、以及允许 22/tcp 端口向外发送请求,除此外其他的协议和端口都不允许;

[root@route ~]# iptables -t filter -I OUTPUT -p icmp -j ACCEPT
[root@route ~]# iptables -t filter -I OUTPUT -p tcp --sport 22 -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -j DROP

2、测试

[root@route ~]#ping 10.0.0.21
PING 10.0.0.21 (10.0.0.21) 56(84) 比特的数据。
64 比特,来自 10.0.0.21: icmp_seq=1 ttl=64 时间=0.549 毫秒

# 因为域名需要解析,该解析协议没有允许
[root@route ~]# ping baidu.com
ping: baidu.com: 未知的名称或服务
由于DNS被阻止,只能通过IP地址连接外部服务,如果需要域名解析,需添加DNS规则:
[root@route ~]# iptables -I OUTPUT -p udp --dport 53 -j ACCEPT
[root@route ~]# ping jd.com -c2

[root@route ~]# ping -c2 8.8.8.8

[root@route ~]# ssh 10.0.0.9
SSH规则限制:
当前规则只允许源端口为22的输出
这意味着本机可以作为SSH服务器(响应客户端请求)
但不能作为SSH客户端连接其他服务器(因为客户端使用随机端口)
如果需要作为SSH客户端连接其他服务器,需添加:iptables -I OUTPUT -p tcp --dport 22 -j ACCEPT

# 客户端连接
[root@rocky9 ~]# ssh 10.0.0.19

6、Iptables扩展匹配

前面我们已经对 iptables 中的基本匹配条件有了基本的认识,接下来,我们来认识一些新的扩展模块。

6.1 multiport模块

multiport 模块可以添加多个不连续的端口; -m multiport <--sports|--dports|--ports> 端口1[,端口2,..,端口n]

1、示例 :允许 10.0.0.100 访问本机 20、21、80、443

[root@Route ~]# iptables -F
[root@route ~]# iptables -t filter -I INPUT -m multiport -s 10.0.0.100 -d 10.0.0.20 -p tcp --dports 20:22,80,443 -j ACCEPT

[root@route ~]# iptables -t filter -A INPUT -p tcp -j DROP

2、测试

通过10.0.0.100测试访问成功,其他主机失败(Xshell会立即断开)可设置的时候放开宿主机IP

[root@route ~]# iptables -t filter -I INPUT -m multiport -s 10.0.0.9,10.0.0.244 -d 10.0.0.19 -p tcp --dports 20:22,80,443 -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p tcp -j DROP

6.2 iprange模块

iprange 模块可以指定 "一段连续的IP地址范围";用于匹配报文的源地址或者目标地址, iprange 扩展模块中有两个扩展匹配条件可以使用。

  • [!] --src-range from[-to]: 原地址范围

  • [!] --dst-range from[-to]: 目标地址范围

1、示例:如果 10.0.0.5-10.0.0.10 地址段 ping 本机,则拒绝;

[root@route ~]# iptables -t filter -F

[root@route ~]# iptables -t filter -I INPUT -p icmp -m iprange --src-range "10.0.0.5-10.0.0.10" -j DROP

[root@route ~]# iptables -t filter -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       1    --  0.0.0.0/0            0.0.0.0/0            source IP range 10.0.0.9-10.0.0.29

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

2、测试

[root@centos7 ~]# ping 10.0.0.19
PING 10.0.0.19 (10.0.0.19) 56(84) bytes of data.

[root@rocky9 ~]# ping 10.0.0.19
PING 10.0.0.19 (10.0.0.19) 56(84) 比特的数据。

6.3 string模块

string 模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则可以执行相应的动作。

  • --algo {bm|kmp} :字符匹配的查询算法;

  • [!] --string pattern :字符匹配的字符串;

1、如果应用返回的报文中包含字符 "hello" ,我们就丢弃当前报文,其余正常通过。

[root@route ~]# iptables -F

[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m string --string "hello" --algo kmp -j DROP

[root@route ~]# iptables -t filter -L -n
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         
DROP       6    --  0.0.0.0/0            0.0.0.0/0            STRING match  "hello" ALGO name kmp

2、准备环境,安装httpd服务,然后准备两个文件

[root@route ~]# yum install httpd -y
[root@route ~]# echo "hello" > /var/www/html/test.html
[root@route ~]# echo "index" > /var/www/html/index.html
[root@route ~]# systemctl restart httpd

3、访问测试

#访问成功
[root@rocky9 ~]# curl 10.0.0.19
index

#访问失败
[root@rocky9 ~]# curl 10.0.0.19/test.html

6.4 time模块

time 模块,可以根据时间段区匹配报文,如果报文到达的时间在指定的时间范围内,则符合匹配条件。 (该模块在RockyLinux9暂不⽀持)

  • --timestart hh:mm[:ss] :开始时间

  • --timestop hh:mm[:ss] :结束时间

  • [!] --monthdays day[,day...] :指定一个月的某一天

  • [!] --weekdays day[,day...] :指定周一到周天

  • --kerneltz :使用内核时区而不是 UTC 时间

示例:拒绝每天 8:30~12:30(00:30~04:30)、13:30~18:30(05:30~10:30) ,任何主机发送 icmp 协议;

# utc时间,与本地快8小时,所以需要-8小时
[root@route ~]# iptables -t filter -I INPUT -p icmp -m time --timestart 00:30 --timestop 04:30 -j DROP

[root@route ~]# iptables -t filter -I INPUT -p icmp -m time --timestart 05:30 --timestop 10:30 -j DROP

# 限制用户在上班时间段禁止访问优酷、爱奇艺等资源,其他时间可以正常放行;
[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m string --string "taobao.com" --algo kmp -m time --timestart 01:00 --timestop 04:00 -j DROP

[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m string --string "taobao.com" --algo kmp -m time --timestart 06:00 --timestop 10:30 -j DROP

[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m string --string "aqiyi.com" --algo kmp -m time --timestart 01:00 --timestop 04:00 -j DROP

[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m string --string "aqiyi.com" --algo kmp -m time --timestart 06:00 --timestop 10:30 -j DROP

2、测试

6.5 icmp模块

icmp 模块:可以控制其他主机无法ping通本机,但本机可以ping通其他主机;

默认情况当禁止 ping 后,其他主机无法 ping 通本主机,本主机也无法 ping 通其他主机,现需要本主机可以 ping 通其他主机,而其他主机依然无法 ping 通本主机.

  • [!] --icmp-type {type[/code]|typename}

  • ICMP 类型, echo-request(8请求)主动发起探测请求echo-reply(0回应)响应探测请求

1、配置icmp扩展模块

# 常规做法不满足需求
[root@route ~]# iptables -t filter -I INPUT -p icmp -j DROP

# 通过扩展 icmp
[root@route ~]# iptables -t filter -F INPUT

# 拒绝所有 ICMP 协议中类型为 "echo-request"(回显请求)的数据包(即 ping 请求)
[root@route ~]# iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT

常见应用场景:
增强服务器安全性:防止潜在的攻击者通过 ping 扫描来发现网络中存在的主机
减少不必要的流量:避免被大量的 ping 请求消耗网络带宽和系统资源
符合某些安全策略:一些安全规范要求隐藏服务器,使其不响应 ping 请求

[root@route ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
REJECT     1    --  0.0.0.0/0            0.0.0.0/0            icmptype 8 reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

2、测试

[root@route ~]# ping 10.0.0.9

[root@rocky9 ~]# ping 10.0.0.19
PING 10.0.0.19 (10.0.0.19) 56(84) 比特的数据。
来自 10.0.0.19 icmp_seq=1 目标端口不可达

3、示例

# 拒绝所有入站 ping 请求(别人 ping 你)
iptables -A INPUT -p icmp --icmp-type echo-request -j REJECT

# 允许本机 ping 别人(出站请求)
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT

# 拒绝回复 ping 请求(不响应别人的 ping)
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j DROP

# 允许接收 ping 响应(接收别人对 ping 的回复)
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT

6.6 connlimit模块

connlimit 扩展模块,限制每个客户端IP地址到服务器的并发连接数。

  • --connlimit-upto n :如果现有连接数小于或等于n,则匹配。

  • --connlimit-above n :如果现有连接数大于n,则匹配。

DDOS 攻击脚本程序,模拟大量的并发数连接;下载📎flood_connect.c

示例:使用脚本模拟 DDOS 攻击,然后检查网站是否异常,如果异常,则使用iptables限制并发连接数。

1、配置http服务站点

[root@rocky9 ~]# dnf install httpd gcc net-tools -y
[root@rocky9 ~]# echo "hello" > /var/www/html/test.html
[root@rocky9 ~]# echo "index" > /var/www/html/index.html
[root@rocky9 ~]# systemctl restart httpd

2、客户端模拟攻击(通过netstat会发现大量的ESTABLISHED状态,从而造成正常用户请求异常;)

[root@rocky9 ~]# gcc flood_connect.c

[root@rocky9 ~]# ls
anaconda-ks.cfg  a.out  flood_connect.c

# 执行脚本,传递服务器IP和Port
[root@route ~]# ./a.out 10.0.0.20 -p 80 

3、设定Iptables规则(开启并发限制)

[root@route ~]# iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 2 -j DROP

4、测试限制后的结果

# 未开启并发限制效果
[root@rocky9 ~]# ./a.out 10.0.0.19 -p 80
Starting flood connect attack on 10.0.0.19 port 80
^CAborted (made 1423 successful connects)

# 开启并发限制效果
[root@rocky9 ~]# ./a.out 10.0.0.19 -p 80
Starting flood connect attack on 10.0.0.19 port 80
^CAborted (made 2 successful connects)

6.7 limit模块

limit 模块,限制单位时间内流入包的数量;可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制。

  • --limit rate[second|minute|hour|day] :平均匹配的速率

  • --limit-burst number :超过限制速率的包,允许超过 burst 所设定值,默认可超出5个

1、限制主机每分钟接收 10个icmp 数据包,差不多6s会接收客户端一个数据包。

[root@route ~]# iptables -t filter -F
[root@route ~]# iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p icmp -j REJECT

2、允许icmp瞬间通过10个数据包通过,超过的数据包每分钟仅能通过一个。

[root@route ~]# iptables -t filter -A INPUT -p icmp -m limit --limit 1/m --limit-burst 10 -j ACCEPT

# 如果超过10的我们给其drop掉
[root@route ~]# iptables -t filter -A INPUT -p icmp -j REJECT 

3、限制主机传输时的带宽每秒不超过 500k ; (500k * 1000=500000字节/1500=333个包) 单位换算网站

  • 500k指的是 500 KBps(千字节每秒)

  • 500k500 KBps500 * 1024 Bytes = 512,000 Bytes或有时按 1000500 * 1000 = 500,000 Bytes

  • 以太网标准的最大传输单元 (MTU) 通常是 1500 字节。这指的是 IP 数据包的最大载荷(不包括以太网帧头等开销)

  • 为了达到 500,000 字节/秒的速率,如果每个包都满载 (1500 字节),那么每秒最多需要发送的包数就是:总字节速率 / 每个包的字节数 = 500,000 Bps / 1500 Bytes/packet ≈ 333.333 packets/s

  • 所以,333 个包/秒是理论上的最大值

[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m limit --limit 300/second -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -p tcp -j DROP
[root@route ~]# dd if=/dev/zero of=/root/bigfile count=100 bs=3M
[root@route ~]# mv bigfile /var/www/html/

[root@route ~]# scp bigfile 10.0.0.9:
root@10.0.0.9's password: 
bigfile                                                       1% 4160KB  88.8KB/s   56:51 ETA

[root@route ~]# mv bigfile /var/www/html/

#浏览器访问:http://10.0.0.19/bigfile

6.8 tcp-flags模块

使用 tcp 模块的 --tcp-flags 可以对 TCP 的标志位进行匹配,匹配指定标志位的值是否为"1";

在tcp协议建立连接的过程中,需要先进行三次握手,而三次握手就要依靠tcp头中的标志位进行。

TCP 报文头中有 6 个控制标志位:

  • SYN (Synchronize):用于建立连接

  • ACK (Acknowledgment):确认收到数据

  • FIN (Finish):用于终止连接

  • RST (Reset):重置连接

  • PSH (Push):要求立即传递数据

  • URG (Urgent):紧急数据

  • 第一次:客户端向服务端发起 TCP 连接,在 TCP 的 flag 标志位中, SYN,RST,ACK,FIN 等仅 SYN 为1,其他标志位为0。

  • 第二次:服务端向客户端返回 ACK ,在 TCP 的 flag 标志位中, SYN,RST,ACK,FIN 等标志位仅 SYN、ACK 为1,其他标志位为0。

  • 第三次:客户端向服务端返回 ACK ,在 TCP 的 flag 标志位中, SYN,RST,ACK,FIN 等标志位仅 ACK 为1,其他标志位为0。

我们可以通过 --tcp-flag 指明需要匹配哪些标志位,然后再指明这些标志位中,哪些必须为1,剩余的都必须为0。

所以当服务器接收新请求时,SYN标志位必须1,其他的标志位为0,而服务端响应这个连接时, SYN、ACK 标志位必须为1,其他的标志位为0。(这样可以避免木马程序通过端口主动向外发送新连接。)

示例:客户端连接服务端22端口第一次握手必须是客户端发起的,所以SYN必须为1,剩下全部为0。然后服务端可以通过22端口返回对应的报文。

# 使用"--syn"选项相当于使用"--tcp-flags SYN,RST,ACK,FIN SYN"

# 数据包流入本机时的策略:
[root@route ~]# iptables -t filter -I INPUT -p tcp --dport 22 -m tcp --tcp-flags SYN,ACk,FIN,RST SYN -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p tcp --dport 22 -m tcp --tcp-flags SYN,ACk,FIN,RST ACK -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p tcp --dport 22 -j REJECT

# SYN+ACK数据包流出本机时策略:
[root@Route ~]# iptables -t filter -I OUTPUT -p tcp --sport 22 -m tcp --tcp-flags SYN,ACK,FIN,RST SYN,ACK -j ACCEPT

#如果不加下面这条指令,Xshell会立即断开,原因:
上面这条规则只允许 SYN+ACK 标志位的数据包通过,但 SSH 连接需要多种类型的数据包:
1)数据传输包:通常是 ACK+PSH(PSH 标志位不在检查范围内)
2)心跳包:纯 ACK 包(保持连接活跃)
3)连接关闭包:FIN+ACK
这些数据包都被 OUTPUT 链的 REJECT 规则阻止了

[root@route ~]# iptables -t filter -A OUTPUT -p tcp --sport 22 -m tcp --tcp-flags SYN,ACK,FIN,RST ACK -j ACCEPT

[root@route ~]# iptables -t filter -A OUTPUT -p tcp -j REJECT

测试:

# 保持 SSH 连接空闲 5 分钟
[root@rocky9 ~]# ssh 10.0.0.19

# 在另一个终端监控连接状态
[root@route ~]# watch -n 1 "netstat -tn | grep 10.0.0.9"

[root@rocky9 ~]# scp /etc/passwd 10.0.0.19:


[root@rocky9 ~]# dnf install epel-release -y
[root@rocky9 ~]# dnf install hping3 -y

#说明 -SA:设置TCP标志位,S表示SYN,A表示ACK,所以这个参数设置SYN和ACK标志位都为1(即SYN+ACK包)
[root@rocky9 ~]# hping3 -SA 10.0.0.19 -p 22 -c 3

7、Iptables连接追踪state

7.1 什么是连接追踪

state(conntrack) 连接跟踪,顾名思义,就是跟踪(并记录)连接的状态。 如下图:是一台 IP 地址为 10.1.1.2Linux 机器,我们能看到这台机器上有三条连接:

  • 机器访问外部 HTTP 服务的连接(目的端口 80)

  • 外部访问机器内 FTP 服务的连接(目的端口 21)

  • 机器访问外部 DNS 服务的连接(目的端口 53)

连接跟踪所做的事情就是发现并跟踪这些连接的状态;但这个追踪状态与TCP协议没有关系。

它是由内核 nefilter 在IP层实现,可IP层是无连接、无追踪的,那是如何知道这个IP是否存在;

当用户发送请求时,会将用户的请求信息存储在内存开辟的空间中,对应在 /proc/net/nf_conntrack 文件会记录源IP、目标IP、协议、时间、状态、等信息;当用户再次发起请求,就可以通过文件获取该用户是否来过,以此来实现连接追踪机制;

注意:该文件能存储的条目是受 /proc/sys/net/nf_conntrack_max 设定大小所限;

7.1 连接追踪有哪些状态

  • [ New ] :新请求,内存中不存在此连接的相关条目,因此识别为第一次请求,状态为 NEW

  • [ ESTABLISHED ] NEW 状态之后,再次建立连接,由于此前的连接还没有失效,所以追踪后被视为已连接通讯状态,状态为 ESTABLISHED

  • [ RELATED ] :相关的连接。比如 ftp 程序有两个连接,命令连接和数据连接;命令连接有来有往是一个独立的循环,数据连接有来有往又是另外一个独立的循环,但是两者之间有关系,如果没有命令连接就不可能有数据连接,所以我们将这种称为”相关联的连接“

  • [ INVALID ] :无效的连接;

7.2 连接追踪应用场景

正常情况下服务器的80端口不会主动连接其他服务器,如果出现了80端口连接其他服务器,那么说明出现了异常行为,或者可以理解为中了木马程序病毒。访问 --> 反弹端口型木马

如果关闭80端口的响应报文,就会造成请求进来⽆法响应;如果开放80端口则又会出现异常行为。

所以我们需要对80端口做连接追踪限制,凡事从80端口出去的就必须是对某个请求的响应,也就是说通过80端口出去的状态必须是 ESTABLISHED ,不能是 NEW

7.3 连接追踪配置场景

1、允许接收远程主机向本机发送的 SSHHTTP 请求 (NEW、ESTABLISHED)

2、同时也仅允许本机向其他主机回应 SSH 以及 HTTP 响应 (ESTABLISHED)

3、但不允许本机通过 22、80 端口主动向外发起连接

# INPUT
[root@route ~]# iptables -t filter -I INPUT -p tcp -m multiport --dport 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p tcp -m multiport --dport 22,80 -j DROP

# OUTPUT
[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m multiport --sport 22,80 -m state --state ESTABLISHED -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -p tcp -m multiport --sport 22,80 -j DROP
[root@route ~]# iptables -P OUTPUT DROP
# 查看当前连接跟踪最大值
[root@route ~]# cat /proc/sys/net/nf_conntrack_max

# 临时设置较小的值便于测试(测试后恢复原值)
[root@route ~]# sysctl -w net.netfilter.nf_conntrack_max=10

[root@route ~]# cat /proc/sys/net/nf_conntrack_max
10

# conntrack工具作用:监控连接跟踪表
[root@route ~]# dnf install epel-release -y

# 安装 conntrack-tools
[root@route ~]# dnf install conntrack-tools -y

# 验证安装
[root@route ~]# conntrack --version
conntrack v1.4.7 (conntrack-tools)

# 查看当前连接跟踪条目数
[root@route ~]# conntrack -C

# 列出所有连接跟踪条目
[root@route ~]# conntrack -L

# 客户端访问测试
[root@rocky9 ~]# hping3 -S -p 80 --flood 10.0.0.19

#客户端使用ab工具创建多个连接
[root@rocky9 ~]# ab -n 100 -c 100 http://10.0.0.19/

#监控连接跟踪表
[root@route ~]# watch -n 1 "conntrack -C && echo 'Used/Max: $(conntrack -C)/$(cat /proc/sys/net/nf_conntrack_max)'"

========================了解=================================
# 设置TCP连接跟踪超时时间为30秒(默认是5天)
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=30

# 设置UDP超时时间为30秒(默认是30秒,可以不用改)
sysctl -w net.netfilter.nf_conntrack_udp_timeout=30
========================了解=================================
# 清除现有规则
iptables -F
iptables -X
iptables -Z

# 设置默认策略
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

# 允许本地回环通信
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# 允许入站 SSH 和 HTTP 连接(NEW 和 ESTABLISHED)
iptables -A INPUT -p tcp -m multiport --dport 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT

# 允许出站 SSH 和 HTTP 响应(ESTABLISHED)
iptables -A OUTPUT -p tcp -m multiport --sport 22,80 -m state --state ESTABLISHED -j ACCEPT

# 阻止本机主动发起 SSH 连接
iptables -A OUTPUT -p tcp --dport 22 -j DROP

# 阻止本机主动发起 HTTP 连接
iptables -A OUTPUT -p tcp --dport 80 -j DROP

# 设置默认拒绝规则(放在最后)
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP

额外补充:如果服务器需要使用SSH连接其他远程主机,需要增加以下配置(但不建议)

# 1.送出的数据包目的端口为22
[root@route ~]# iptables -I OUTPUT 2 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

-I OUTPUT 2:表示在OUTPUT链的第2个位置插入规则,OUTPUT链用于处理从本机发出的数据包
-p tcp:指定协议为TCP
--dport 22:指定目标端口为22(SSH服务的默认端口)
-m state:使用状态匹配模块
--state NEW,ESTABLISHED:匹配连接状态为NEW(新建连接)和ESTABLISHED(已建立的连接)的数据包
-j ACCEPT:对匹配的数据包执行ACCEPT操作,即允许通过

作用:允许本机主动发起SSH连接(状态为NEW)以及维持已建立的SSH连接(状态为ESTABLISHED)的数据包通过。也就是说,本机可以作为SSH客户端去连接其他SSH服务器。

# 2.接收的数据包源端口为22
[root@route ~]# iptables -I INPUT 2 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
-I INPUT 2:表示在INPUT链的第2个位置插入规则。INPUT链用于处理进入本机的数据包
-p tcp:指定协议为TCP
--sport 22:指定源端口为22(SSH服务的默认端口)
-m state:使用状态匹配模块
--state ESTABLISHED:匹配连接状态为ESTABLISHED(已建立的连接)的数据包
-j ACCEPT:对匹配的数据包执行ACCEPT操作,即允许通过

作用:允许本机接收来自SSH服务器的、已建立的SSH连接的数据包(状态为ESTABLISHED)。注意,这里只允许ESTABLISHED状态,而不允许NEW状态。这意味着,这条规则主要用于本机作为SSH客户端时,接收来自SSH服务器的响应数据包(在已建立的连接中),但不允许外部主机主动向本机的22端口发起新的SSH连接(因为没有允许NEW状态)。

测试:

#成功
[root@rocky9 ~]# ssh 10.0.0.19
[root@rocky9 ~]# curl 10.0.0.19
[root@rocky9 ~]# scp /etc/passwd 10.0.0.19:

#失败
[root@route ~]# curl -I www.baidu.com
curl: (6) Could not resolve host: www.baidu.com

[root@route ~]# ssh 10.0.0.9

8、Iptables地址转换

8.1 什么是NAT

网络地址转换 (NAT) ,意思也比较清楚:对(数据包的)网络地址 (IP + Port) 进行转换。

例如,机器自已的 IP 10.1.1.2 是能与外部正常通信的,但 192.168 网段是私有 IP段,⽆法与外界通信,因此当源地址为 192.168 网段的包要出去时,机器会先将源 IP 换成机器自已的 10.1.1.2 再发送出去;收到应答包时,再进行相反的转换。这就是 NAT 的基本过程。

8.2 NAT的几种模式

  • SNAT :源地址转换

  • DNAT :目标地址转换

  • PNAT :端口转换

8.3 NAT环境搭建

  • DNAT:数据包进来的时候,进行目标地址替换,因此在 PREROUTING 链上面设定规则;

  • DNAT主要用于修改数据包的目标IP地址。当外部设备需要访问内部网络的服务时,DNAT将公网IP地址和端口映射到内部服务器的私有IP地址和端口。

DNAT应用场景:

  1. 端口转发(Port Forwarding)

  • 将公网IP的某个端口映射到内网服务器的端口,使外部用户能够访问内网服务(如Web服务器、SSH服务器等)

  • 例如:将公网IP的80端口映射到内网Web服务器的80端口

  1. 负载均衡(入站)

  • 负载均衡器将外部请求的IP地址和端口转换为后端服务器的IP地址和端口,实现流量分发

  1. 隐藏后端服务器

  • 外部用户只能看到公网IP,无法直接访问内部服务器,提高安全性

  1. 服务迁移透明化

  • 当内部服务迁移到新的服务器时,通过DNAT修改映射关系,外部用户无感知

  • SNAT:数据包在出去的那一刻,进行源地址的修改,因此在 POSTROUTING 链上面设定规则;

  • SNAT主要用于修改数据包的源IP地址。当内网设备需要访问外部网络(如互联网)时,SNAT将内网私有IP地址转换为公网IP地址,以便数据包能够在互联网上路由。

SNAT应用场景:

  1. 内网主机访问互联网(最常见场景):

  • 多个内网设备共享一个公网IP地址访问互联网(如家庭或企业网络)

  • 例如:公司内部有100台电脑,但只有1个公网IP,通过SNAT实现所有电脑上网

  1. 隐藏内部网络结构

  • 将内部私有IP地址转换为公网IP,外部无法直接看到内部网络结构,提高安全性

  1. 解决IP地址冲突

  • 当两个私有网络使用相同的IP地址段需要通信时,可以通过SNAT将一方的地址转换为不同的地址段以避免冲突

  1. 负载均衡器(出站)

  • 当负载均衡器作为出口网关时,可以将后端服务器的私有IP转换为公网IP

  • 端口转换(PNAT)通常指的是端口级别的网络地址转换,它实际上是NAT(网络地址转换)的一个子集,主要关注于在转换IP地址的同时转换端口号。

  1. 端口转发(Port Forwarding):将外部网络对某个公网IP地址的特定端口的访问,转发到内部网络中的某个私有IP地址的特定端口上。这实际上是DNAT的一种形式,但特别指定了端口。

  2. PAT(Port Address Translation):也称为NAPT(Network Address Port Translation),这是一种特殊的SNAT,允许多个内网设备共享一个公网IP地址,通过不同的端口号来区分不同的内网设备。这是家庭和小型企业路由器中最常见的NAT形式。

PNAT应用场景:

  1. 端口转发(DNAT的一种形式)

  1. 场景:你有一个内网服务器(如Web服务器)运行在私有IP地址上(例如92.168.1.100:80),而你希望公网用户能够通过访问你的公网IP地址(例如203.0.113.5)的80端口来访问该服务器

1、客户端:仅充当外网用户;

[root@clinet ~]# nmcli connection down eth1
[root@clinet ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ethernet]
[ipv4]
address1=10.0.0.100/24
gateway=10.0.0.2
dns=223.5.5.5;
method=manual

# 重启eth0
[root@clinet ~]# nmcli connection reload && nmcli c down eth0 && nmcli connection up eth0

2、路由节点:需要双网卡,同时还需要开启 FORWARD 转发;

# eth0外网网卡
[root@route ~]# cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0
[ethernet]
[ipv4]
address1=10.0.0.20/24
gateway=10.0.0.2
dns=223.5.5.5;
method=manual

# eth1内网网卡
[root@route ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.20/24
method=manual

# 开启Forward转发
[root@route ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
[root@route ~]# sysctl -p
net.ipv4.ip_forward = 1

3、内网节点:需要将网关指向到 Route

# eth1内网网卡
[root@web01 ~]# cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
type=ethernet
interface-name=eth1
[ethernet]
[ipv4]
address1=172.16.1.7/24
gateway=172.16.1.20
dns=223.5.5.5;
method=manual

[root@web01 ~]# dnf -y install httpd
[root@web01 ~]# echo 123 > /var/www/html/index.html  
[root@web01 ~]# systemctl stop firewalld
[root@web01 ~]# setenforce 0 
[root@web01 ~]# systemctl start httpd

[root@web01 ~]# nmcli connection down eth0
[root@web01 ~]# nmcli connection reload && nmcli connection down eth0 && nmcli connection up eth1

8.3 SNAT场景配置

实现内网主机通过防火墙进行访问公网,需要使用 SNAT (源地址转换 POSTROUTING

方法1.指定从哪个ip地址转换出去(静态公网地址)

[root@route ~]# iptables -t nat -I POSTROUTING -s 172.16.1.0/24 -j SNAT --to 10.0.0.20

方法2.当外网源地址为动态获取的地址时, MASQUERADE 可自行判断要转换为的外网地址

[root@route ~]# iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j MASQUERADE

iptables:Linux系统中用于配置防火墙规则的工具。
-t nat:指定操作的表(table)为nat表,NAT表用于网络地址转换。
-A POSTROUTING:在POSTROUTING链中追加一条规则。POSTROUTING链是数据包离开本机之前进行处理的链,通常在这里做源地址转换(SNAT)。
-s 10.0.0.0/24:匹配源IP地址在10.0.0.0/24网段的数据包。
-j MASQUERADE:跳转到MASQUERADE目标,即对匹配的数据包进行源地址伪装。

这个命令的作用是:当来自10.0.0.0/24网段的数据包要通过防火墙(即本机)发送到外部网络时,将这些数据包的源IP地址替换为防火墙当前所在网络接口的IP地址(通常是公网IP地址)。
MASQUERADE与SNAT的主要区别在于:MASQUERADE不需要指定固定的IP地址,它会自动使用数据包发出时所在网络接口的IP地址。这在防火墙使用动态IP地址(如拨号上网)的情况下非常有用。

3.测试

[root@rocky9 ~]# ping 192.168.80.129 -c2
PING 192.168.80.129 (192.168.80.129) 56(84) 比特的数据。
64 比特,来自 192.168.80.129: icmp_seq=1 ttl=63 时间=0.523 毫秒
64 比特,来自 192.168.80.129: icmp_seq=2 ttl=63 时间=0.799 毫秒

--- 192.168.80.129 ping 统计 ---
已发送 2 个包, 已接收 2 个包, 0% packet loss, time 1021ms
rtt min/avg/max/mdev = 0.523/0.661/0.799/0.138 ms

[root@rocky9 ~]# curl 192.168.80.129
123

8.4 DNAT场景配置

实现外网主机通过防火墙访问内部主机80端口,需要通过 DNAT (目标地址转换PREROUTING

1.端口映射,将公网 IP+Port 映射到私网的 IP+Port

[root@route ~]# iptables -t nat -I PREROUTING -d 10.0.0.20 -p tcp --dport 80 -j DNAT --to 172.16.1.7:80

[root@route ~]# iptables -t nat -I PREROUTING -d 10.0.0.20 -p tcp --dport 22 -j DNAT --to 172.16.1.7:22

2.地址映射,将公网地址映射到私网地址;

[root@route ~]# iptables -t nat -I PREROUTING -d 10.0.0.20 -j DNAT --to 172.16.1.7

9、Iptables自定义链

9.1.为什么要使用自定义链

iptables 的默认链就已经能够满足我们了,为什么还需要自定义链呢?如果默认链中的规则非常多时,不便于管理。

  • 假设INPUT链中存放了100条规则,这100条规则有针对80端口的,有针对22端口的;

  • 如果想修改22端口的规则,则需要将所有规则都看一遍,然后找出匹配的规则,这显然不合理;

所以,我们需要使用自定义链,通过自定义链即可解决上述问题。

  • ⾸先创建一个自定义链,链名叫 IN_SSHD

  • 然后将所有针对22端口入站规则都写入到这条自定义链中;

  • 后期想要修改针对22端口入站规则时,就直接修改 IN_SSHD 链中的规则就可以了;

  • 这样即使有再多的规则也没有关系,因为我们可以通过自定义链,快速定位到想修改的规则;

9.2 自定义链基本应用

1.在 filter 表中,添加一个自定义链

[root@route ~]# iptables -t filter -N IN_SSHD
[root@route ~]# iptables -L -n
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         

Chain IN_SSHD (0 references)     # 自定义的链、⽆法直接使用
target     prot opt source               destination

2.配置自定义链规则:禁止 10.0.0.100 访问 10.0.0.2022 端口。

[root@route ~]# iptables -t filter -I IN_SSHD -s 10.0.0.100 -d 10.0.0.20 -p tcp --dport 22 -j REJECT

3.测试发现规则没有生效,因为自定义的链需要被默认的链调用才会生效;

[root@route ~]# iptables -I INPUT -p tcp --dport 22 -j IN_SSHD

9.3 自定义测试结果

测试后发现 10.0.0.100 ,⽆法访问 22 端口,由于请求的是本机 22 端口,所以需要先经过 INPUT 链,而 INPUT 链将 22 端口处理规则转给 IN_SSHD 链,由 IN_SSHD 链进行规则的匹配;

  • 如果来源IP是 10.0.0.100 则按照规则执行拒绝。

  • 如果来源IP非 10.0.0.100 则按照规则执行运行。

如果没有规则匹配,则回到默认 INPUT 链,继续往下执行规则匹配,如果没有任何匹配成功的规则,则⾛ INPUT 链的默认规则。

9.5 如何删除自定义链

删除自定义链需要满足两个条件:

  1. 自定义链没有被引用

  2. 自定义链中没有任何规则

[root@route ~]# iptables -t filter -D IN_SSHD 1   # 删除自定义规则
[root@route ~]# iptables -t filter -D INPUT 2     # 删除 INPUT 链中的引用,第2条
[root@route ~]# iptables -E IN_SSHD SSHD          # 自定义链重命令
[root@route ~]# iptables -X SSHD                  # 删除自定义链SSHD

10、Iptables场景示例

10.1 iptables场景一

场景描述:

  • 1.对所有的地址开放本机的tcp(80、22、8080-9090)端口的访问

  • 2.允许对所有的地址开放本机的基于ICMP协议的数据包访问

  • 3.其他未被允许的端口禁止访问

实现思路:

  • 1.先允许端口、协议

  • 2.配置拒绝规则

# INPUT
[root@route ~]# iptables -t filter -I INPUT -p tcp -m multiport --dport 22,80,8080:9090 -m state --state "NEW,ESTABLISHED,RELATED" -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p icmp -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -j DROP

# OUTPUT
[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m multiport --sport 22,80,8080:9090 -m state --state "NEW,ESTABLISHED,RELATED" -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -p icmp -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -j DROP

10.2 iptables场景二

场景描述:

  • 1.员工在公司内部 (10.0.0.0/24、10.8.0.0/24) 能访问服务器上任何服务

  • 2.当员工出差外地,通过 vpn 连接到公司,也可以访问内部上的任何服务

  • 3.公司有门户网站需要允许公网用户访问 http 80/tcphttps 443/tcp

实现思路:

  • 1.允许本地lo访问

  • 2.允许 10.0.0.010.8.0.0 网段访问任何服务

  • 3.允许其他网段主机可以访问 80、443

  • 4.允许已建立的数据包通过 (ESTABLISHED

  • 5.拒绝所有未允许的数据包

[root@route ~]# iptables -F
[root@route ~]# iptables -t filter -I INPUT -s 10.0.0.0/24 -j ACCEPT
[root@route ~]# iptables -t filter -I INPUT -s 10.8.0.0/24 -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p tcp -m multiport --dport 80,443,22 -j ACCEPT
[root@route ~]# iptables -t filter -A INPUT -p tcp -j DROP

10.3 iptables场景三

ftp 服务一般有主动和被动两个模式,那么针对这两个模式该如何配置 Iptables 规则呢?

10.3.1 ftp主动模式规则配置

通常 ftp 主动模式监听在21端口,然后由20端口作为数据传输端口,向客户端发送数据。

1. vsftpd 服务端配置⽀持主动模式

[root@route ~]# yum install vsftpd -y
[root@route ~]# vim /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
connect_from_port_20=YES
port_enable=YES
pasv_enable=NO  #禁用FTP被动模式(PASV)

[root@route ~]# cat /etc/vsftpd/vsftpd.conf | grep -E "(connect_from_port_20|port_enable|pasv_enable|anonymous_enable)"
anonymous_enable=YES
connect_from_port_20=YES
port_enable=YES
pasv_enable=NO

[root@route ~]# systemctl restart vsftpd
[root@route ~]# dd if=/dev/zero of=/var/ftp/pub/bigfile count=1 bs=1024M

2.ftp客户端连接模式默认为被动模式,需要通过 passive 命令切换到主动模式

[root@route ~]# yum install ftp -y
[root@route ~]# ftp server_address
# 用户名:ftp,直接回车
ftp> passive
Passive mode off. # 提示被动模式关闭
ftp> cd pub
ftp> get bigdata

3.登陆服务端,查看客户端与服务端的连接的状态。 [ 服务端20端口主动向客户端随机端口发送数据 ]

[root@route ~]# netstat -an | grep -i estab
Active Internet connections (servers and established)
tcp        0     52 10.0.0.19:22            10.0.0.244:61403        ESTABLISHED
tcp6       0 1863576 10.0.0.19:20            10.0.0.9:38721          ESTABLISHED
tcp6       0      0 10.0.0.19:21            10.0.0.9:57708          ESTABLISHED
Active UNIX domain sockets (servers and established)
Active Bluetooth connections (servers and established)

4.配置防火墙,放行 21、20 端口,以及建立连接后的数据传输。

# INPUT
[root@route ~]# iptables -F
[root@route ~]# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
[root@route ~]# iptables -A INPUT -p tcp -m state --state "NEW,ESTABLISHED,RELATED" -j ACCEPT
[root@route ~]# iptables -A INPUT -p tcp -m multiport --dport 20,21 -j ACCEPT
[root@route ~]# iptables -A INPUT -j DROP

# OUTPUT放行从20、21端口出去新建的连接,以及已建立的连接。至于ssh就响应建立的连接即可
[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m multiport --sport 22 -m state --state "ESTABLISHED" -j ACCEPT
[root@route ~]# iptables -t filter -I OUTPUT -p tcp -m multiport --sport 20,21 -m state --state "NEW,ESTABLISHED,RELATED" -j ACCEPT
[root@route ~]# iptables -t filter -A OUTPUT -j DROP

10.3.2 ftp被动模式规则配置

  • ftp被动模式监听在21端口,然后由随机端口作为数据传输端口,向客户端回发送数据

  • 由于是随机就没办法指定端口,所以可以配置vsftpd控制随机端口范围

1.修改 vsftpd 服务端传输数据时的随机端口

[root@route ~]# vim /etc/vsftpd/vsftpd.conf
pasv_min_port=50000
pasv_max_port=60000
[root@route ~]# systemctl restart vsftpd

2.配置 iptables 放行规则

# INPUT
[root@route ~]# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
[root@route ~]# iptables -A INPUT -p tcp -m multiport --dport 21,50000:60000 -m state --state "NEW,ESTABLISHED,RELATED" -j ACCEPT
[root@route ~]# iptables -A INPUT -j DROP

# OUTPUT
[root@route ~]# iptables -I OUTPUT -p tcp --sport 22 -m state --state "ESTABLISHED" -j ACCEPT
[root@route ~]# iptables -A OUTPUT -p tcp -m multiport --sports 21,50000:60000 -m state --state "ESTABLISHED" -j ACCEPT
[root@route ~]# iptables -A OUTPUT -j DROP
[root@route /var/ftp/pub]# tail -4 /etc/vsftpd/vsftpd.conf 
anonymous_enable=YES
port_enable=YES
pasv_min_port=50000
pasv_max_port=60000

[root@rocky9 ~]# ftp 10.0.0.19
Name (10.0.0.19:root): ftp
ftp> cd pub
ftp> get bigfile

[root@route ~]# netstat -an | grep -i estab
Active Internet connections (servers and established)
tcp        0      0 10.0.0.19:22            10.0.0.244:61403        ESTABLISHED
tcp6       0      0 10.0.0.19:21            10.0.0.9:49648          ESTABLISHED
tcp6       0 2484768 10.0.0.19:57634       10.0.0.9:54877       ESTABLISHED # 数据传输随机端口
Active UNIX domain sockets (servers and established)
Active Bluetooth connections (servers and established)