Loading

iptables防火墙详解

1. 什么是iptables

​iptables是Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。

​规则(rules)其实就是网络管理员预定义的条件,规则一般的定义为“如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。当数据包与规 则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。


2. 理解本机数据路由决策

​网络数据总是会流入、流出的,即使是本机的客户端和服务端进程间通信,也需要从一个套接字流出、另一个套接字流入,只不过这些数据无需路由、无需经过物理网卡(走的是LoopBack)。


img

  1. 当接收外界发送的数据时,在数据从网卡流入后需要对它做路由决策,根据其目标决定是流入本机数据还是转发给其他主机,如果是流入本机的数据,则数据会从内核空间进入用户空间(被应用程序接收、处理)。
  2. 当用户空间响应(应用程序生成新的数据包)时,响应数据包是本机产生的新数据,在响应包流出之前,需要做路由决策,根据目标决定从哪个网卡流出。
  3. 如果不是流入本机的,而是要转发给其他主机的,则必然涉及到另一个流出网卡,此时数据包必须从流入网卡完整地转发给流出网卡,这要求Linux主机能够完成这样的转发。(ip_forward未开启,数据包无法转发而被丢弃)

Tips:Linux主机默认未开启ip_forward功能!Linux主机和路由器的不同就是路由器本身就是为了转发数据包,所以路由器内部默认就能在不同网卡间转发数据包,而Linux主机默认则不能转发。


一个例子的理解

​Linux主机1有两张网卡eth0:10.0.0.61,eth1:172.16.1.61。Linux主机2有一张网卡,IP为10.0.0.5,网关10.0.0.5。Linux主机2能不能直接ping通172.16.1.61?答案是可以的。Linux主机2查询路由表无匹配路由条目后将数据包发往网关。网关即Linux主机1从eth0接收数据包。内核分析发现目标地址为本机地址,直接产生数据包进行回应10.0.0.5,根据Linux主机1的路由表策略,数据走的eth0网卡。

​在此过程中,没有进行数据包转发过程,因为流出的响应包是新产生的,而非原来流入的数据包。如果流入和流出的包是一样的(或者稍作修改),则数据流入后不能进入用户空间,而是直接通过内核转发给另一个网卡。数据包从网卡1交给网卡2,这个过程就是转发,在Linux主机上由ip_forward进行控制。例如,网卡1所在网段主机ping网卡2所在主机时,数据包流入网卡1后就需要转交给网卡2,然后从网卡2流出。

Tips:IP地址是属于内核的(不仅如此,整个tcp/ip协议栈都属于内核,包括端口号)



3. iptables和netfilter的关系

​iptables和netfilter的关系是一个很容易让人搞不清的问题。很多的知道iptables却不知道 netfilter。iptables只是管理控制netfilter的工具,可以使用该工具进行相关规则的制定以及其他的动作。iptables是用户层的程序,netfilter是内核空间的。真正实现防火墙功能的是 netfilter,它是Linux内核中实现包过滤的内部结构。


3.1 netfilter的结构

​netfilter自己维护一个内存块,在此内存块中有4个表:filter表、NAT表、mangle表和raw表。在每个表中有相应的链,链中存放的是一条条的规则,规则就是过滤防火的语句或者其他功能的语句。也就是说表是链的容器,链是规则的容器。实际上,每个链都只是一个hook函数(钩子函数)而已。

Tips:要使netfilter能够工作,就需要将所有的规则读入内存中。


3.2 四表五链

img

filter表:netfilter中最重要的表,负责过滤数据包,也就是防火墙实现"防火"的功能。filter表中只有OUTPUT/FORWARD/INPUT链。

NAT表:实现网络地址转换的表。可以转换源地址、源端口、目标地址、目标端口。NAT表中的链是PREROUTING/POSTROUTING/OUTPUT。

mangle表:一种特殊的表,通过mangle表可以实现拆解报文、做出修改、重新封装。mangle表中包含所有的链。

raw表:加速数据包穿过防火墙的表,也就是增强防火墙性能的表。只有PREROUTING/OUTPUT表。

Tips:用的多的才是filter表和NAT表!


通过下图来理解这五条默认的规则链

image-20230322154104624

从上图可知,不考虑特殊情况的话,一个数据包只会经过下面三个路径中的一个:

  • A:主机收到目的 IP 是本机的数据包
  • B:主机收到目的 IP 不是本机的数据包
  • C:本机发出去的数据包

Tips:NAT表中OUTPUT链是本机发出的数据,很少需要用到NAT的场景,忽略即可。


路径 A, 从外界到达防火墙的数据包,先被NAT表的PREROUTING规则链处理(是否修改数据包地址等),之后会进行路由选择(判断该数据包应该发往何处),如果数据包的目标主机是防火墙本机。那么内核将其传给filter表的INPUT规则链进行处理(决定是否允许通过等),通过以后再交给系统上层的应用程序(比如Apache服务器)进行响应。

路径 B, 来自外界的数据包到达防火墙后,首先被NAT表的PREROUTING规则链处理,之后会进行路由选择,如果数据包的目标地址是路由表中的其它外部地址,则内核将其传递给filter表的FORWARD规则链进行处理(是否转发或拦截),然后再交给NAT表的POSTROUTING规则链(是否修改数据包的地址等)进行处理。

路径 C,数据包由 Linux 主机向外发送,比如响应客户端的请求要求,或者是 Linux 主机主动发送出去的数据包,都会通过路径 C。它会先进行路由判断,在确定了输出的路径后,再通过 filter 表的 OUTPUT 链来传送。当然,最终还是会经过 nat 表的 POSTROUTING 链。


总结规律

filter 表主要跟进入 Linux 主机的数据包有关,如下:

  • INPUT:主要与想要进入 Linux 主机的数据包有关
  • OUTPUT:主要与 Linux 主机所要发送出去的数据包有关
  • FORWARD:与 Linux 主机没有关系,它可以对数据包进行转发

nat表主要在进行来源与目的之 IP 或 port 的转换,如下:

  • PREROUTING:在进行路由判断之前所要执行的规则(DNAT目的地址转换)
  • POSTROUTING:在进行路由判断之后所要执行的规则(SNAT源地址转换)
  • OUTPUT:与发送出去的数据包有关

3.3 规则的行为

规则存放在特定表中的链上,链上的每条规则包含下面两部分的信息:

  • Matching

    • 就是如何匹配一个数据包,匹配条件很多,比如协议类型、源/目的IP、源/目的端口、in/out接口、包头里面的数据以及连接状态等,这些条件可以任意组合从而实现复杂情况下的匹配。
  • Targets

    • 就是找到匹配的数据包之后怎么办,会有什么动作。有下面几种:
      • DROP:直接将数据包丢弃,不再进行后续的处理。
      • ACCEPT:同意数据包通过,继续执行后续的规则(rule)。
      • RETURN:跳出当前链,该链后续的规则不再执行。
      • QUEUE:将数据包放入用户空间的队列,供用户空间的程序处理
      • 跳转到其他用户自定义的链继续执行

Tips:最常用的数据包处理方式还是DROP,ACCEPT。


4. iptables使用方法

4.1 iptables命令

iptables 【-t 表名】 操作 链名 【规则编号】 匹配规则 -j 处理动作

-A 在指定链的末尾添加(append)一条新的规则
-D 删除(delete)指定链中的某一条规则,可以按规则序号和内容删除
-I 在指定链中插入(insert)一条新的规则,默认在第一行添加
-R 修改、替换(replace)指定链中的某一条规则,可以按规则序号和内容替换
-L 列出(list)指定链中所有的规则进行查看
-E 重命名用户定义的链,不改变链本身
-F 清空(flush)
-N 新建(new-chain)一条用户自己定义的规则链
-X 删除指定表中用户自定义的规则链(delete-chain)
-P 设置指定链的默认策略(policy)
-Z 将所有表的所有链的字节和数据包计数器清零
-n 使用数字形式(numeric)显示输出结果
-v 查看规则表详细信息(verbose)的信息
-V 查看版本(version)
-h 获取帮助(help)

4.2 表名和链名

表名:filter、nat、mangle、raw

链名:不同表只能使用允许的链名

  1. PREROUTING
  2. INPUT
  3. FORWARD
  4. OUTPUT
  5. POSTROUTING

4.3 操作

  • -A 链中末尾添加规则
  • -I 链名 【规则编号】 如果没有规则编号,插入到第一条的位置,有规则编号,插入到指定编号位置,原编号及之后的规则依次下移
  • -R 链名 规则编号 必须输入规则编号,替换该编号的规则
  • -D 链名 规则编号 必须输入规则编号,删除该编号的规则

4.4 匹配条件

一级条件参数形式 -option , 一级参数可能包含二级参数, 二级参数必须紧跟在主参数后写, 形式为 --option 两个 “--”。

  1. TCP/IP匹配条件,IP 和端口号

    • -s 源IP IP可以是单个IP , 也加掩码 配置网段 如192.168.1.1/24, 但不能是连续ip,如 192.168.1.1-192.168.1.20 (连续ip需要扩展模块)
    • -d 目标IP IP可以是单个IP , 也加掩码 配置网段 如192.168.1.1/24, 但不能是连续ip,如 192.168.1.1-192.168.1.20
  2. -i 网卡名 数据进入的网卡

  3. -0 网卡名 数据流出的网卡

  4. -p 协议名 tcp 、udp、icmp 等等, 指定协议名后才能进一步指定端口号,其实-p 会自动加载相应协议的扩展模块,指定端口号是扩展模块的功能。

    • --sport 源端口号 port[:port] ,--source-port 的简写,可以是端口范围
    • --dport 目标端口号 port[:port] --destination-port的简写, 可以是端口范围
    • --tcp-flags mask comp
    • mask comp 例 SYN,ACK,FIN,RST SYN 匹配 SYN标志必须为1, ACK,FIN,RST必须为0, 其它标志不检查的数据包。
  5. -m 扩展模块

    1. state

      基于状态的匹配规则, 与特定的协议没有关系,可以是TCP, UDP , 状态也不是指TCP协议连接状态。

      对于TCP来说,第一个连接请求SYN包状态为 NEW , 之后的全部为 ESTABLISHED 。 这个简单的规则是非常有用的,用于区分连接发起的方向,是从内到外还是从外到内,而其它的匹配规则都无法识别连接的发起方向

      这个模块我认为是最有用的,关于内核如何跟踪、标识各个协议的链接状态,这个地址里有详细的介绍:https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html

      • --state 状态
        • NEW 新发起的连接请求,第一次讲求的数据报为NEW状态
        • ESTABLISHED 同一连接第一次请求之后的数据报均是该状态
        • RELATED 第一请求,但是该请求是由已建立的其它连接发起的,典型应用 FTP的数据传输,数据传输连接是由已建立的FTP控制连接发起的新连接,使用这个需要加载
        • INVALID 无效数据包,数据包不合法
    2. connlimit

      连接数据限制,可以限制匹配规则的连接数量,比如限制SSH连接数据只能为3

      • --connlimit-upto n 连接数小于等于n

      • --connlimit-above n 连接数大于等于n

    3. multiport
      端口使用集合指定 ,最多15个。

      • --sports port,port,port 或者 port:port 连续范围的port

      • --dports port,port,port 或者 port:port 连续范围的port

    4. iprange 指定ip地址范围

      • --src-range ip1-ip2

      • --dst-range ip1-ip2

    5. time 时间匹配

      • --timestart 开始日期 yyyy-mm-ddThh:mm:ss 例 1990-01-01T11:30:00 注意J日期和时间中间有个大写T,默认 1970-01-01T00:00:00

      • --timestop 结束日期 yyyy-mm-ddThh:mm:ss 例 1990-01-01T11:30:00 注意J日期和时间中间有个大写T,默认 2038-01-19T04:17:07

      • --datestart 结束时间 hh:mm:ss 例 11:30:00, 默认00:00:00

      • --datestop 结束时间 hh:mm:ss 例 11:30:00, 默认23:59:59

      • --monthdays 日期 1-31, 可以是集合,如 1,2,5,9

      • --weekdays 星期,1-7 , 可以是集合,如 1,3,5 1是星期一

    6. limit 速率匹配

      使用令牌桶的算法,每个要转发的数据包要获取一个令牌才能转发,没有获取令牌的包,不匹配该规则,会转由下一条匹配,如果限速,紧跟后面要有一条规则丢弃数据。

      • --limit rate n[/second|/minute/hour/day] 速率限制 , 单位时间允许生成的令牌数据,也即允许转发的数据报数量, 注意: 不是带宽,不是带宽,当然通过限制包的数据也会间接限制了带宽速率,包大小*包数=带宽数。 默认3/hour
      • --limit-burst n 初始令牌数据, 即初始允许不受限制发送的数据量,初始令牌用完,后面要等--limit 指定的单位时间生成的新令牌填充。
    7. string

      • 匹配应用层数据中的字符串, 只是简单以字符串形式匹配应用层数据,不会识别应用协议,如果是加密的也不会解密,只能是应该层协议没有加密时有用,比如http
      • --string pattern

4.5 处理动作

filter表动作

  • ACCEPT 允许
  • DROP 直接丢弃
  • REJECT 拒绝 ,丢弃同时返回ICMP消息
  • LOG 日志记录 , 不会终止规则匹配,也就是说该动作只记录日志,至于数据包是否被转发,会继续匹配后续规则

NAT表动作

  • SNAT 源地址转换
  • DNAT 目标地址转换

4.6 总结

image-20230323195454374


5. 使用iptables

​iptalbes 是基于内核的,和 iptables.service 没有关系,对于 centOS 7 来讲,不用安装任何工具包就可以使用 iptable 命令添加的防火墙规则,只是添加的规则是临时的,基于内存的,会在系统重启前消失,所以需要 iptables.service,firewalld.service 来对添加的规则进行保存。在系统重启后重载对应的防火墙规则,在系统关机时卸载对应的规则。


5.1 安装iptables管理工具

yum install -y iptables-services

#关闭firewalld
systemctl stop firewalld
systemctl disable firewalld

#启动iptables管理
systemctl enable iptables.service
systemctl start iptables.service

#加载防火墙内核选项
modprobe ip_tables
modprobe iptable_filter
modprobe iptable_nat
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
modprobe ipt_state

#永久加载
cat >>/etc/rc.local<<EOF
modprobe ip_tables
modprobe iptable_filter
modprobe iptable_nat
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
modprobe ipt_state
EOF

#检查加载的内容
lsmod |egrep 'filter|nat|ipt'

5.2 iptables的保存和恢复

#保存
iptables–save > /etc/iptables/iptables.rules

#恢复
iptables–restore < /etc/iptables/iptables.rules

5.3 查看防火墙当前的规则

-t 指定表

-n使用数字形式显示输出结果

-L列出该表中链的规则情况

[root@ms01 ~]# iptables -t filter -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

显示表下的某个链的规则情况,直接在-L后加链名

[root@ms01 ~]# iptables -t filter -nL INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

显示规则编号,加上--line-numbers

[root@ms01 ~]# iptables -t filter  -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    DROP       tcp  --  10.0.0.5             0.0.0.0/0            tcp dpt:22
2    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0
4    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22

5.4 设置表的默认规则

#默认规则就是不添加-j指定规则行为
iptables -P INPUT DROP
iptables -P FORWARD DROP

5.5 禁止某主机连入ssh

#如要禁止某网段,直接写成网段形式
[root@ms01 ~]# iptables -t filter -I INPUT -s 10.0.0.5 -p tcp --dport 22 -j DROP
[root@ms01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  10.0.0.5             0.0.0.0/0            tcp dpt:22

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

5.6 禁止某主机ping

[root@ms01 ~]# iptables -t filter -A INPUT -s 10.0.0.5 -p icmp -j DROP

5.7 允许指定多个端口连入

[root@ms01 ~]# iptables -t filter -I INPUT -s 10.0.0.5 -p tcp -m multiport --dport 80,43,22 -j ACCEPT
[root@ms01 ~]# iptables -t filter -nL INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  10.0.0.5             0.0.0.0/0            multiport dports 80,43,22
DROP       tcp  --  10.0.0.5             0.0.0.0/0            tcp dpt:22
DROP       icmp --  10.0.0.5             0.0.0.0/0

5.8 删除指定链的某条规则

[root@ms01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  10.0.0.5             0.0.0.0/0            multiport dports 80,43,22
2    DROP       tcp  --  10.0.0.5             0.0.0.0/0            tcp dpt:22
3    DROP       icmp --  10.0.0.5             0.0.0.0/0
[root@ms01 ~]# iptables -t filter -D INPUT 1
[root@ms01 ~]# iptables -t filter -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    DROP       tcp  --  10.0.0.5             0.0.0.0/0            tcp dpt:22
2    DROP       icmp --  10.0.0.5             0.0.0.0/0

Tips:本文部分内容参考骏马金龙、sparkdev、wyf368等博主,感谢提供技术干货知识!

posted @ 2023-09-12 22:30  YinJayChen  阅读(39)  评论(0编辑  收藏  举报