原文链接:朱双印的iptables博客
目录- 第一章 基本概念
- 第二章 常用命令
- 第三章 iptables匹配条件
- 第四章 iptables扩展匹配条件
- 第五章 iptables的黑白名单机制
- 第六章 iptables自定义链
- 第七章 网络防火墙
- 第八章 iptables动作总结
- 第九章 iptables总结
第一章 基本概念
防火墙相关概念:
从逻辑上讲,防火墙可以大体分为主机防火墙和网络防火墙。
主机防火墙:针对于单个主机进行防护。
网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网。
网络防火墙和主机防火墙并不冲突,可以理解为网络防火墙主外(集体),主机防火墙主内(个人)。
从物理上讲,防火墙可以分为硬件防火墙和软件防火墙。
硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高。
软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能低,成本低。
iptables其实不是真正的防火墙,可以把它理解成一个客户端代理,用户通过iptables这个代理,将用户的安全设定执行到对应的"安全框架"中,这个"安全框架"才是真正的防火墙,这个框架的名字叫netfilter。
netfilter才是防火墙真正的安全框架(framework),netfilter位于内核空间。
iptables其实是一个命令行工具,位于用户空间,用这个工具操作真正的框架。
netfilter/iptables(下文中简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。
Netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有如下功能:
1.网络地址转换(Network Address Translate)
2.数据包内容修改
3.数据包过滤的防火墙功能
所以说,虽然使用service iptables start
或systemctl start iptables.service
启动iptables"服务",但是其实准确的来说,iptables并没有一个守护进程,所以并不能算是真正意义上的服务,而应该算是内核提供的功能。
iptables基础:
iptables是按照规则来办事的,就来说说规则(rules),规则就是网络管理员预定义的条件,规则一般的定义为"如果数据包头符合这样的条件,就这样处理这个数据包"。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。
当客户端访问服务器的web服务时,客户端发送报文到网卡,而tcp/ip协议栈是属于内核的一部分,所以,客户端的信息会通过内核的TCP协议传输到用户空间中的web服务中,而此时,客户端报文的目标终点为web服务所监听的套接字(IP:Port)上,当web服务需要响应客户端请求时,web服务发出的响应报文的目标终点则为客户端,这个时候,web服务所监听的IP与端口反而变成了原点,我们说过,netfilter才是真正的防火墙,它是内核的一部分,所以,如果我们想要防火墙能够达到"防火"的目的,则需要在内核中设置关卡,所有进出的报文都要通过这些关卡,经过检查后,符合放行条件的才能放行,符合阻拦条件的则需要被阻止。于是,就出现了input关卡和output关卡,而这些关卡在iptables中不被称为"关卡",而被称为"链"。
其实上面描述的场景并不完善,因为客户端发来的报文访问的目标地址可能并不是本机,而是其他服务器,当本机的内核支持IP_FORWARD时,可以将报文转发给其他服务器,这个时候,就会提到iptables中的其他"关卡",也就是其他"链",他们就是"路由前"、"转发"、"路由后",英文名是PREROUTING、FORWARD、POSTROUTING。
也就是说,当启用了防火墙功能时,根据实际情况的不同,报文经过"链"可能不同。如果报文需要转发,那么报文则不会经过INPUT链发往用户空间,而是直接在内核空间中经过FORWARD链和POSTROUTING链转发出去的。
某些常用场景中报文的流向:
- 到本机某进程的报文:PREROUTING --> INPUT
- 由本机转发的报文:PREROUTING --> FORWARD --> POSTROUTING
- 由本机的某进程发出报文(通常为响应报文):OUTPUT --> POSTROUTING
链的概念:
防火墙的作用就在于对经过的报文匹配"规则",然后执行对应的"动作"。所以,当报文经过这些关卡的时候,则必须匹配这个关卡上的规则,但是,这个关卡上可能不止有一条规则,而是有很多条规则,当我们把这些规则串到一个链条上的时候,就形成了"链"。所以,我们把每一个"关卡"想象成如下图中的模样,这样来说,把他们称为"链"更为合适,每个经过这个"关卡"的报文,都要将这条"链"上的所有规则匹配一遍,如果有符合条件的规则,则执行规则对应的动作。
表的概念:
对每个"链"上都放置了一串规则,但是这些规则有些很相似。比如,A类规则都是对IP或者端口的过滤,B类规则是修改报文,那么可以把实现相同功能的规则放在一起。
把具有相同功能的规则的集合叫做"表",不同功能的规则,可以放置在不同的表中进行管理,iptables已经定义了4种表,每种表对应了不同的功能,而定义的规则也都逃脱不了这4种功能的范围,所以,必须先搞明白每种表的作用。
iptables为我们提供了如下规则的分类,或者说,iptables为我们提供了如下"表":
- filter表:负责过滤功能,防火墙;内核模块:iptable_filter
- nat表:network address translation,网络地址转换功能;内核模块:iptable_nat
- mangle表:拆解报文,做出修改,并重新封装的功能:iptable_mangle
- raw表:关闭nat表上启用的连接追踪机制:iptable_raw
自定义的所有规则都是这四种分类中的规则,所有规则都存在于这4张"表"中。
表链关系:
需要注意的是,某些"链"中注定不会包含"某类规则",就像某些"关卡"天生就不具备某些功能一样,比如,A"关卡"只负责打击陆地敌人,没有防空能力,B"关卡"只负责打击空中敌人,没有防御步兵的能力,C"关卡"可能比较NB,既能防空,也能防御陆地敌人,D"关卡"最屌,海陆空都能防。
那让我们来看看,每个"关卡"都有哪些能力,或者说,让我们看看每个"链"上的规则都存在于哪些"表"中。
我们还是以图为例,先看看prerouting"链"上的规则都存在于哪些表中。
注意:下图只用于说明prerouting链上的规则存在于哪些表中,并没有描述表的顺序。
这幅图是什么意思呢?它的意思是说,prerouting"链"只拥有nat表、raw表和mangle表所对应的功能,所以,prerouting中的规则只能存放于nat表、raw表和mangle表中。
那么,根据上述思路,总结一下每个"关卡"都拥有什么功能,即每个"链"中的规则都存在于哪些"表"中。
- PREROUTING的规则可以存在于:raw表,mangle表,nat表。
- INPUT的规则可以存在于:mangle表,filter表,(centos7中还有nat表,centos6中没有)。
- FORWARD的规则可以存在于:mangle表,filter表。
- OUTPUT的规则可以存在于:raw表mangle表,nat表,filter表。
- POSTROUTING的规则可以存在于:mangle表,nat表。
但是,在实际的使用过程中,往往是通过"表"作为操作入口,对规则进行定义的,之所以按照上述过程介绍iptables,是因为从"关卡"的角度更容易从入门的角度理解,但是为了以便在实际使用的时候,更加顺畅的理解它们,此处我们还要将各"表"与"链"的关系罗列出来。
表(功能) <–> 链(钩子):
- raw表中的规则可以被哪些链使用:PREROUTING,OUTPUT
- mangle表中的规则可以被哪些链使用:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
- nat表中的规则可以被哪些链使用:PREROUTING,OUTPUT,POSTROUTING(centos7中还有INPUT,centos6中没有)
- filter表中的规则可以被哪些链使用:INPUT,FORWARD,OUTPUT
还需要注意,因为数据包经过一个"链"的时候,会将当前链的所有规则都匹配一遍,但是匹配时总归要有顺序,应该一条一条的去匹配,相同功能类型的规则会汇聚在一张"表"中,那么,哪些"表"中的规则会放在"链"的最前面执行呢,这时候就需要有一个优先级的问题,拿prerouting"链"做图示。
prerouting链中的规则存放于三张表中,而这三张表中的规则执行的优先级如下:
raw --> mangle --> nat
但是iptables定义了4张"表",当处于同一条"链"时,执行的优先级如下(由高到低):
raw --> mangle --> nat --> filter
但是某些链天生就不能使用某些表中的规则。所以,4张表中的规则处于同一条链的目前只有output链,它就是传说中海陆空都能防守的关卡。
为了更方便的管理,还可以在某个表里面创建自定义链,将针对某个应用程序所设置的规则放置在这个自定义链中,但是自定义链接不能直接使用,只能被某个默认的链当做动作去调用才能起作用,自定义链就是一段比较"短"的链子,这条"短"链子上的规则都是针对某个应用程序制定的,但是这条短的链子并不能直接使用,而是需要"焊接"在iptables默认定义链子上,才能被IPtables使用,这就是为什么默认定义的"链"需要把"自定义链"当做"动作"去引用的原因。
数据经过防火墙的流程:
结合上述所有的描述,可以将数据包通过防火墙的流程总结为下图:
在写iptables规则的时候,要时刻牢记这张路由次序图,灵活配置规则。
规则的概念:
规则:根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,则由规则后面指定的处理动作进行处理;
通俗的解释一下什么是iptables的规则,之前打过一个比方,每条"链"都是一个"关卡",每个通过这个"关卡"的报文都要匹配这个关卡上的规则,如果匹配,则对报文进行对应的处理,比如说,你我二人此刻就好像两个"报文",你我二人此刻都要入关,可是城主有命,只有器宇轩昂的人才能入关,不符合此条件的人不能入关,于是守关将士按照城主制定的"规则",开始打量你我二人,最终,你顺利入关了,而我已被拒之门外,因为你符合"器宇轩昂"的标准,所以把你"放行"了,而我不符合标准,所以没有被放行,其实,"器宇轩昂"就是一种"匹配条件","放行"就是一种"动作","匹配条件"与"动作"组成了规则。
规则由匹配条件和处理动作组成。匹配条件分为基本匹配条件与扩展匹配条件。
基本匹配条件:
源地址Source IP,目标地址Destination IP
上述内容都可以作为基本匹配条件。
扩展匹配条件:
除了上述的条件可以用于匹配,还有很多其他的条件可以用于匹配,这些条件泛称为扩展条件,这些扩展条件其实也是netfilter中的一部分,只是以模块的形式存在,如果想要使用这些条件,则需要依赖对应的扩展模块。
源端口Source Port,目标端口Destination Port
上述内容都可以作为扩展匹配条件。
处理动作:
处理动作在iptables中被称为target(这样说并不准确,我们暂且这样称呼),动作也可以分为基本动作和扩展动作。
此处列出一些常用的动作:
ACCEPT:允许数据包通过。
DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求石沉大海了,过了超时时间才会有反应。
REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。
SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
DNAT:目标地址转换。
REDIRECT:在本机做端口映射。
LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。
第二章 常用命令
查看iptables规则命令:
# 查看对应表的所有规则,-t选项指定要操作的表,省略"-t 表名"时,默认表示操作filter表,-L表示列出规则,即查看规则。
iptables -t 表名 -L
# 查看指定表的指定链中的规则
iptables -t 表名 -L 链名
# 查看指定表的所有规则,并且显示更详细的信息(更多字段),-v表示verbose,表示详细的,冗长的,当使用-v选项时,会显示出"计数器"的信息,由于上例中使用的选项都是短选项,所以一般简写为iptables -t 表名 -vL
iptables -t 表名 -v -L
iptables -vL INPUT
Chain INPUT (policy ACCEPT 3552K packets, 215M bytes)
pkts bytes target prot opt in out source destination
224M 132G ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
2 168 ACCEPT icmp -- any any anywhere anywhere
38341 1996K ACCEPT all -- any any 172.16.31.0/24 anywhere
9210 480K ACCEPT all -- any any 10.253.36.0/24 anywhere
7328 466K ACCEPT tcp -- any any 10.255.224.0/20 anywhere tcp dpt:esmagent
0 0 ACCEPT tcp -- any any 10.255.208.0/21 anywhere tcp dpt:esmagent
305K 18M ACCEPT all -- lo any anywhere anywhere
0 0 ACCEPT tcp -- any any anywhere anywhere state NEW tcp dpt:ssh
字段含义解释:
pkts: 对应规则匹配到的报文的个数。
bytes: 对应匹配到的报文包的大小总和。
target: 规则对应的target,往往表示规则对应的"动作",即规则匹配成功后需要采取的措施。
prot: 表示规则对应的协议,是否只针对某些协议应用此规则。
opt: 表示规则对应的选项。
in: 表示数据包由哪个接口(网卡)流入,即从哪个网卡来。
out: 表示数据包将由哪个接口(网卡)流出,即到哪个网卡去。
source: 表示规则对应的源头地址,可以是一个IP,也可以是一个网段。
destination: 表示规则对应的目标地址。可以是一个IP,也可以是一个网段。
policy表示当前链的默认策略,policy ACCEPT表示上图中INPUT的链的默认动作为ACCEPT,换句话说就是,默认接受通过INPUT关卡的所有请求,所以在配置INPUT链的具体规则时,应该将需要拒绝的请求配置到规则中,说白了就是"黑名单"机制,默认所有人都能通过,只有指定的人不能通过,当我们把INPUT链默认动作设置为接受(ACCEPT),就表示所有人都能通过这个关卡,此时就应该在具体的规则中指定需要拒绝的请求,就表示只有指定的人不能通过这个关卡,这就是黑名单机制,但是,你一定发现了,上图中所显示出的规则,大部分都是接受请求(ACCEPT),并不是想象中的拒绝请求(DROP或者REJECT),这与我们所描述的黑名单机制不符啊,按照道理来说,默认动作为接受,就应该在具体的规则中配置需要拒绝的人,但是上图中并不是这样的,之所以出现上图中的情况,是因为IPTABLES的工作机制导致到,上例其实是利用了这些"机制",完成了所谓的"白名单"机制,并不是我们所描述的"黑名单"机制,我们此处暂时不用关注这一点,之后会进行详细的举例并解释,此处我们只要明白policy对应的动作为链的默认动作即可,或者换句话说,我们只要理解,policy为链的默认策略即可。
packets表示当前链(上例为INPUT链)默认策略匹配到的包的数量,0 packets表示默认策略匹配到0个包。
bytes表示当前链默认策略匹配到的所有包的大小总和。
可以把packets与bytes称作"计数器",上图中的计数器记录了默认策略匹配到的报文数量与总大小,"计数器"只会在使用-v选项时,才会显示出来。
iptables -nvL
Chain INPUT (policy ACCEPT 3552K packets, 215M bytes)
如果想要查看精确的计数值,而不是经过可读性优化过的计数值,那么你可以使用-x选项,表示显示精确的计数值。
iptables -nvxL
Chain INPUT (policy ACCEPT 3555362 packets, 214844217 bytes)
# 表示查看表的所有规则,并且在显示规则时,不对规则中的IP或者端口进行名称反解,-n选项表示不解析IP地址
iptables -t 表名 -n -L
# 表示查看表的所有规则,并且显示规则的序号,--line-numbers选项表示显示规则的序号,注意,此选项为长选项,不能与其他短选项合并,不过此选项可以简写为--line,注意,简写后仍然是两条横杠,仍然是长选项。
iptables --line-numbers -t 表名 -L
# 表示查看表中的所有规则,并且显示更详细的信息(-v选项),不过,计数器中的信息显示为精确的计数值,而不是显示为经过可读优化的计数值,-x选项表示显示计数器的精确值。
iptables -t 表名 -v -x -L
# 实际使用中,为了方便,往往会将短选项进行合并,所以,如果将上述选项都糅合在一起,可以写成如下命令,以filter表为例。
iptables --line -t filter -nvxL
# 只查看filter表中的INPUT链
iptables --line -t filter -nvxL INPUT
增加规则:
注意点:添加规则时,规则的顺序十分重要。
iptables -t 表名 -I 链名 匹配条件 -j 动作
eg: iptables -t filter -I INPUT -s 192.168.172.101 -j DROP
-t 指定表名
-I 插入 insert(队首)
-s 源地址 source
-j 所对应的动作
iptables -t 表名 -A 链名 匹配条件 -j 动作
eg: iptables -t filter -A INPUT -s 192.168.172.101 -j ACCEPT
-A 追加 append(尾部)
# 在指定表的指定链的指定位置添加一条规则
iptables -t 表名 -I 链名 规则序号 匹配条件 -j 动作
eg: iptables -t filter -I INPUT 2 -s 192.168.172.101 -j DROP
删除规则:
1.根据规则的编号删除规则
2.根据具体的匹配条件与动作删除规则
如果没有保存规则,删除规则时要慎重。
# 清空filter表INPUT链中的规则
iptables -F INPUT
-F 冲刷 flush
# 删除指定表中指定链中所有规则的命令
iptables -t 表名 -F 链名
eg: iptables -t filter -F INPUT
# 删除指定表所有链的规则(删除指定表的所有规则)
iptables -t 表名 -F
eg: iptables -t filter -F
# 按照规则序号删除规则,删除指定表的指定链的指定规则,-D表示删除对应链中的规则
iptables -t 表名 -D 链名 规则序号
eg: iptables -t filter -D INPUT 3
# 按照具体的匹配条件与动作删除规则,删除指定表的指定链的指定规则
iptables -t 表名 -D 链名 匹配条件 -j 动作
删除源地址是192.168.172.101,动作是ACCEPT的规则
eg: iptables -D INPUT -s 192.168.172.101 -j ACCEPT
修改规则(慎行):
如果使用-R选项修改规则中的动作,必须指定原规则中的原匹配条件,如:源IP,目标IP等。
# 修改指定表中指定链的指定规则,-R选项表示修改对应链中的规则,使用-R选项时要同时指定对应的链以及规则对应的序号,并且规则中原本的匹配条件不可省略。
iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作
将INPUT链的第一条规则的动作修改为REJECT
eg: iptables -t filter -R INPUT 1 -s 192.168.172.101 -j REJECT
(在指定规则对应的编号后,-s对应的源地址还是不能省略,也就是使用-R选项修改某些规则时,必须指定规则对应的原本的匹配条件,否则,省略-s及参数的话,修改后规则的源地址可能会变成0.0.0.0)
# 修改指定链的默认策略(将FORWARD链的默认策略改为DROP)
iptables -t 表名 -P 链名 动作
eg: iptables -t filter -P FORWARD DROP
-t 要操作的表
-P 要修改的链
保存规则:
# centos6保存规则:
service iptables save
规则默认保存在/etc/sysconfig/iptables文件中
# centos7配置iptables-service的步骤:
# 配置好yum源以后安装iptables-service
yum install -y iptables-services
# 停止firewalld
systemctl stop firewalld
# 禁止firewalld自动启动
systemctl disable firewalld
# 启动iptables
systemctl start iptables
# 将iptables设置为开机自动启动,以后即可通过iptables-service控制iptables服务
systemctl enable iptables
配置完成后就可以用service iptables save保存规则了
# 其他通用方法:
iptables-save可以把当前的iptables规则以"保存后的格式"输出到屏幕上,再配合重定向,将规则重定向到/etc/sysconfig/iptables文件中
iptables-save > /etc/sysconfig/iptables
也可以将/etc/sysconfig/iptables文件中的规重新载入当前的iptables规则,未保存到/etc/sysconfig/iptables文件中的修改将会丢失或者被覆盖
iptables-restore < /etc/sysconfig/iptables
第三章 iptables匹配条件
匹配条件1:源IP地址
-s 指定匹配报文的源地址,可以同时指定多个源地址,每个IP之间用逗号隔开,也可以指定为一个网段。
# 指定源地址时,一次指定多个,用","隔开
iptables -t filter -I INPUT -s 192.168.172.101,192.168.172.102 -j DROP
# 指定网段
iptables -t filter -I INPUT -s 192.168.172.0/24 -j DROP
# 匹配条件取反
源IP地址只要不是192.168.172.101就接受报文
iptables -t filter -I INPUT ! -s 192.168.172.101 -j ACCEPT
只要报文的源IP不是192.168.172.101,就接受此报文。也就是说,报文的源IP不是192.168.172.101时,会被接收,并不能代表,报文的源IP是192.168.172.101时,会被拒绝。因为并没有任何一条规则指明源IP是192.168.172.101时,该执行怎样的动作,所以,当来自192.168.172.101的报文经过INPUT链时,并不能匹配上例中的规则,于是,此报文就继续匹配后面的规则,可是,上例中只有一条规则,这条规则后面没有其他可以匹配的规则,于是,此报文就会去匹配当前链的默认动作(默认策略),而上例中,INPUT链的默认动作为ACCEPT,所以,来自101的ping报文就被接收了,如果,把上例中INPUT链的默认策略改为DROP,那么,101的报文将会被丢弃,101上的ping命令将得不到任何回应,但是如果将INPUT链的默认策略设置为DROP,当INPUT链中没有任何规则时,所有外来报文将会被丢弃,包括我们ssh远程连接。
匹配条件2:目标IP地址
-d 指定匹配报文的目标地址,可以同时指定多个目标地址,每个IP之间用逗号隔开,也可以指定为一个网段。
# 丢弃192.168.172.101主机给192.168.172.111这个IP发送的报文
iptables -t filter -I INPUT -s 192.168.172.101 -d 192.168.172.111 -j DROP
# 不指定源IP,则默认源IP为0.0.0.0,即丢弃所有IP给192.168.172.111这个IP发送的报文
iptables -t filter -I INPUT -d 192.168.172.111 -j DROP
-d也可以指定网段,","分隔,"!"取反
iptables -t filter -I INPUT -d 192.168.172.101,192.168.172.102 -j DROP
iptables -t filter -I INPUT -d 192.168.172.0/24 -j DROP
iptables -t filter -I INPUT ! -d 192.168.172.101 -j ACCEPT
注意:-s和-d的"!"取反和","分隔不能同时使用
当一条规则中有多个匹配条件时,这多个匹配条件之间,默认存在"与"的关系,也就是报文同时满足这些条件。才能被规则匹配。
匹配条件3:协议类型
-p 指定需要匹配的报文的协议类型
centos6中-p选项支持如下协议类型:
tcp,udp,udplite,icmp,esp,ah,sctp
centos7中-p选项支持如下协议类型:
tcp,udp,udplite,icmp,icmpv6,esp,ah,sctp,mh
当不使用-p指定协议类型时,默认表示所有类型的协议都会被匹配到,与使用-p all
的效果相同。
# 只拒绝来自192.168.172.101发给192.168.172.111的tcp请求
iptables -I INPUT -s 192.168.172.101 -d 192.168.172.111 -p tcp -j REJECT
iptables -t filter -I INPUT ! -p udp -s 192.168.172.101 -j REJECT
匹配条件4:网卡接口
-i 指定网卡名称,匹配报文从哪块网卡流入,只能用于PREROUTING链,INPUT链,FORWARD链。
# 拒绝由网卡eth4流入的ping请求报文
iptables -t filter -I INPUT -i eth4 -p icmp -j DROP
iptables -t filter -I INPUT ! -i eth4 -p icmp -j DROP
-o 指定网卡名称,匹配报文将从哪个网卡流出,只能用于FORWARD链,OUTPUT链,POSTROUTING链。
iptables -t filter -I OUTPUT -p icmp -o eth4 -j DROP
iptables -t filter -I OUTPUT -p icmp ! -o eth4 -j DROP
第四章 iptables扩展匹配条件
扩展匹配条件:要是用扩展匹配条件,则需要依赖一些扩展模块。
扩展匹配条件1:tcp扩展模块
**1.--sport **
-p tcp -m tcp –sport
(--sport即--source-port),用于匹配tcp协议报文的源端口,可以使用冒号指定一个连续的端口范围。
2.--dport
-p tcp -m tcp –dport
(--dport即--destination-port),用于匹配tcp协议报文的目标端口,可以使用冒号指定一个连续的端口范围。
都可以使用"!"取反,即"! --dport 22"
都指定端口范围,"--dport 22:25"表示目标端口为22到25之间的所有端口,即22端口、23端口、24端口、25端口
"--dport :22" 0-22之间的所有端口
"--dport 80:" 80以及以后的所有端口(直到65535)
-m 指定扩展模块名称 tcp扩展模块
-p 指定匹配报文的协议
iptables -t filter -I OUTPUT -d 192.168.172.101 -p tcp -m tcp --sport 22 -j REJECT
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m tcp --dport 22:25 -j ACCEPT
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m tcp --dport :22 -j ACCEPT
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m tcp --dport 80: -j ACCEPT
iptables -t filter -I OUTPUT -d 192.168.172.101 -p tcp -m tcp ! --sport 22 -j ACCEPT
iptables -t filter -I OUTPUT -d 192.168.172.101 -p tcp --sport 22 -j REJECT
隐含了-m tcp之意,表示使用了tcp扩展模块的--sport扩展匹配条件
3.--tcp-flags
"--tcp-flags"指的是tcp头的标志位,去匹配tcp报文头部的标志位,根据标志位的实际情况实现访问控制的功能。
把这串字符拆成两部分去理解,第一部分为"SYN,ACK,FIN,RST,URG,PSH",第二部分为"SYN"。
# 第一次握手
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
第一部分表示:需要匹配报文tcp头中的哪些标志位,那么上例的配置表示,需要匹配报文tcp头中的6个标志位,这6个标志位分别为为"SYN、ACK、FIN、RST、URG、PSH",可以把这一部分理解成需要匹配的标志位列表。
第二部分表示:第一部分的标志位列表中,哪些标志位必须为1,上例中,第二部分为SYN,则表示,第一部分需要匹配的标志位列表中,SYN标志位的值必须为1,其他标志位必须为0。
# 第二次握手
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECT
# 第三次握手
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH ACK -j REJECT
# 或者上面3条还可以简写成下面这样:
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN,ACK -j REJECT
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL ACK -j REJECT
# 用ALL来表示"SYN,ACK,FIN,RST,URG,PSH"
4.--sync
相当于使用"--tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN",使用--sync匹配tcp新建连接的请求报文。
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --sync -j REJECT
扩展匹配条件2:multiport扩展模块,指定多个离散的端口。
常用的扩展匹配条件如下:
-p tcp -m multiport --sports
用于匹配报文的源端口,可以指定离散的多个端口号,端口之间用"逗号"隔开。
-p udp -m multiport --dports
用于匹配报文的目标端口,可以指定离散的多个端口号,端口之间用"逗号"隔开。
可以使用multiport模块的--sports扩展条件同时指定多个离散的源端口。
可以使用multiport模块的--dports扩展条件同时指定多个离散的目标端口。
iptables -t filter -I OUTPUT -d 192.168.172.101 -p udp -m multiport --sports 137,138 -j REJECT
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m multiport --dports 22,80 -j DROP
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m multiport ! --dports 22,80 -j DROP
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m multiport --dports 80:88 -j REJECT
iptables -t filter -I INPUT -s 192.168.172.101 -p tcp -m multiport --dports 22,80:88 -j REJECT
扩展匹配条件3:iprange扩展模块,一段连续的IP地址范围,用于匹配报文的源地址或者目标地址。
常用扩展匹配条件如下:
--src-range
:匹配报文的源地址所在范围。
--dst-range
:匹配报文的目标地址所在范围。
iptables -t filter -I INPUT -m iprange --src-range 192.168.172.101-192.168.172.111 -j DROP
iptables -t filter -I OUTPUT -m iprange --dst-range 192.168.172.101-192.168.172.111 -j DROP
iptables -t filter -I INPUT -m iprange ! --src-range 192.168.172.101-192.168.172.111 -j DROP
扩展匹配条件4:string扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件。
常用扩展匹配条件如下:
--algo
:用于指定匹配算法,可选的算法有bm与kmp,此选项为必须选项,我们不用纠结于选择哪个算法,但是我们必须指定一个。
--string
:用于指定需要匹配的字符串。
iptables -t filter -I INPUT -m string --algo bm --string "OOXX" -j REJECT
iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "OOXX" -j REJECT
"-m string"表示使用string模块,"--algo bm"表示使用bm算法去匹配指定的字符串,"--string "OOXX""则表示我们想要匹配的字符串为"OOXX"
扩展匹配条件5:time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件。
常用扩展匹配条件如下:
--timestart
:用于指定时间范围的开始时间,不可取反
--timestop
:用于指定时间范围的结束时间,不可取反
--weekdays
:用于指定"星期几",可取反
--monthdays
:用于指定"几号",可取反
--datestart
:用于指定日期范围的开始日期,不可取反
--datestop
:用于指定日期范围的结束时间,不可取反
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 18:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 18:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --monthdays 22,23 -j REJECT
# 多个条件之间存在默认"与"的关系
# 必须为周五,且这个周五需要是每个月22-28号之间的一天
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --datestart 2022-08-22 --datestop 2022-08-24 -j REJECT
扩展匹配条件6:connlimit扩展模块,可以限制每个IP地址同时连接到server端的链接数量,注意:不指定IP默认就是针对"每个客户端IP",即对单IP的并发连接数限制。
常用扩展匹配条件如下:
--connlimit-above
:单独使用此选项时,表示限制每个IP的链接数量。
--connlimit-mask
:此选项不能单独使用,在使用--connlimit-above选项时,配合此选项,则可以针对"某类IP段内的一定数量的IP"进行连接数量的限制。
# 限制每个IP地址最多只能占用2个ssh连接远程到server端,上限是2。
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
# 每个客户端IP的ssh链接数量只要不超过两个,则允许链接。(并不能表示:每个客户端IP的ssh链接数量超过两个则拒绝链接)
iptables -I INPUT -p tcp --dport 22 -m connlimit ! --connlimit-above 2 -j ACCEPT
# 限制某类网段的链接数量
# 一个最多包含254个IP的C类网络中,同时最多只能有2个ssh客户端连接到当前服务器。
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 --connlimit-mask 24 -j REJECT
# 这个网段最多只能30个IP,这30个IP最多只能有10个ssh连接同时连接到服务器端。
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 --connlimit-mask 27 -j REJECT
扩展匹配条件7:limit扩展模块,对"报文到达速率"进行限制,限制单位时间内流入的包的数量。
常用的扩展匹配条件如下:
--limit-burst
:类比"令牌桶"算法,此选项用于指定令牌桶中令牌的最大数量。
--limit
:类比"令牌桶"算法,此选项用于指定令牌桶中生成新令牌的频率,可用时间单位有second、minute、hour、day。
# 外部主机对本机进行ping操作时,最多每6秒放行一个ping包
iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
# 匹配漏网之鱼
iptables -t filter -A INPUT -p icmp -j REJECT
# --limit-burst 可以指定"空闲时可放行的包的数量",默认值是5(也就是在用--limit进行报文到达速率限制时,前5个ping包并不会受到任何速率限制),这里用到了"令牌桶"算法。
# 有一个木桶,木桶里面放了5块令牌,而且这个木桶最多也只能放下5块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔6秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足5块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在5块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有5个报文想要入关,那么这5个报文就去木桶里找令牌,正好一人一个,于是他们5个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了6秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到5个令牌,并且一直保持着5个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑。
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
# 可以选择的时间单位:
/second
/minute
/hour
/day
eg: 3/second 每秒3个,30/minute 每分钟30个
扩展匹配条件8:udp扩展模块
常用的扩展匹配条件:
--sport
:匹配udp报文的源地址
--dport
:匹配udp报文的目标地址
iptables -t filter -I INPUT -p udp -m udp --dport 137 -j ACCEPT
# 当使用扩展匹配条件时,如果未指定扩展模块,iptables会默认调用与"-p"对应的协议名称相同的模块,所以,当使用"-p udp"时,可以省略"-m udp"。
iptables -t filter -I INPUT -p udp --dport 137 -j ACCEPT
iptables -t filter -I INPUT -p udp --dport 137:157 -j ACCEPT
扩展匹配条件9:icmp扩展模块
ICMP协议的全称为Internet Control Message Protocol,翻译为互联网控制报文协议,它主要用于探测网络上的主机是否可用,目标是否可达,网络是否通畅,路由是否可用等。
常用的扩展匹配条件:
--icmp-type
:匹配icmp报文的具体类型
# 别的主机向我们发送的ping请求报文无法进入防火墙,我们向别人发送的ping请求对应的回应报文也无法进入防火墙。即既无法ping通别人,别人也无法ping通我们。
iptables -t filter -I INPUT -p icmp -j REJECT
# 只想要ping通别人,但是不想让别人ping通我们,--icmp-type 8/0表示icmp报文的type为8,code为0才会被匹配到,也就是只有ping请求类型的报文才能被匹配到。
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT
# 因为type为8的类型下只有1个code为0的类型,所以可以省略对应的code
iptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECT
# 可以用icmp报文的描述名称匹配对应类型的报文,注意:名称中的"空格"需要替换成"-"。
iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT
iptables -t filter -I OUTPUT -p icmp --icmp-type 0/0 -j REJECT
iptables -t filter -I OUTPUT -p icmp --icmp-type 0 -j REJECT
扩展匹配条件10:state模块
可以让iptables实现"连接追踪"机制。
对于state模块而言的"连接"并不能与tcp的"连接"划等号,在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在"你来我往"的通信,就算建立起了连接,如下图所示
对于state模块的连接而言,"连接"其中的报文可以分为5种状态,报文状态可以为NEW,ESTABLISHED,RELATED,INVALID,UNTRACKED。
注意:如下报文状态都是对于state模块来说的。
NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。
ESTABLISHED:可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。
RELATED:从字面上理解RELATED译为关系,但是这样仍然不容易理解,我们举个例子。
比如FTP服务,FTP服务端会建立两个进程,一个命令进程,一个数据进程。
命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个"连接",暂称为"命令连接")。
数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为"数据连接")。
但是具体传输哪些数据,是由命令去控制的,所以,"数据连接"中的报文与"命令连接"是有"关系"的。
那么,"数据连接"中的报文可能就是RELATED状态,因为这些报文与"命令连接"中的报文有关系。
(注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块nf_conntrack_ftp,如果想要自动加载,可以配置/etc/sysconfig/iptables-config
文件)
INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。
UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。
# 将状态为RELATED或ESTABLISHED的报文放行,就表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新的报文,则无法通过防火墙
iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
第五章 iptables的黑白名单机制
报文在经过iptables的链时,会匹配链中的规则,遇到匹配的规则时,就执行对应的动作,如果链中的规则都无法匹配到当前报文,则使用链的默认策略(默认动作),链的默认策略通常设置为ACCEPT或者DROP。
当链的默认策略设置为ACCEPT时,如果对应的链中没有配置任何规则,就表示接受所有的报文,如果对应的链中存在规则,但是这些规则没有匹配到报文,报文还是会被接受。
同理,当链的默认策略设置为DROP时,如果对应的链中没有配置任何规则,就表示拒绝所有报文,如果对应的链中存在规则,但是这些规则没有匹配到报文,报文还是会被拒绝。
当链的默认策略为ACCEPT时,链中的规则对应的动作应该为DROP或者REJECT,表示只有匹配到规则的报文才会被拒绝,没有被规则匹配到的报文都会被默认接受,这就是"黑名单"机制。
同理,当链的默认策略为DROP时,链中的规则对应的动作应该为ACCEPT,表示只有匹配到规则的报文才会被放行,没有被规则匹配到的报文都会被默认拒绝,这就是"白名单"机制。
白名单机制更安全,黑名单机制更灵活。
白名单:
# INPUT链默认策略设为DROP
iptables -P INPUT DROP
iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
默认策略设置为DROP的缺点,在对应的链中没有设置任何规则时,这样使用默认策略为DROP是非常不明智的,因为管理员也会把自己拒之门外,即使对应的链中存在放行规则,当我们不小心使用"iptables -F"清空规则时,放行规则被删除,则所有数据包都无法进入,这个时候就相当于给管理员挖了个坑,所以,我们如果想要使用"白名单"的机制,最好将链的默认策略保持为"ACCEPT",然后将"拒绝所有请求"这条规则放在链的尾部,将"放行规则"放在前面,这样做,既能实现"白名单"机制,又能保证在规则被清空时,管理员还有机会连接到主机。
iptables -P INPUT ACCEPT
iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
# 拒绝所有请求的规则
iptables -A INPUT -j REJECT
既将INPUT链的默认策略设置为了ACCEPT,同时又使用了白名单机制,因为如果报文符合放行条件,则会被前面的放行规则匹配到,如果报文不符合放行条件,则会被最后一条拒绝规则匹配到。此刻,即使我们误操作,执行了"iptables -F"操作,也能保证管理员能够远程到主机上进行维护,因为默认策略仍然是ACCEPT。
第六章 iptables自定义链
原因:当iptables默认链非常多不方便管理时,可以使用iptables自定义链。自定义链不能直接使用,需要被默认链引用才能使用。
创建自定义链
# -N 创建自定义链
iptables -t filter -N IN_WEB
引用自定义链
给自定义链配置规则:
iptables -t filter -I IN_WEB -s 192.168.172.101 -j REJECT
iptables -I IN_WEB -s 192.168.172.111 -j ACCEPT
自定义链在哪里创建,应该被哪条默认链引用,取决于实际的工作场景,此处示例的规则是匹配入站报文,所以在INPUT链中引用自定义链:
iptables -I INPUT -p tcp --dport 80 -j IN_WEB
访问本机80端口的tcp报文将会被这条规则匹配到
上述规则中的"-j IN_WEB"表示:访问80端口的tcp报文将由自定义链"IN_WEB"中的规则进行处理,没错,在之前的示例中,使用"-j"选项指定动作,而此处,我们将"动作"替换为了"自定义链",当"-j"对应的值为一个自定义链时,就表示被当前规则匹配到的报文将交由对应的自定义链处理,具体怎样处理,取决于自定义链中的规则,当IN_WEB自定义链被INPUT链引用以后,可以发现,IN_WEB链的引用计数已经变为1,表示这条自定义链已经被引用了1次。
Chain IN_WEB (1 references)
target prot opt source destination
ACCEPT all -- 192.168.172.104 0.0.0.0/0
REJECT all -- 192.168.172.103 0.0.0.0/0 reject-with icmp-port-unreachable
重命名自定义链
# -E 对自定义链重命名
iptables -E IN_WEB WEB
删除自定义链
# -X 删除一个引用数为0,且为空的自定义链,需要满足两个条件:
1.自定义链没有被任何默认链引用,即自定义链的引用计数为0
2.自定义链中没有任何规则,即自定义链为空
删除对应的引用规则:
iptables -D INPUT 1
清空对应的自定义链:
iptables -t filter -F WEB
删除自定义链:
iptables -t filter -X WEB
第七章 网络防火墙
网络防火墙往往处于网络的入口或者边缘,那么,如果想要使用iptables充当网络防火墙,iptables所在的主机则需要处于网络入口处。
当外部网络中的主机与网络内部主机通讯时,不管是由外部主机发往内部主机的报文,还是由内部主机发往外部主机的报文,都需要经过iptables所在的主机,由iptables所在的主机进行"过滤并转发"。所以,防火墙主机的主要工作就是"过滤并转发"。
# 配置iptables网络防火墙,过滤与转发,白名单机制
iptables -A FORWARD -j REJECT
# 放行内部主机对外部主机的web请求
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
# 放行外部主机对内部主机的回应报文
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 80 -j ACCEPT
iptables -D FORWARD 1(删除iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 80 -j ACCEPT)
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# 内部主机访问外部的sshd服务
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
# 如果想要iptables作为网络防火墙,iptables所在主机开启核心转发功能,以便能够转发报文。
# 使用如下命令查看当前主机是否已经开启了核心转发,0表示未开启,1表示已开启
cat /proc/sys/net/ipv4/ip_forward
# 使用如下两种方法均可临时开启核心转发,立即生效,但是重启网络配置后会失效。
方法一:echo 1 > /proc/sys/net/ipv4/ip_forward
方法二:sysctl -w net.ipv4.ip_forward=1
# 使用如下方法开启核心转发功能,重启网络服务后永久生效。
配置/etc/sysctl.conf文件(centos7中配置/usr/lib/sysctl.d/00-system.conf文件),在配置文件中将 net.ipv4.ip_forward设置为1
# 由于iptables此时的角色为"网络防火墙",所以需要在filter表中的FORWARD链中设置规则。
# 可以使用"白名单机制",先添加一条默认拒绝的规则,然后再为需要放行的报文设置规则。
# 配置规则时需要考虑"方向问题",针对请求报文与回应报文,考虑报文的源地址与目标地址,源端口与目标端口等。
# 示例为允许网络内主机访问网络外主机的web服务与sshd服务。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 22 -j ACCEPT
#可以使用state扩展模块,对上述规则进行优化,使用如下配置可以省略许多"回应报文放行规则"。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
一些注意点:
1.当测试网络防火墙时,默认前提为网络已经正确配置。
2.当测试网络防火墙时,如果出现问题,请先确定主机防火墙规则的配置没有问题。
第八章 iptables动作总结
基础动作:ACCEPT,DROP
1.扩展动作:REJECT
-j 指定动作
REJECT动作的常用选项为--reject-with
使用--reject-with选项,可以设置提示信息,当对方被拒绝时,会提示对方为什么被拒绝。
可用值如下:
icmp-net-unreachable
icmp-host-unreachable
icmp-port-unreachable,
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-pro-hibited
icmp-admin-prohibited
当不设置任何值时,默认值为icmp-port-unreachable。
iptables -I INPUT 2 -j REJECT --reject-with icmp-host-unreachable
2.扩展动作:动作LOG
使用LOG动作,可以将符合条件的报文的相关信息记录到日志中,但当前报文具体是被"接受",还是被"拒绝",都由后面的规则控制,换句话说,LOG动作只负责记录匹配到的报文的相关信息,不负责对报文的其他处理,如果想要对报文进行进一步的处理,可以在之后设置具体规则,进行进一步的处理。
iptables -I INPUT -p tcp --dport 22 -j LOG
上述规则表示所有发往22号端口的tcp报文都符合条件,所以都会被记录到日志中,查看/var/log/messages即可看到对应报文的相关信息,但是上述规则只是用于示例,因为上例中使用的匹配条件过于宽泛,所以匹配到的报文数量将会非常之多,记录到的信息也不利于分析,所以在使用LOG动作时,匹配条件应该尽量写的精确一些,匹配到的报文数量也会大幅度的减少,这样冗余的日志信息就会变少,同时日后分析日志时,日志中的信息可用程度更高。
LOG动作会将报文的相关信息记录在/var/log/message
文件中,当然,我们也可以将相关信息记录在指定的文件中,以防止iptables的相关信息与其他日志信息相混淆,修改/etc/rsyslog.conf
文件(或者/etc/syslog.conf
),在rsyslog配置文件中添加如下配置即可。
vim /etc/rsyslog.conf
kern.warning /var/log/iptables.log
加入上述配置后,报文的相关信息将会被记录到/var/log/iptables.log文件中。
完成上述配置后,重启rsyslog服务(或者syslogd)
service rsyslog restart
服务重启后,配置即可生效,匹配到的报文的相关信息将被记录到指定的文件中。
LOG动作也有自己的选项,常用选项如下(先列出概念,后面有示例)
--log-level选项可以指定记录日志的日志级别,可用级别有emerg,alert,crit,error,warning,notice,info,debug。
--log-prefix选项可以给记录到的相关信息添加"标签"之类的信息,以便区分各种记录到的报文信息,方便在分析时进行过滤。
注:--log-prefix对应的值不能超过29个字符。
# 将主动连接22号端口的报文的相关信息都记录到日志里
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -j LOG --log-prefix "want-in-from-port-22"
NAT是Network Address Translation的缩写,译为"网络地址转换",NAT说白了就是修改报文的IP地址,NAT功能通常会被集成到路由器、防火墙、或独立的NAT设备中。
主机A:扮演公网主机,尝试访问公司提供的服务
模拟公网IP地址为192.168.1.147
主机B:扮演了拥有NAT功能的防火墙或路由器,充当网关,并且负责NAT,公网、私网通讯的报文通过B主机时,报文会被NAT
模拟公网IP为:192.168.1.146
模拟私网IP为:10.1.0.3
主机C:扮演内网web服务器
模拟私网IP为:10.1.0.1
主机D:扮演内网windows主机
模拟私网IP为:10.1.0.6
如果想要NAT功能能够正常使用,需要开启Linux主机的核心转发功能。
echo 1 > /proc/sys/net/ipv4/ip_forward
3.扩展动作:SNAT
当网络内部的主机向网络外部主机发送报文时,报文会经过防火墙或路由器,当报文经过防火墙或路由器时,将报文的源IP修改为防火墙或者路由器的IP地址,当其他网络中的主机收到这些报文时,显示的源IP地址则是路由器或者防火墙的,而不是那10台主机的IP地址,这样,就起到隐藏网络内部主机IP的作用,当网络内部主机的报文经过路由器时,路由器会维护一张NAT表,表中记录了报文来自于哪个内部主机的哪个进程(内部主机IP+端口),当报文经过路由器时,路由器会将报文的内部主机源IP替换为路由器的IP地址,把源端口也映射为某个端口,NAT表会把这种对应关系记录下来。
源IP|源PORT|目标IP|目标PORT --> 路由IP|映射后的PORT|目标IP|目标PORT
外部主机收到报文时,源IP与源端口显示的都是路由的IP与端口,当外部网络中的主机进行回应时,外部主机将响应报文发送给路由器,路由器根据刚才NAT表中的映射记录,将响应报文中的目标IP与目标端口再改为内部主机的IP与端口号,然后再将响应报文发送给内部网络中的主机。整个过程中,外部主机都不知道内部主机的IP地址,内部主机还能与外部主机通讯,于是起到了隐藏网络内主机IP的作用。
上述整个过程中,就用到了NAT功能,准确的说是用到了NAPT功能,NAPT是NAT的一种,全称为Network Address Port Translation,就是映射报文IP地址的同时还会映射其端口号。
IP地址的转换一共发生了两次:
1.内部网络的报文发送出去时,报文的源IP会被修改,也就是源地址转换:Source Network Address Translation,缩写为SNAT。
2.外部网络的报文响应时,响应报文的目标IP会再次被修改,也就是目标地址转换:Destinationnetwork address translation,缩写为DNAT。
上述"整个过程"被称为SNAT,因为"整个过程"的前半段使用了SNAT,如果上述"整个过程"的前半段使用了DNAT,则整个过程被称为DNAT,也就是说,整个过程被称为SNAT还是DNAT,取决于整个过程的前半段使用了SNAT还是DNAT。
其实刚才描述的场景不仅仅能够隐藏网络内部主机的IP地址,还能够让局域网内的主机共享公网IP,让使用私网IP的主机能够访问互联网。
比如,整个公司只有一个公网IP,但是整个公司有10台电脑,我们怎样能让这10台电脑都访问互联网呢?我们可以为这10台电脑都配置上各自的私网IP,比如"192.168"这种私网IP,但是互联网是不会路由私网IP的,如果想要访问互联网,则必须使用公网IP,那么,我们就需要想办法,能让这10台主机共享公司仅有的一个公网IP,没错,这与刚才描述的场景其实完全一致,我们只要在路由器上配置公网IP,在私网主机访问公网服务时,报文经过路由器,路由器将报文中的私网IP与端口号进行修改和映射,将其映射为公网IP与端口号,这时,内网主机即可共享公网IP访问互联网上的服务了。
SNAT不仅能够隐藏网内的主机IP,还能够共享公网IP,这在IPV4地址较为紧张的今天,是非常有用的。
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 192.168.1.146
"-t nat"表示操作nat表,不同的表有不同的功能,filter表的功能是过滤,nat表的功能就是地址转换,需要在nat表中定义nat规则。
"-A POSTROUTING"表示将SNAT规则添加到POSTROUTING链的末尾,在centos7中,SNAT规则只能存在于POSTROUTING链与INPUT链中,在centos6中,SNAT规则只能存在于POSTROUTING链中。为什么SNAT规则必须定义在POSTROUTING链中,POSTROUTING链是iptables中报文发出的最后一个"关卡",应该在报文马上发出之前修改报文的源地址,否则就再也没有机会修改报文的源地址了,在centos7中,SNAT规则也可以定义在INPUT链中,我们可以这样理解,发往本机的报文经过INPUT链以后报文就到达了本机,如果再不修改报文的源地址,就没有机会修改了。
"-s 10.1.0.0/16"表示报文来自于10.1.0.0/16网段。
"-j SNAT"表示使用SNAT动作,对匹配到的报文进行处理,对匹配到的报文进行源地址转换。
"--to-source 192.168.1.146"表示将匹配到的报文的源IP修改为192.168.1.146,"--to-source"就是SNAT动作的常用选项,用于指定SNAT需要将报文的源IP修改为哪个IP地址。
共享ip配置如下SNAT规则:
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP
4.扩展动作:DNAT
公司有自己的局域网,网络中有两台主机作为服务器,主机1提供web服务,主机2提供数据库服务,但是这两台服务器在局域网中使用私有IP地址,只能被局域网内的主机访问,互联网无法访问到这两台服务器,整个公司只有一个可用的公网IP,怎样通过这个公网IP访问到内网中的这些服务呢?我们可以将这个公网IP配置到公司的某台主机或路由器上,然后对外宣称,这个IP地址对外提供web服务与数据库服务,于是互联网主机将请求报文发送给这公网 IP地址,也就是说,此时报文中的目标IP为公网IP,当路由器收到报文后,将报文的目标地址改为对应的私网地址,比如,如果报文的目标IP与端口号为:公网IP+3306,我们就将报文的目标地址与端口改为:主机2的私网IP+3306,同理,公网IP+80端口映射为主机1的私网IP+80端口,当私网中的主机回应对应请求报文时,再将回应报文的源地址从私网IP+端口号映射为公网IP+端口号,再由路由器或公网主机发送给互联网中的主机。
上述过程也牵扯到DNAT与SNAT,但是由于整个过程的前半段使用了DNAT,所以上述过程被称为DNAT。
其实,不管是SNAT还是DNAT,都起到了隐藏内部主机IP的作用。
iptables -t nat -I PREROUTING -d 192.168.1.146 -p tcp --dport 3386 -j DNAT --to-destination 10.1.0.6:3389
"-t nat -I PREROUTING"表示在nat表中的PREROUTING链中配置DNAT规则,DNAT规则只配置在PREROUTING链与OUTPUT链中。
"-d 192.168.1.146 -p tcp --dport 3389"表示报文的目标地址为公司的公网IP地址,目标端口为tcp的3389号端口,而我们知道,windows远程桌面使用的默认端口号就是3389,当外部主机访问公司公网IP的3389号端口时,报文则符合匹配条件。
"-j DNAT --to-destination 10.1.0.6:3389"表示将符合条件的报文进行DNAT,也就是目标地址转换,将符合条件的报文的目标地址与目标端口修改为10.1.0.6:3389,"--to-destination"就是动作DNAT的常用选项。
规则的含义为,当外网主机访问公司公网IP的3389时,其报文的目标地址与端口将会被映射到10.1.0.6:3389上。
iptables -t nat -I PREROUTING -d 192.168.1.146 -p tcp --dport 801 -j DNAT --to-destination 10.1.0.1:80
将公司公网IP的801号端口映射到了公司内网中C主机的80端口,所以,当外网主机访问公司公网IP的801端口时,报文将会发送到C主机的80端口上。
配置DNAT,可以通过公网IP访问局域网内的服务。
注:理论上来说,只要配置DNAT规则,不需要对应的SNAT规则即可达到DNAT效果。
但是在测试DNAT时,对应SNAT规则也需要配置,才能正常DNAT,可以先尝试只配置DNAT规则,如果无法正常DNAT,再尝试添加对应的SNAT规则,SNAT规则配置一条即可,DNAT规则需要根据实际情况配置不同的DNAT规则。
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 公网端口 -j DNAT --to-destination 私网IP:端口号
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 8080 -j DNAT --to-destination 10.1.0.1:80
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP
5.扩展动作:MASQUERADE
当我们拨号网上时,每次分配的IP地址往往不同,不会长期分给我们一个固定的IP地址,如果这时,我们想要让内网主机共享公网IP上网,就会很麻烦,因为每次IP地址发生变化以后,都要重新配置SNAT规则,这样显示不是很人性化,通过MASQUERADE即可解决这个问题,MASQUERADE会动态的将源地址转换为可用的IP地址,其实与SNAT实现的功能完全一致,都是修改源地址,只不过SNAT需要指明将报文的源地址改为哪个IP,而MASQUERADE则不用指定明确的IP,会动态的将报文的源地址修改为指定网卡上可用的IP地址,示例如下:
iptables -t nat -I POSTROUTING -s 10.1.0.0/16 -o ens33 -j MASQUERADE
通过外网网卡出去的报文在经过POSTROUTING链时,会自动将报文的源地址修改为外网网卡上可用的IP地址,这时,即使外网网卡中的公网IP地址发生了改变,也能够正常的、动态的将内部主机的报文的源IP映射为对应的公网IP。
可以把MASQUERADE理解为动态的、自动化的SNAT,如果没有动态SNAT的需求,没有必要使用MASQUERADE,因为SNAT更加高效。
6.扩展动作:REDIRECT
使用REDIRECT动作可以在本机上进行端口映射
比如,将本机的80端口映射到本机的8080端口上
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
经过上述规则映射后,当别的机器访问本机的80端口时,报文会被重定向到本机的8080端口上。
REDIRECT规则只能定义在PREROUTING链或者OUTPUT链中。
第九章 iptables总结
1.规则的顺序非常重要。
如果报文已经被前面的规则匹配到,iptables则会对报文执行对应的动作,通常是ACCEPT或者REJECT,报文被放行或拒绝以后,即使后面的规则也能匹配到刚才放行或拒绝的报文,也没有机会再对报文执行相应的动作了(前面规则的动作为LOG时除外)。所以,针对相同服务的规则,更严格的规则应该放在前面。
2.当规则中有多个匹配条件时,条件之间默认存在"与"的关系。
如果一条规则中包含了多个匹配条件,那么报文必须同时满足这个规则中的所有匹配条件,报文才能被这条规则匹配到。
3.在不考虑1的情况下,应该将更容易被匹配到的规则放置在前面。
比如,你写了两条规则,一条针对sshd服务,一条针对web服务。
假设,一天之内,有20000个请求访问web服务,有200个请求访问sshd服务,
那么,应该将针对web服务的规则放在前面,针对sshd的规则放在后面,因为访问web服务的请求频率更高。
如果将sshd的规则放在前面,当报文是访问web服务时,sshd的规则也要白白的验证一遍,由于访问web服务的频率更高,白白耗费的资源就更多。
如果web服务的规则放在前面,由于访问web服务的频率更高,所以无用功会比较少。
换句话说就是,在没有顺序要求的情况下,不同类别的规则,被匹配次数多的、匹配频率高的规则应该放在前面。
4.当iptables所在主机作为网络防火墙时,在配置规则时,应着重考虑方向性,双向都要考虑,从外到内,从内到外。
5.在配置iptables白名单时,往往会将链的默认策略设置为ACCEPT,通过在链的最后设置REJECT规则实现白名单机制,而不是将链的默认策略设置为DROP,如果将链的默认策略设置为DROP,当链中的规则被清空时,管理员的请求也将会被DROP掉。
标签:iptables,--,报文,笔记,学习,tcp,规则,INPUT From: https://www.cnblogs.com/even160941/p/16625142.html