文章目录
- 一、 基本概念
- 二、iptables
- 三、firewalld
- 四、实验练习
一、 基本概念
什么是防火墙?路由策略和策略路由/ipsec vpn gre hdlc ppp 硬件 iDS+
在计算中,防火墙是基于预定安全规则来监视和控制传入和传出网络流量的网络安全系统。该计算机流入流出的所有网络通信均要经过此防火墙。防火墙对流经它的网络通信进行扫描,这样能够过滤掉一些攻击,以免其在目标计算机上被执行。防火墙还可以关闭不使用的端口。而且它还能禁止特定端口的流出通信,封锁特洛伊木马。最后,它可以禁止来自特殊站点的访问,从而防止来自不明入侵者的所有通信。
防火墙分为软件防火墙和硬件防火墙,他们的优缺点:
硬件防火墙: 拥有经过特别设计的硬件及芯片,性能高、成本高(当然硬件防火墙也是有软件的,只不过有部分功能由硬件实现,所以硬件防火墙其实是硬件+软件的方式);
软件防火墙: 应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能比硬件防火墙低、成本低。
链的概念
iptables开启后,数据报文从进入服务器到出来会经过5道关卡,分别为Prerouting(路由前)、Input(输入)、Outpu(输出)、Forward(转发)、Postrouting(路由后):
每一道关卡中有多个规则,数据报文必须按顺序一个一个匹配这些规则,这些规则串起来就像一条链,所以我们把这些关卡都叫**“链”**:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TxHA7jtg-1673436621301)(https://img.xiebruce.top/2019/07/20/e3ffc9afdb8cd8bd450ed917e3fe50e3.png)]
- **INPUT链:**当接收到防火墙本机地址的数据包(入站)时,应用此链中的规则;
- **OUTPUT链:**当防火墙本机向外发送数据包(出站)时,应用此链中的规则;
- **FORWARD链:**当接收到需要通过防火墙发送给其他地址的数据包(转发)时,应用此链中的规则;
- PREROUTING链:(互联网进入局域网)在对数据包作路由选择之前,应用此链中的规则,如DNAT;
- POSTROUTING链:(局域网出互联网)在对数据包作路由选择之后,应用此链中的规则,如SNAT。
其中中INPUT、OUTPUT链更多的应用在“主机防火墙”中,即主要针对服务器本机进出数据的安全控制;而FORWARD、PREROUTING、POSTROUTING链更多的应用在“网络防火墙”中,特别是防火墙服务器作为网关使用时的情况。
表的概念
虽然每一条链上有多条规则,但有些规则的作用(功能)很相似,多条具有相同功能的规则合在一起就组成了一个“表”,iptables提供了四种“表”:
– filter表: 主要用于对数据包进行过滤,根据具体的规则决定是否放行该数据包(如DROP、ACCEPT、REJECT、LOG),所谓的防火墙其实基本上是指这张表上的过滤规则,对应内核模块iptables_filter;
– nat表: network address translation,网络地址转换功能,主要用于修改数据包的IP地址、端口号等信息(网络地址转换,如SNAT、DNAT、MASQUERADE、REDIRECT)。属于一个流的包(因为包的大小限制导致数据可能会被分成多个数据包)只会经过这个表一次,如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作,也就是说,余下的包不会再通过这个表。对应内核模块iptables_nat;
– mangle表: 拆解报文,做出修改,并重新封装,主要用于修改数据包的TOS(Type Of Service,服务类型)、TTL(Time To Live,生存周期)指以及为数据包设置Mark标记,以实现Qos(Quality Of Service,服务质量)调整以及策略路由等应用,由于需要相应的路由设备支持,因此应用并不广泛。对应内核模块iptables_mangle;
– **raw表:**是自1.2.9以后版本的iptables新增的表,主要用于决定数据包是否被状态跟踪机制处理,在匹配数据包时,raw表的规则要优先于其他表,对应内核模块iptables_raw。
我们最终定义的防火墙规则,都会添加到这四张表中的其中一张表中。
表链关系
5条链(即5个关卡)中,并不是每条链都能应用所有类型的表,事实上除了Ouptput链能同时有四种表,其他链都只有两种或三种表:
实际上由上图我们可以看出,无论在哪条链上,raw表永远在mangle表上边,而mangle表永远在nat表上边,nat表又永远在filter表上边,这表明各表之间是有匹配顺序的。
前面说过,数据报文必须按顺序匹配每条链上的一个一个的规则,但其实同一类(即属于同一种表)的规则是放在一起的,不同类的规则不会交叉着放,按上边的规律,每条链上各个表被匹配的顺序为:raw→mangle→nat→filter。
前面说过,我们最终定义的防火墙规则,都会添加到这四张表中的其中一张表中,所以我们实际操作是对“表”进行操作的,所以我们反过来说一下,每种表都能用于哪些链:
表名 | 能应用的链 | ||||
---|---|---|---|---|---|
raw | prerouting | output | |||
mangle | prerouting | input | forward | output | postrouting |
nat | prerouting | input(仅centos7) | output | postrouting | |
filter | input | forward | output |
综上,数据包通过防火墙的流程可总结为下图:
规则的概念
iptables规则主要包含“条件&动作”,即匹配出符合什么条件(规则)后,对它采取怎样的动作。
匹配条件
- S_IP: source ip,源ip
- S_PORT: source port,源端口
- D_IP: destination ip,目标ip
- D_PORT: destination port,目标端口
- **TCP/UDP:**第四层(传输层)协议
处理的动作
- ACCEPT: 允许数据包通过;
- DROP: 直接丢弃数据包,不回应任何信息,客户端只有当该链接超时后才会有反应;
- REJECT: 拒绝数据包,会给客户端发送一个数据包被丢弃的响应的信息;
- SNAT: S指Source,源NAT(源地址转换)。在进入路由层面的route之后,出本地的网络栈之前,改写源地址,目标地址不变,并在本机建立NAT表项,当数据返回时,根据NAT表将目的地址数据改写为数据发送出去时候的源地址,并发送给主机。解决私网用户用同一个公网IP上网的问题;
- MASQUERADE: 是SNAT的一种特殊形式,适用于动态的、临时会变的IP上;
- DNAT: D指Destination,目的NAT,解决私网服务端,接收公网请求的问题。和SNAT相反,IP包经过route之前,重新修改目标地址,源地址不变,在本机建立NAT表项,当数据返回时,根据NAT表将源地址修改为数据发送过来时的目标地址,并发给远程主机。可以隐藏后端服务器的真实地址;
- REDIRECT: 在本机做端口映射;
- LOG: 在
/var/log/messages
文件中记录日志信息,然后将数据包传递给下一条规则。
除去最后一个LOG,前3条规则匹配数据包后,该数据包不会再往下继续匹配了,所以编写的规则顺序极其关键。
其中REJECT和DROP有点类似,以下是服务器设置REJECT和DROP后,ping这个服务器的响应的区别:
REJECT动作:
PING 10.37.129.9 (10.37.129.9): 56 data bytes
92 bytes from centos-linux-6.5.host-only (10.37.129.9): Destination Port Unreachable
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 5400 29a3 0 0000 40 01 3ab1 10.37.129.2 10.37.129.9
Request timeout for icmp_seq 0
92 bytes from centos-linux-6.5.host-only (10.37.129.9): Destination Port Unreachable
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 5400 999d 0 0000 40 01 cab6 10.37.129.2 10.37.129.9
DROP动作:
PING 10.37.129.9 (10.37.129.9): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
Request timeout for icmp_seq 4
二、iptables
语法格式:
iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作
iptables命令操作
对iptables进行操作,其实就是对它的四种“表”进行“增删改查”操作。
启动iptables
由于国内大部分公司的服务器都采用CentOS系统,所以这里以CentOS为例。CentOS6及其之前的CentOS系统都默认使用iptables防火墙,但CentOS7默认已经没有iptables防火墙了,取而代之的是firewalld,不过你还是可以自己安装iptables。
对于CentOS6:
启动iptables(事实上应该叫“加载”iptables模块更合适,前面也说过iptables并不是一个真正的服务,它没有进程,这意味着你用ps -ef | grep iptables
是看不到进程的):
service iptables start
其它命令:
# 查看启动状态
service iptables status
# 停止iptables
service iptables stop
# 重启iptables(重启其实就是先stop再start)
service iptables restart
# 重载就是重新加载配置的规则,在这里貌似跟重启一样
service iptables reload
对于CentOS7:
前面说过,CentOS7默认没有iptables(CentOS7默认防火墙是firewalld),但我们还是可以自己安装iptables。
CentOS7关闭firewalld防火墙:
systemctl stop firewalld
CentOS7关闭firewalld防火墙开机启动:
systemctl disable firewalld
CentOS7安装iptables防火墙:
sudo yum -y install iptables
CentOS7安装iptables的service启动工具:
sudo yum -y install iptables-services
安装完之后,所有启动、停止之类的操作与CentOS6都一样,参考前面CentOS6的操作即可。
但实际上在CentOS7中用service
来操作程序的启停,它会自动跳转到使用systemctl
,所以其实除了用CentOS6的方法,还可以用CentOS7的:
# 启动iptables
systemctl start iptables
# 查看iptables状态
systemctl status iptables
# 停止iptables
systemctl stop iptables
# 重启iptables
systemctl restart iptables
# 重载iptables
systemctl reload iptables
这里要特别注意,稍微了解Linux的童鞋都知道,service
命令是用于启动Linux的进程的(参见这里),但在这里是例外,service iptables start
并没有启动一个进程,你无法用ps aux | grep iptables
的方式看到一个叫iptables
的进程,你只能用service iptables status
去查看它的状态。
所以iptables其实不能叫“服务”,因为它并没有一个“守护进程”,其实iptables只是相当于一个客户端工具,真正的防火墙是Linux内核中的netfilter,由于netfilter是内核功能,用户无法直接操作,iptables这个工具是提供给用户设置过滤规则的,但最终这个过滤规则是由netfilter来执行的。
查询规则
命令格式:iptables [选项] [参数]
常用选项:
-L
: list的缩写,list我们通常翻译成列表,意思是列出每条链上的规则,因为多条规则就是一个列表,所以用-L
来表示。-L
后面还可以跟上5条链(POSTROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING)的其中一条链名,注意链名必须全大写,如查看“INPUT链”上的规则:
iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
不指定的话就是默认查看所有链上的规则列表:
iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
- Chain INPUT: INPUT链上的规则,同理,后面的“Chain FORWARD”、“Chain OUTPUT”分别是FORWARD链和OUTPUT链上的规则;
- (policy ACCEPT): 表示默认策略是接受,即假如我没设置,那就是允许,只有我设置哪个不允许,才会不允许,示例中是安装iptables后的默认规则,由于默认是ACCEPT,你规则也设置为ACCEPT按道理来说是没什么意义的,因为你不设置也是ACCEPT呀,但事实上,是为了方便修改为REJECT/DROP等规则,说白了就是放在那,要设置的时候我们就可以直接修改;
- target: 英文意思是“目标”,但该列的值通常是动作,比如ACCEPT(接受)、REJECT(拒绝)等等,但它确实可以是“目标”,比如我们创建 一条链
iptables -N July_filter
,然后在INPUT链上添加一条规则,让它跳转到刚刚的新链-A INPUT -p tcp -j July_filter
,再用iptables -L
查看,可以看到target此时已经是真正的“target(July_filter)”而不再是动作了:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
July_filter tcp -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain July_filter (1 references)
target prot opt source destination
- prot: protocol,协议;
- opt: option,选项;
- source: 源地址(ip(可以是网段)/域名/主机名)
- destination: 目标地址(ip(可以是网段)/域名/主机名)
- 末列: 一些额外的信息
-t
:前面-L
不是列出所有链的规则列表吗?为什么没有PREROUTING和POSTROUTING链呢?因为有默认参数-t
,t是table的缩写,意思是指定显示哪张“表”中的规则(前面说过iptables有四种表),iptables -L
其实就相当于iptables -t filter -L
,即相当于你查看的是“filter”表中的规则。而根据前面的讲解,filter表只可用于INPUT、FORWARD、OUTPUT三条链中,这就是为什么iptables -L
不显示PREROUTING链和POSTROUTING链的原因。
-n
: numeric的缩写,numeric意思是数字的,数值的,意思是指定源和目标地址、端口什么的都以数字/数值的方式显示,否则默认会以域名/主机名/程序名等显示,该选项一般与-L
合用,因为单独的-n
是没有用的(没有-L
列表都不显示,所以用-n
就没有意义了)。
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
其中dpt:22
中的dpt是指destination port(目标端口),同理,spt就是source port(源端口)。
-v
: 基本上有点Linux常识的童鞋就应该知道,-v
在Linux命令里,一般都是指“verbose”,这个词的意思是是“冗余的,啰嗦的”,即输出更加详细的信息,在iptables这里也是这个意思,一般可以跟-L
连用:
iptables -v -L
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
13627 1033K ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
0 0 ACCEPT icmp -- any any anywhere anywhere
0 0 ACCEPT all -- lo any anywhere anywhere
2 128 ACCEPT tcp -- any any anywhere anywhere state NEW tcp dpt:ssh
275 53284 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 12506 packets, 1485K bytes)
pkts bytes target prot opt in out source destination
可以看到多了四列:
- pkts: packets,包的数量;
- bytes: 流过的数据包的字节数;
- in: 入站网卡;
- out: 出站网卡。
当然还可以跟前面的-n
合用:
iptables -n -v -L
这样source和destination中用域名或者字符串表示的方式就换成ip了:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
13642 1034K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
2 128 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
275 53284 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 12516 packets, 1489K bytes)
pkts bytes target prot opt in out source destination
稍微了解Linux命令的童鞋应该都知道,在很多情况下,Linux的选项是可以合并的,比如前面的iptables -n -v -L
其实是可以合并成iptables -nvL
的,并且参数顺序一般情况下是无关紧要的,比如iptables -vnL
也是一样的。但是-L
一定要写在最后,原因是-L
是要接收参数的选项(虽然可以不传参数),而-v
和-n
是不需要接收参数的,假如你写成iptables -Lvn
,那就表示是用-n
来接收参数了,这肯定是不行的。
-x
: 加了-v
后,Policy那里变成了“(policy ACCEPT 0 packets, 0 bytes)”,即多了过滤的数据包数量和字节数,其中的字节数,如果数据大了之后,会自动转换单位,比如够KB不够MB,它会显示“xxxk”,够了MB它显示“MB”,但单位转换之后,就不完全精确了,因为它没有小数,如果还是想要看以“字母”即“byptes”为单位查看的话,加个-x
就行了,“x”来自于“exact”,意思是“精确的;准确的”,不取首字母应该是太多选项首字母是e了。
--line-numbers
: 如果你想列表有序号,可以加上该选项:
iptables -nvL --line-numbers
结果中多了一列“num”,就是序号:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 14739 1123K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 2 128 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
5 305 55948 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
6 0 0 July_filter tcp -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 310 packets, 42772 bytes)
num pkts bytes target prot opt in out source destination
Chain July_filter (1 references)
num pkts bytes target prot opt in out source destination
其实,--line-numbers
并不用写全,不然也太长了,其实写成--line
就行了,甚至你不写最后一个e,即写成--lin
都行。
合并使用各选项的命令示例:
iptables --line -t filter -nvxL INPUT
添加规则
我们可以向某条链中的某个表的最前面添加记录(我们叫“插入”,会用到-I
选项,I表示Insert),也可以向某条链中的某个表的最后面添加记录(我们叫“追加”,会用到-A
选项,A表示Append),熟悉vi/vim
的童鞋会对这个“I”和“A”感觉到熟悉,因为在vi/vim
的命令模式下,按I
是在光标所行的行首插入,按A
是在光标所在行的行尾插入,跟这个在表头跟表尾插入非常像。
之所以有向前添加和向后添加,是因为如果前面规则的是丢弃或拒绝,那么后面的规则是不会起作用的;而如果前面的是接受后面的是丢弃或拒绝,则接受之后后面的丢弃或拒绝也是不会生效的。
向INPUT链的filter表中添加一条规则:
iptables -t filter -I INPUT -s 10.37.129.2 -j DROP
-t
: 是指定插入到哪个表中,不写的话默认为“filter”表;-I
: 指定插入到哪条链中,并且会在该链指定表(在这里是filter表)中的最前面插入(I:Input),如果用-A
则是在最后插入(A:Append)。-s
: 匹配源ip,s: source,源。-j
: jump,跳转的意思,后面可指定跳转的target(目标),比如自定义的链,当然更多的是跳转到“action(动作)”中,比如ACCEPT、DROP、REJECT等等。- 整个意思,就是向iptables中的“INPUT”链(
-I INPUT
)的“filter”表(-t filter
)的最前面(-I
)添加一条记录,这次记录会匹配源地址为“10.39.129.2”的请求(-s 10.39.129.2
),并把该请求丢弃掉(-j DROP
)。
删除iptables中的记录
1、根据编号删除:
前面说过,查询iptables规则列表时,添加--line-numbers
简写成--line
即可显示记录编号,我们现在就可以根据这个编号来删除了:
iptables -t filter -D INPUT 2
-t filter
指定操作的表为filter表,-D
表示delete,后面跟的两个参数,第一个是链名,第二个是要删除的规则的编号。
2、根据条件删除:
iptables -t filter -D INPUT -s 10.37.129.2 -j DROP
删除INPUT链中的filter表中源地址为“10.37.129.2”并且动作为“DROP”的规则。
3、清空:
-F
: flush的缩写,flush是“冲洗、冲掉”的意思,在这里是清空的意思,iptables -t filter -F INPUT
代表清空“INPUT”链中“filter”表中的所有规则,如果不指定链不指定表,即直接用iptables -F
,则清空所有链中所有表的规则。
修改规则
事实上用“替换”来描述会更好一点,因为所谓的修改其实就是把整个规则替换成新的规则:
iptables -t filter -R INPUT 1 -s 10.37.129.3 -j ACCEPT
其中的-R
就是replace,即替换的意思,整句命令意思是从INPUT链中的filter表中替换编号为1的规则,编号1后面的-s 10.37.129.3 -j ACCEPT
就是要替换成的新规则。
修改策略(policy):
iptables -P FORWARD DROP
-P
: policy,即策略。整个意思是把FORWARD链的默认规则设置为DROP,iptables [-t table] -P chain target
这个说明,表示可以根据不同的表,设置不同的限制
iptables -t raw -P OUTPUT ACCEPT
iptables -t filter -P OUTPUT DROP
保存规则
对于CentOS6:
service iptables save
保存时它会输出:
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
是的,它是保存到/etc/sysconfig/iptables
文件中的。
另一种方式保存方式:iptables-save
命令能把需要保存规则数据输出到控制台,由前面可知,保存iptables规则其实是保存到/etc/sysconfig/iptables
文件中,所以我们只要把iptables-save
输出的内容重定向输入到/etc/sysconfig/iptables
文件中即可:
iptables-save > /etc/sysconfig/iptables
同理,还有另一个命令用于重载配置(即以下操作相当于service iptables reload
):
iptables-restore < /etc/sysconfig/iptables
对于CentOS7:
前面说过CentOS7需要自己安装iptables-services
:
yum install -y iptables-services
安装后,就可以跟CentOS6一样保存了:
service iptables save
但要注意的是,这个save必须用service的方式,不能用systemctl,也就是不能这样:
systemctl save iptables
在CentOS7中start/status/stop/restart/reload都可以换成systemctl的方式,但唯独save不能换成systemctl的方式。
另外,iptables-save
和iptables-restore
也跟CentOS6一样可以使用。
更详细的命令(5链4表)
-d
:destination,用于匹配报文的目标地址,可以同时指定多个ip(逗号隔开,逗号两侧都不允许有空格),也可指定ip段:
iptables -t filter -I OUTPUT -d 192.168.1.111,192.168.1.118 -j DROP
iptables -t filter -I INPUT -d 192.168.1.0/24 -j ACCEPT
iptables -t filter -I INPUT ! -d 192.168.1.0/24 -j ACCEPT
-p
:用于匹配报文的协议类型,可以匹配的协议类型tcp、udp、udplite、icmp、esp、ah、sctp等(centos7中还支持icmpv6、mh):
iptables -t filter -I INPUT -p tcp -s 192.168.1.146 -j ACCEPT
# 感叹号表示“非”,即除了匹配这个条件的都ACCEPT,但匹配这个条件不一定就是REJECT或DROP?这要看是否有为它特别写一条规则,如果没有写就会用默认策略:
iptables -t filter -I INPUT ! -p udp -s 192.168.1.146 -j ACCEPT
上图中,使用”! -s 192.168.1.146″表示对 -s 192.168.1.146这个匹配条件取反, -s 192.168.1.146表示报文源IP地址为192.168.1.146即可满足匹配条件,使用 “!” 取反后则表示,报文源地址IP只要不为192.168.1.146即满足条件,那么,上例中规则表达的意思就是,只要发往本机的报文的源地址不是192.168.1.146,就接受报文。
此刻,你猜猜,按照上例中的配置,如果此时从146主机上向防火墙所在的主机发送ping请求,146主机能得到回应吗?(此处不考虑其他链,只考虑filter表的INPUT链)
为了给你思考的空间,我把答案写的远一点。
答案是:能,也就是说,按照上例的配置,146主机仍然能够ping通当前主机,为什么呢?我们来分析一下。
上例中,filter表的INPUT链中只有一条规则,这条规则要表达的意思就是:
只要报文的源IP不是192.168.1.146,那么就接受此报文,但是,某些小伙伴可能会误会,把上例中的规则理解成如下含义,
只要报文的源IP是192.168.1.146,那么就不接受此报文,这种理解与上述理解看似差别不大,其实完全不一样,这样理解是错误的,上述理解才是正确的。
换句话说就是,报文的源IP不是192.168.1.146时,会被接收,并不能代表,报文的源IP是192.168.1.146时,会被拒绝。
上例中,因为并没有任何一条规则指明源IP是192.168.1.146时,该执行怎样的动作,所以,当来自192.168.1.146的报文经过INPUT链时,并不能匹配上例中的规则,于是,此报文就继续匹配后面的规则,可是,上例中只有一条规则,这条规则后面没有其他可以匹配的规则,于是,此报文就会去匹配当前链的默认动作(默认策略),而上例中,INPUT链的默认动作为ACCEPT,所以,来自146的ping报文就被接收了,如果,把上例中INPUT链的默认策略改为DROP,那么,146的报文将会被丢弃,146上的ping命令将得不到任何回应,但是如果将INPUT链的默认策略设置为DROP,当INPUT链中没有任何规则时,所有外来报文将会被丢弃,包括我们ssh远程连接。
-i
:用于匹配报文是从哪个网卡接口流入本机的,由于匹配条件只是用于匹配报文流入的网卡,所以在OUTPUT链与POSTROUTING链中不能使用此选项:
iptables -t filter -I INPUT -p icmp -i eth0 -j DROP
iptables -t filter -I INPUT -p icmp ! -i eth0 -j DROP
-o
:用于匹配报文将要从哪个网卡接口流出本机,于匹配条件只是用于匹配报文流出的网卡,所以在INPUT链与PREROUTING链中不能使用此选项。
iptables -t filter -I OUTPUT -p icmp -o eth0 -j DROP
iptables -t filter -I OUTPUT -p icmp ! -o eth0 -j DROP
iptables扩展模块
tcp扩展模块
-p tcp -m tcp --sport
用于匹配tcp协议报文的源端口,可以使用冒号指定一个连续的端口范围(-p protocol,
-m:match,指匹配的模块,很多人可能以为是module的缩写,其实是match的缩写,
–sport: source port);
-p tcp -m tcp --dport用于匹配tcp协议报文的目标端口,可以使用冒号指定一个连续的端口范围(
–dport 80:88
#示例如下
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22:25 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport :22 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 80: -j REJECT
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT
此外,tcp扩展模块还有-tcp-flags选项,它可以根据TCP头部的“标识位”来匹配。
multiport扩展模块
-p tcp -m multiport --sports
用于匹配报文的源端口,可以指定离散的多个端口号,端口之间用”逗号”隔开;
-p udp -m multiport --dports
用于匹配报文的目标端口,可以指定离散的多个端口号,端口之间用”逗号”隔开:
#示例如下
iptables -t filter -I OUTPUT -d 192.168.1.146 -p udp -m multiport --sports 137,138 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport ! --dports 22,80 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 80:88 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80:88 -j REJECT
iprange扩展模块
使用iprange扩展模块可以指定”一段连续的IP地址范围”,用于匹配报文的源地址或者目标地址。iprange扩展模块中有两个扩展匹配条件可以使用:
– --src-range
(匹配源地址范围)
– --dst-range
(匹配目标地址范围)
iptables -t filter -I INPUT -m iprange --src-range 192.168.1.127-192.168.1.146 -j DROP
string扩展模块
假设我们访问的是“http://192.168.1.146/index.html”,当“index.html”中包括“XXOO”字符时,就会被以下规则匹配上:
iptables -t filter -I INPUT -m string --algo bm --string "XXOO" -j REJECT
-m string
:表示使用string模块
--algo bm
:表示使用bm算法来匹配index.html中的字符串,“algo”是“algorithm”的缩写,另外还有一种算法叫“kmp”,所以--algo
可以指定两种值,bm或kmp,貌似是bm算法速度比较快。
time扩展模块
我们可以通过time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件。
我想要自我约束,每天早上9点到下午6点不能看网页:
iptables -t filter -I INPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 18:00:00 -j REJECT
iptables -t filter -I INPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 18:00:00 -j REJECT
周六日不能看网页:
iptables -t filter -I INPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT
iptables -t filter -I INPUT -p tcp --dport 443 -m time --weekdays 6,7 -j REJECT
--weekdays
可用1-7表示一周的7天,还能用星期的缩写来指定匹配:Mon、Tue、Wed、Thu、Fri、Sat、Sun。
匹配每月22,23号:
iptables -t filter -I INPUT -p tcp --dport 80 -m time --monthdays 22,23 -j REJECT
多个条件是“相与”的关系,比如以下规则指定匹配每周五,并且这个周五还必须是在22,23,24,25,26,27,28中的一天(其实就相当于设置每月的第四个星期五):
iptables -t filter -I INPUT -p tcp --dport 80 -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
另外还有daystart和daystop:
iptables -t filter -I INPUT -p tcp --dport 80 -m time --daystart 2019-07-20 --daystop 2019-07-25 -j REJECT
--monthdays
和--weekdays
可以用感叹号!
取反,其他的不行。
connlimit模块
使用connlimit扩展模块,可以限制每个IP地址同时链接到server端的链接数量,注意:我们不用指定IP,其默认就是针对”每个客户端IP”,即对单IP的并发连接数限制。
限制22端口(ssh默认端口)连接数量上限不能超过2个;
iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
在CentOS6中可对--connlimit-above
取反:
iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit ! --connlimit-above 2 -j REJECT
表示连接数量只要不超过两个就允许连接,至于超过两个并不一定不允许连接,这得看默认策略是ACCEPT还是DROP或REJECT,又或者有其它规则对它进行限制。
在CentOS7中有一个叫--connlimit-upto
的选项,它的作用跟! --connlimit-above
一样,不过这种用法还是比较少用的。
配合--connlimit-mask
来限制网段:
iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 --connlimit-mask 24 -j REJECT
网址由32位二进制组成,最大可写成:255.255.255.255,而mask就是掩码(网络知识,请自行了解),24表示24个1,即255.255.255.0。
limit扩展模块
limit模块是限速用的,用于限制“单位时间内流入的数据包的数量”。
每6位秒放行一下ping包(因为1分钟是60秒,所以1分钟10个包,就相当于每6秒1个包):
iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
--limit
后面的单位除了minute,还可以是second、hour、day
--limit-burst
: burst是爆发、迸发的意思,在这里是指最多允许一次性有几个包通过。
udp扩展模块
udp扩展模块中能用的匹配条件比较少,只有两个,就是--sport
与--dport
,即匹配报文的源端口与目标端口。
放行samba服务的137和138端口:
iptables -t filter -I INPUT -p udp -m udp --dport 137 -j ACCEPT
iptables -t filter -I INPUT -p udp -m udp --dport 138 -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 138 -j ACCEPT
udp扩展中的--sport
与--dport
与tcp一样,同样支持指定一个连续的端口范围:
iptables -t filter -I INPUT -p udp --dport 137:157 -j ACCEPT
--dport 137:157
表示匹配137-157之间的所有端口。
另外与tcp一样,udp也能使用--multiport
指定多个不连续的端口。
icmp扩展模块
ping是使用icmp协议的,假设要禁止所有icmp协议的报文进入本机(根据前面所说,我们可以省略用-m icmp
来指定使用icmp模块,因为不指定它会默认使用-p
指定的协议对应的模块):
iptables -t filter -I INPUT -p icmp -j REJECT
上述命令能产生两个效果:
– 1、别人ping本机时,无法ping通,因为数据报文无法进入;
– 2、本机ping别人时,虽然数据包可以出去,但别人的响应包也是icmp协议,无法进来(即“有去无回”)。
所以这样设置会导致,不止别人ping不通本机,本机也ping不通别人。
很明显上边的规则不是我们想要的,我们想要的一般都是允许本机ping别人,不允许别人ping本机:
iptables -t filter -I INPUT -p icmp --icmp-type 8/0 -j REJECT
--icmp-type 8/0
用于匹配报文type为8,code为0时才会被匹配到,至于会是type和code,这是icmp协议的知识。
其实上边的命令还可以省略code(即把“8/0”写成“8”即可,省略掉“/0”,原因是type=8的报文中只有code=0一种,所以我们不写默认就是code=0,不会有其它值):
iptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECT
除了能用type/code来匹配icmp报文,还可以使用icmp的描述名称来匹配:
iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT
--icmp-type "echo-request"
的效果与icmp --icmp-type 8/0
或icmp --icmp-type 8
的效果完全一样(你可能发现了,icmp协议的描述“echo-request”其实是“echo request”,只不过我们用于作为匹配条件时,要把空格换成横杠)。
state扩展模块
在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在”你来我往”的通信,就算建立起了连接。
而”连接”中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。
放行RELATED和ESTABLISHED状态的报文:
iptables -t filter -I INPUT -m state --state RELATED, ESTABLISHED -j ACCEPT
三、firewalld
相比于传统的防火墙管理工具,firewalld支持动态更新技术并加入了区域的概念。区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以选择不同的集合,从而实现防火墙策略之间的快速切换。
firewalld中常见的区域名称(默认为public)以及相应的策略规则:
阻塞区域(block) | 工作区域(work) | 家庭区域(home) | 公共区域(public) | 隔离区域(DMZ) | 信任区域(trusted) | 丢弃区域(drop) | 内部区域(internal) | 外部区域(external) | |
---|---|---|---|---|---|---|---|---|---|
拒绝流入的流量,除非与流出的流量相关 | 拒绝流入的流量,除非与流出的流量相关 | 拒绝流入的流量,除非与流出的流量相关 | 不相信网络上的任何计算机,只有选择接受传入的网络连接。 | 隔离区域也称为非军事区域,内外网络之间增加的一层网络,起到缓冲作用。对于隔离区域,只有选择接受传入的网络连接。 | 允许所有的数据包。 | 拒绝流入的流量,除非与流出的流量相关 | 等同于home区域 | 拒绝流入的流量,除非与流出的流量有关;而如果流量与ssh服务相关,则允许流量 |
firewalld默认提供的九个zone配置文件都保存在“/usr/lib/firewalld/zones/”目录下,分别为:block.xml drop.xml home.xml public.xml work.xml dmz.xml external.xml internal.xml trusted.xml
安装firewalld服务的软件:
[root@localhost ~]# yum install firewall -y
firewall-cmd命令的参数说明如下:
参数 | 作用 |
---|---|
–get-default-zone | 查询默认的区域名称 |
–set-default-zone=<区域名称> | 设置默认的区域,使其永久生效 |
–get-zones | 显示可用的区域 |
–get-services | 显示预先定义的服务 |
–get-active-zones | 显示当前正在使用的区域与网卡名称 |
–add-source= | 将源自此IP或子网的流量导向指定的区域 |
–remove-source= | 不再将源自此IP或子网的流量导向某个指定区域 |
–add-interface=<网卡名称> | 将源自该网卡的所有流量都导向某个指定区域 |
–change-interface=<网卡名称> | 将某个网卡与区域进行关联 |
–list-all | 显示当前区域的网卡配置参数、资源、端口以及服务等信息 |
–list-all-zones | 显示所有区域的网卡配置参数、资源、端口以及服务等信息 |
–add-service=<服务名> | 设置默认区域允许该服务的流量 |
–add-port=<端口号/协议> | 设置默认区域允许该端口的流量 |
–remove-service=<服务名> | 设置默认区域不再允许该服务的流量 |
–remove-port=<端口号/协议> | 设置默认区域不再允许该端口的流量 |
–reload | 让“永久生效”的配置规则立即生效,并覆盖当前的配置规则 |
–panic-on | 开启应急状况模式 |
–panic-off | 关闭应急状况模式 |
示例:
[root@localhost ~]# firewall-cmd --version #查看版本
[root@localhost ~]# firewall-cmd --help #查看帮助
[root@localhost ~]# firewall-cmd --state #显示状态
[root@localhost ~]#firewall-cmd --reload #重载查看才有该服务
使用firewalld配置的防火墙策略默认为当前生效,会随着系统的重启而失效。如果想让策略一直存在,就需要使用永久模式了,即在使用firewall-cmd命令设置防火墙策略时添加–permanent参数,这样配置的防火墙策略就可以永久生效了,最后想要使用这种方式设置的策略生效,只能重启或者输入命令:firewall-cmd --reload。
四、实验练习
安装iptables和firewalld服务的包
[root@qingyuxin ~]# yum install iptables-services -y
[root@qingyuxin ~]# yum install firewalld -y
1.iptables: 开启防火墙:可以正常使用ssh服务,dns服务, httpd服务,chrony服务, nfs服务
开启iptables服务
[root@qingyuxin ~]# systemctl restart iptables
写策略
[root@qingyuxin ~]# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
[root@qingyuxin ~]# iptables -I INPUT -p tcp --dport 443 -j ACCEPT
[root@qingyuxin ~]# iptables -I INPUT -p tcp --dport 2049 -j ACCEPT
[root@qingyuxin ~]# iptables -I INPUT -p tcp --dport 53 -j ACCEPT
[root@qingyuxin ~]# iptables -I INPUT -p udp --dport 323 -j ACCEPT
测试
启动httpd服务
httpd服务可以通过防火墙
2.firewalld: 开启防火墙:可以正常使用ssh服务,dns服务, httpd服务, nfs服务
且实现:访问第一台机器web服务的9090端口,转发到第二台机器的80端口(永久生效)
清空第一题配置的策略
iptables -F
开启防火墙并配置策略
[root@qingyuxin ~]# systemctl stop iptables
[root@qingyuxin ~]# systemctl start firewalld
[root@qingyuxin ~]# firewall-cmd --add-service=http --permanent
success
[root@qingyuxin ~]# firewall-cmd --add-service=dns --permanent
success
[root@qingyuxin ~]# firewall-cmd --add-service=ssh --permanent
success
[root@qingyuxin ~]# firewall-cmd --add-service=nfs --permanent
success
访问第一台机器web服务的9090端口,转发到第二台机器的80端口(永久生效)
首先要开启防火墙伪装
firewall-cmd --add-masquerade --permanent
添加转发规则
firewall-cmd --add-forward-port=port=9090:proto=tcp:toport=80:toaddr=192.168.15.128 --permanent
因为没有允许
测试
开启http服务
systemctl start httpd
在浏览器上访问第一台机器
第二台机器
实现端口跳转