netfilter介绍
防火墙是作用与内网和外网之间,根据定义的策略来过滤流量的软件或者硬件。在Linux内核中,自带了防火墙模块netfilter,通过netfilter可以是实现网络流量的过过滤,以及NAT、连接跟踪等功能。
通过用户空间的iptables、firewalld等工具,可以实现相关规则的定义,将这些规则传递给内核的netfilter框架,实现网络数据包的处理。
netfilter五个钩子
用户空间工具允许管理员定义规则,这些规则随后会与 netfilter 的五个钩子函数之一关联。当数据包在网络堆栈中流动并到达某个钩子点时,netfilter 根据与该钩子关联的规则对数据包进行处理。
这五个钩子函数位于网络堆栈的不同位置:
1、 PREROUTING :这是数据包首先到达的地方,即它在路由决策之前被捕获
2、 INPUT :用于处理目标是本地系统的数据包
3、 FORWARD :用于处理要被路由转发的数据包,即它们既不是发往本地系统,也不是从本地系统发出的
4、 OUTPUT :用于处理从本地系统发出的数据包,即在数据包离开系统之前
5、 POSTROUTING :在数据包被路由之后捕获,即在它离开系统之前
iptables
一般用户空间常用的防火墙管理工具是iptables,除此之外还有firewalld、nettable等。一般情况下,会用iptables就行了。
使用iptables编写流量过滤规则前,我们需要先知道iptables的三个概念:规则、规则链和表
-
规则:就是一种数据流量的匹配策略。每条规则由两部分组成:匹配条件+执行动作
-
规则链:链是一组规则的有序集合。匹配时按顺序与链中的规则进行匹配,直到它与某个规则匹配或到达链的末尾为止
-
表:表是将若干规则链按照其功能进行分类的方式。每个表都专注于特定类型的任务,例如过滤、网络地址转换等。
一个数据包先进入一个特定的表,然后按顺序遍历该表中的规则链,在每个链中按顺序与规则进行匹配,直到找到一个匹配项或到达链的末尾为止。
说明:
数据包不是随机地进入某个表,而是基于数据包的处理阶段和网络堆栈中的位置进入特定的表。netfilter框架定义了几个预定的钩子点(hooks),这些钩子点决定了数据包何时应该被检查和如何被处理。
钩子和表的对应关系如下:
默认情况下,netfilter为它的五个钩子提供了默认的链,这个链和钩子同名。例如 INPUT 钩子与 INPUT 链关联。当数据包准备进入本地系统时,会触发此链。
-
filter 表:主要用于数据包过滤。此表通常包含链如 INPUT、OUTPUT 和 FORWARD。例如,进入本机的数据包将会遍历 INPUT 链。
-
nat 表:用于网络地址转换 (NAT)。此表与 PREROUTING (用于目的地址转换)和 POSTROUTING (用于源地址转换)链相关联。例如,当数据包首次到达系统时,它可能会被送到 nat 表的 PREROUTING 链来决定是否需要进行目标地址的转换。
-
mangle 表:用于特殊的数据包修改,如更改TOS字段。它有多个链,如 PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING 等。
-
raw 表:用于配置例外,避免连接跟踪。此表与 PREROUTING 和 OUTPUT 链相关联。
实现流量过滤
定义规则
iptables -t 指定表名 -I或-A 指定规则链名 指定匹配条件 -j 指定处理动作
说明:
-
-I 表示将该规则插入规则链的前面,数据流量匹配规则链的时候最先就会匹配到该规则
-
-A 表示将该规则插入规则链的末尾,最后才会被匹配到
例如:新增一条规则,实现拒绝10.0.0.11主机的报文
iptables -t filter -I INPUT -s 10.0.0.11 -j DROP
-
当处理动作是DROP时,符合这条规则的数据流量都会被丢弃。
-
通过 -s 参数指定的就是数据流量的源地址,如果要指定目标地址的话需要使用 -d参数
例如:新增一条规则,如果目标地址是10.0.0.11的报文,就丢弃
iptables -A INPUT -d 10.0.0.11 -j DROP
丢弃目标地址为10.0.0.11的报文,也应该在INPUT链中添加这个规则,因为INPUT链是处理到达本机的数据包的规则链。
iptables中,匹配条件分为两种,基本匹配和扩展匹配。
-
基本匹配:iptables这个工具默认就自带的不需要加载任何额外的模块。包括地址匹配、接口匹配和协议匹配
-
扩展匹配:iptable默认没带由iptables的模块系统提供,所以使用扩展匹配的时候需要指定模块名称,扩展匹配允许使用更复杂、更特定的匹配条件。
基本匹配条件使用:
-
地址匹配:使用 -s 参数指定源地址 使用 -d参数指定目标地址
-
接口匹配:使用 -i 参数指定数据流量从那张网卡进来,使用-o参数指定匹配数据
扩展匹配条件私用:
iptables的扩展匹配模块是放在 /usr/lib/x86_64-linux-gnu(ubuntu)或/usr/lib64/xtables/*.so(RedHat系列)中的,iptables工具通过 -m 参数即可调用这些扩展模块。
-
端口匹配:如果要匹配端口的话需要用到multiport模块,提供了三个常用的参数。–sports 指定源端口,–dports 指定目标端口。–ports 指定端口(不区分源或目标)。这个模块有一个特点就是可以离散方式定义多端口匹配,最多指定15个端口
-
协议匹配:tcp协议匹配使用tcp模块,udp协议匹配使用udp模块,icmp协议匹配使用icmp模块,因为模块名称和协议类型是一样的,所以可以忽略-m指定模块,直接用-p指定协议类型就行了。这些模块也提供了 –sport 参数指定源端口,–dport参数指定目标端口,但是这些端口可以是单个或者一个范围。就是不能是离散的。例如: –sport 11,12,13 这种就是错的。
例如:禁止10.0.0.29的22、80、1884、1883端口的数据
iptables -t filter -I INPUT -s 10.0.0.29 -p tcp -m multiport --ports 22,80,1884,1883 -j DROP
例如:禁止10.0.0.29通过ssh访问本机
iptables -t filter -I INPUT -s 10.0.0.29 -ptcp --dport 22 -j DROP
说明: 端口是传输层的概念,所以要使用 -p来指定协议类型为tcp才行。又因为tcp模块和协议名称一致,所以可以省略 -m tcp
当指定的规则匹配到数据流浪后,有三种处理动作来处理匹配到的流量:
-
ACCEPT:放行
-
DROP:直接丢弃
-
REJECT:拒绝,会高度客户端请求流量被拒绝了
查看规则
要查看规则,首先需要使用 -t 参数指定要查看哪张表的规则,然后使用 -vnL 这三个参数就可以查看规则的信息信息了。
iptables -t 表名 -vnL
删除规则
删除规则使用的是 -D 参数。删除规则有两种方式,一种就是先查看规则的编号,然后通过编号进行删除。还有一种就是根据具体的匹配条件与动作删除规则
例如:删除INPUT链中编号为1的规则
iptables -t filter -D INPUT 1
例如:删除filter表中,INPUT链上,源地址是10.0.0.11,处理动作是DROP的这条规则
iptables -t filter -D INPUT -s 10.0.0.11 -j DROP
清除链表上的所有规则:
通过 -F 参数可以用来清除指定规则链上的所有规则,如果不指定表的话,默认操作的就是filter表。
iptables -t 表明 -F 链名
例如:清除filter表中,INPUT链上的所有规则
iptables -t filter -F INPUT
修改默认策略
如果要修改某个规则链的默认策略,可以通过 -P 参数 来实现。当链中没有任何规则时,防火墙会按照默认动作处理报文
iptables -P 链名 默认的策略
例如:修改filter表中的INPT链的默认策略为DROP
iptables -t filter -P INPUT DROP
实现黑白名单
黑名单:被指定的用户被拒绝,其它用户被允许。实现方式就是将指定规则链的默认策略改为ACCEPT,然后加入的匹配规则的策略为DROP或者REJECT
白名单:默认就是拒绝,指定的用户才会被运行。将指定链的默认的匹配规则设置为REJECT,加入的规则设置为ACCEPT。
例如:只开放 22、80、8000、8001、1883、1884、9001、9100、9802端口
# 需要先保证当前的远程不会断
iptables -t filter -I INPUT -s 10.0.0.1 -j ACCEPT
# 修改INPUT链默认的策略
iptables -t filter -P INPUT DROP
# 添加运行通过的数据报文
iptables -t filter -A INPUT -m multiport -p tcp --dports 22,8000,8001,80,1883,1884,9001,9100,9802 -j ACCEPT
iptables -t filter -A INPUT -m multiport -p udp --dports 22,8000,8001,80,1883,1884,9001,9100,9802 -j ACCEPT
保存规则
默认通过iptables编写的规则,重启系统后就失效了,如果需要实现持久化生效,需要借助特定的工具保存才行。
(1)通过 iptables-save 保存规则
iptables-save 命令可以将当前的 iptables 配置输出到标准输出。你可以将其重定向到一个文件以保存当前的规则集。
sudo iptables-save > /path/to/your/iptables.rules
(2)通过 iptables-restore 恢复规则
sudo iptables-restore
说明:需要保证 restore恢复规则这条命令开机能自动执行,可以加入rc.loca,也可以加入shell配置文件,还可以写一个service文件实现自动运行。
例如:使用service的方式实现
[Unit]
Description=Restore iptables rules
After=network.target
[Service]
Type=oneshot
ExecStart=/sbin/iptables-restore /path/to/your/iptables.rules
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
实现NAT功能
NAT是network address translation的缩写,译为网络地址转换。NAT功能通常会被集成到路由器、防火墙、或独立的NAT设备中。
例如:
一个企业的若干主机需要访问公网,如果每个主机都给配一个公网IP地址,那么IP地址早就不够用了。所以可以在这个企业搭建一个局域网,局域网内使用私网地址,他们要访问外网就通过NAT技术将这个局域网内所有前往公网的请求通过一个公网地址发送出去,这样就大大解决了ip地址。
私网地址:
私网地址是局域网里面使用的地址,随便用.私网地址的报文是没法在公网上面传输的,就算接通了外网,这些数据包也是不会发送给运营商的。公网地址需要找ISP机构申请。
-
A类:10.0.0.0 到 10.255.255.255(子网掩码:255.0.0.0 或前缀/8)
-
B类:172.16.0.0 到 172.31.255.255(子网掩码:255.240.0.0 或前缀/12)
-
C类:192.168.0.0 到 192.168.255.255(子网掩码:255.255.0.0 或前缀/16)
NAT根据转换的是源地址还是目标地址,将ANT分为SNAT和DNAT;
-
SNAT:源地址会发生改变,一般用于局域网内主机通过一个公网地址来访问外网。
-
DNAT:目标地址会发生改变,一个从互联网发来的数据包的目标IP会被更改为局域网内的一个私有IP地址
说明:
一般局域网内某个主机访问公网时,出去的时候会进行SNAT转换,回来的时候会进行DNAT转换。数据包能通过DNAT准确回来是通过连接追踪机制实现的。简单说就是当数据包经过SNAT或DNAT规则时,连接跟踪系统会为这个连接创建一个条目。这个条目会记录数据包的原始地址和端口以及转换后的地址和端口。
例如:
某个局域网内,有一个公网IP是15.20.64.41。某个主机需要访问公网,就会将数据包交给这个公网IP地址进行处理,此时源IP地址就会变为这个公网ip地址,这就是SNAT。回来的时候,互连网上的指定服务将数据范围到这个公网地址后,根据连接追踪机制把数据交给指定的主机。这个时候目标地址会发生变化,这就是DNAT。
除了SNAT和DNAT外,还有种叫作PNAT,也叫做PAT。PNAT(或PAT)通常被看作是SNAT的一个特定形式或变种,其特点不仅在于将内部IP地址转换为公网IP地址,还包括同时更改源端口号。这种技术的主要应用场景是当公网IP地址资源有限,但需要让多个内部设备同时访问互联网时。
在使用PNAT/PAT时,外部设备看到的源地址是NAT设备的公网IP地址和一个由NAT设备分配的端口号。这样,即使多个内部设备共享同一个公网IP地址,由于它们有不同的端口号,返回的流量依然可以被正确地路由到相应的内部设备。
iptables实现NAT实际上是通过iptables默认的 nat这个表来实现的,在数据出区或者进来的时候对数据报文进行处理。 在使用nat表来实现NAT技术的时候,-j 指定的处理动作和流量匹配时有所不同,一般常用的三种策略是:
-
DNAT:目标地址转换
-
SNAT:源地址转换
-
MASQUERADE:地址伪装,这是SNAT的一种特殊形式,特别适用于动态IP地址,它会自动处理地址更改。MASQUERADE也可以进行端口转换,从而允许多个内部设备共享单一公网IP地址。
SNAT实现
# 表示访问的地址只要不是内网地址就使用snat的方式将请求报文源地址替换为to-source指定的地址
iptables -t nat -A POSTROUTING -s LocalNET ! -d LocalNet -j SNAT --to-source ExtIP
例如:局域网中10.0.0.0/24网段主机,只要访问的不是10.0.0/24这个网段,就将请求报文源地址替换为172.18.1.6-172.18.1.9
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! –d 10.0.0.0/24 -j SNAT --to-source 172.18.1.6-172.18.1.9
如果公网IP不固定的话,要通过这种方法:
# MASQUERADE会动态的将源地址转换为可用的IP地址
iptables -t nat -A POSTROUTING -s LocalNET ! -d LocalNet -j MASQUERADE
例如:192.168.0.0/16网段的主机访问外网时,将192.168.0.0/16网段的请求报文源地址都更改为eth0网卡上的公网地址
ptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth0 -j MASQUERADE
DNAT实现
iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport PORT -j DNAT --to-destination InterSeverIP[:PORT]
例如:如果本机的公网地址是10.0.0.100,外网的请求报文访问10.0.0.100:80端口时,就将请求报文的目标地址改为192.168.1.100:80
iptables -t nat -I PREROUTING -d 10.0.0.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
PNAT实现
例如:外网用户要访问内网的http服务请求的端口是80,而内网的httpd服务工作在非标准的端口8080上, 此时内网的http服务器就需要将发送给本机80端口的数据报文重新重定向至本机的8080端口
# 法一
iptables -t nat -I PREROUTING -d 10.0.0.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080
# 法二
# REDIRECT,是NAT表的 target,通过改变目标IP和端口,将接受的包转发至同一个主机的不同端口,可用于PREROUTING OUTPUT链
iptables -t nat -A PREROUTING -d 172.16.100.10 -p tcp --dport 80 -j REDIRECT --to-ports 8080
自定义规则链
netfilter为它的五个钩子提供了默认的链,这些链和钩子同名。除了netfilter提供的五个默认链,我们还可以自定义一些规则链。但是自定义链并不能直接使用,而是需要被默认链引用才能够使用。
创建自定义链
(1)使用 -N 选项可以创建自定义链
iptables -t 表 -N 需要定义的链名
例如:创建一个叫做IN_WEB的自定义链
iptables -t filter -N IN_WEB
(2)给这个自定义链定义队则
例如:实现别的主机不能ping通本机
iptables -t filter -I IN_WEB -p icmp --icmp-type 8/0 -j REJECT
(3)通过 -j 参数来在默认的规则链种引入自定义的规则链
例如:
iptables -t filter -I INPUT -j IN_WEB
删除自定义链
通过 -X 参数可以删除定义的自定义链,但是这个自定义链需要没有被引用以及自定义链中没有任何规则。
(1)清空自定义链规则
iptables -F
(2)将默认链种对自定义链的引用删除,删除默认链中的默认规则就行了
(3)通过 -X 参数来删除自定义链
iptables -X