Firewall:防火墙,就是一个隔离工具。工作于主机或网络的边缘,对于进出本主机或网络的报文根据事先定义好的检查规则做匹配检测,对于能够被规则所匹配到的报文做出相应处理的组件:这个组件可以是硬件,也可以是软件,或二者组合。
对于防火墙,大体上也分为两类: 主机防火墙、 网络防火墙
现在描述一下在没有防火墙的情况下,报文的流经过程(以一台主机为例):
外来的报文要进入主机,必须经过网卡,网卡必须在网卡驱动下工作,经过网卡后,报文被送到协议栈(一般就是TCP/UDP协议栈),在协议栈中对报文进行分析,网卡驱动和协议栈都是在内核空间的。如果报文的目的地址是本机,那么一般是在用户空间有一个进程在监听一个端口,协议栈将报文发送到该监听端口,最终由用户进程进行接收处理;如果报文的目的地址不是本机,那么协议栈要进行路由查找,找到对用的路由后,从相应的网卡接口发送出去,这就是转发。主机用户空间的进程,主动向外发送报文,报文先送到协议栈,协议栈一样要分析,最终通过查找路由,通过对应网口发送报文。
主机防火墙,主要就是在用户进程,即本机接收、发送报文时的过滤。
网络防火墙,主要就是报文经过路由后的转发,主要目的地址不是本主机。
Linux提供的iptables即能实现主机防火墙,也能实现网络防火墙,因为这个防火墙主要是针对报文的,所以iptables是包过滤型防火墙。
再来看一下加上防火墙的情况,首先要研究一下防火墙的位置,防火墙主要进行报文的过滤,所以要在能识别报文的位置上,所以防火墙是要在协议栈的某个位置上设置,这个位置在哪呢?
对于目的地址是本机的报文,经过协议栈分析后,要过滤是否能送到主机的用户进程监控端口,所以,进入本机的报文的过滤点应放在①位置,即协议栈去到用户进程之间,这叫做INPUT链;而从本机用户进程对外发送去到协议栈的报文,需要过滤是否允许发送,即位置②,叫做OUTPUT链;目的地址不是本机的报文,需要经过路由选择后进行转发,这个位置是③,叫做FORWARD链,用于过滤是否允许转发(这种报文不会进入本主机的用户空间);对于刚进入网卡的报文,有时需要进行nat或pat转换,即网络地址转换或端口地址转换,一般是需要在协议栈分析前完成转换,这个位置即为④,叫做PREROUTING链,即要在路由前进行的动作,这个很好理解,如果路由选择后再转换,路由就乱套了;最后是报文离开协议栈对外发送,也可能需要进行nat/pat,这是位置⑤,叫做POSTROUTING链,即路由后的动作。设置多个位置,就是要实现对不同情形的报文的过滤匹配。
通过上面的描述能够看出来,这些位置都是在内核空间,也就是说,防火墙是内核的内容。
各个位置及名称已经知道了,那么这里为什么名称里还要加一个链字呢?主要是在这几个位置,不是完成单一的过滤功能,而是多种功能的叠加,而且,在配置过滤规则时,可以配置多个过滤规则,这样看,就像是一个功能和规则的链(想象一下珍珠链),报文依次要穿过这个链中的每个珠子(功能或规则),每个功能或过滤规则可能对报文发生作用,也可能被跳过不发生作用。这一点有点像Django中的中间件:MIDDLEWARE=[],在settings.py中设置的,一个中间件是多个功能的列表,请求报文也是一一穿过这些个功能,这个MIDLLEWARE就相当于一个链,防火墙有5个链,相当于有5个MIDDLEWARE。
对于每个链,都需要有相应的过滤规则,而且这个规则不是固定不变的,有可能随需要不断修改,所以,就做成一个配置项,相当于一个配置文件,将一些过滤规则等记录在这个配置中,系统启动时,防火墙没有任何规则,启动后通过读取这些配置,加载规则。为了方便这个配置文件的修改和管理,于是就有了iptables,iptables主要是提供了一个用户空间的进程,方便用户管理规则配置。
所以,Linux的防火墙其实是iptables/netfilter,相当于一个C/S架构,netfilter是一个框架,主要是内核中的部分,定义了五个链及各种功能,这五个链,在程序的实现上就是一些特殊函数,叫做hooks function,钩子函数,意思是说,报文经过时,要被这些钩子函数勾过来,在这个函数中过一遍,这个钩子函数中又能定义很多其他函数,实现不同功能或进行规则匹配,报文经过这些函数或规则的匹配后,按照不同的结果被执行不同的动作,以此来达成对报文的控制。iptables是一个规则的通用工具,负债对规则的修改和管理。
前面一直在说的功能,主要是以下几种:一个是filter,即过滤功能,这是我们感官意义上的防火墙,实现包的匹配过滤;一个是nat功能,即网络地址转换;一个是mangle功能,实现报文的拆包修改封包的作用;一个是raw功能,关闭nat表上启动的连接追踪机制。
上面是主机防火墙的示意图,兼具网络防火墙的功能,即有多个网卡,开启转发功能。
对于网络防火墙,可以实现对网络内部设备的保护,但是如果网络内部主机之间相互攻击,或网络内部主机对服务器的攻击,此时这个防火墙是无能为力的。所以对服务器的保护,一般还要在服务器前增加一道防火墙(也可以使用主机防火墙,但对服务器的业务服务有性能上的损耗)。
对于一些网络攻击行为,通过防火墙的规则匹配有时很难区分其行为是恶意还是善意,或者有些还没有认识的新型网络包,规则无法配置,如何来防范呢?如,提供了一台web服务器,防火墙对访问这台服务器的报文放行,如果访问不是访问正常的页面,而是试图获取其他位置的文件呢?这时需要另一种系统:IDS(Intrusion Detection System),入侵检测系统,它能够检测进程的各种行为,但是它也只是能看到这些行为,要阻止这种报文,需要通知防火墙,即IDS-->Firewall,如果实现了这种联动的功能,就形成另一种系统IPS(Intrusion Prevention System),入侵防御系统。
对于IDS,有HIDS和NIDS,即主机入侵检测系统,和网络入侵检测系统,HIDS只需部署于主机上,而NIDS需要在网络的不同部位部署(类似安装监控头)。
还有一种是类似钓鱼执法的做法,部署一个honeypot(蜜罐),诱惑别人攻击,可现场抓获。
Linux一开始内核中是没有防火墙的,后来借鉴OpenBSD,实现了一个防火墙ipfirewall,随后不断进行改进。其发展历程是:ipfirewall-->ipchains--->iptables-->nftables(正在推广):
Linux 2.0版内核中:包过滤机制为ipfw,管理工具是ipfwadm。
Linux 2.2版内核中:包过滤机制为ipchain,管理工具是ipchains。
Linux 2.4,2.6,3.0+版内核中:包过滤机制为netfilter,管理工具是iptables。
Linux 3.1(3.13+)版内核中:包过滤机制为netfilter,中间采取daemon动态管理防火墙,管理工具是firewalld。
iptables/netfilter架构:
framework:netfilter
hooks function
rule utils:iptables
在一个钩子上,可能实现多种功能,而每种功能,又有多种不同的匹配规则和动作,功能要有执行的先后次序,规则匹配也需要先后次序,这些功能和规则,就构成了一个表,这个表就是iptables,也算是名称的由来,由原来的ipchains到iptables。
功能:
filter:过滤,防火墙;
nat:network address translation,网络地址转换;
mangle:拆解报文,做出修改,封装报文
raw:关闭nat表上启用的连接追踪机制;
链(或叫钩子函数,在iptables的名称空间中内置的,规则需要确定作用在哪一个链上):
PREROUTING
INPUT
FORWARD
OUTPUT
POSTROUTING
流入:PREROUTING --> INPUT
流出:OUTPUT --> POSTROUTING
转发:PREROUTING --> FORWARD --> POSTROUTING
各功能的分别实现位置:
filter:INPUT,FORWARD,OUTPUT
nat:PREROUTING(DNAT),OUTPUT,POSTROUTING(SNAT)
mangle:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
raw:PREROUTING,OUTPUT
路由发生的时刻:
报文进入本机后:判断目标主机;
报文发出之前:判断经由哪个接口送往下一跳;
iptables:四表五链,四张表分别是filter、nat、mangle、raw,五链分别是:PREROUTING、 INPUT、FORWARD、OUTPUT、POSTROUTING
添加规则时的考量点:
1)要实现哪种功能:判断添加在哪张表上;
2)报文流经的路径:判断添加在哪个链上;
链:链上规则的次序,即为检查的次序:因此隐含一定的法则:
1)同类规则(访问同一应用),匹配范围小的放上面;
2)不同类规则(访问不同应用),匹配到报文频率较大的放上面;
3)将那些可由一条规则描述的多个规则合并为一个;
4)设置默认策略;(白名单——默认拒绝、黑名单——默认允许)
功能的优先级次序:raw --> mangle --> nat --> filter
规则:
组成部分:报文的匹配条件,匹配到之后处理动作
匹配条件:根据协议报文特征指定
基本匹配条件:
扩展匹配条件:
处理动作:
内建处理机制
自定义处理机制
注意:报文不会经过自定义链,只能在内置链上通过规则引用后生效;
查看一下五链:因为mangle表上五链都存在
iptables:规则管理工具
添加、修改、删除、显示等;
规则和链有计数器:显示从启用到此刻匹配到的数据包,两个计数器
pkts:由规则或链所匹配到的报文的个数;
bytes:由规则或链匹配到的所有报文大小之和;
iptables命令:
iptables [-t table] SUBCOMMAND CHAIN CRETERIA -j TARGET
-t指定在哪个表上,SUBCOMMAND是子命令,CHAIN是在哪个链上,CRETERIA是规则标准,-j TARGET是匹配后的动作。
iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X [chain]
iptables [-t table] -P chain target
iptables [-t table] -E old-chain-name new-chain-name
rule-specification = [matches...] [target]
match = -m matchname [per-match-options]
target = -j targetname [per-target-options]
-t table:
filter,nat,mangle,raw,省略时为filter
链管理:
-F:flush,清空规则链;省略链,表示清空指定表上的所有的链;
-N:new,创建新的自定义规则链;
-X:drop,删除用户自定义的空的规则链;
-Z:zero,清零,置零规则计数器;
-P:Policy,为指定链设置默认策略;对filter表中的链而言,默认策略通常有ACCEPT,DROP,REJECT;
-E:rEname,重命名自定义链;引用计数不为0的自定义链,无法改名,也无法删除;
规则管理:
-A:append,追加,将新规则追加于指定链的尾部;
-I:insert,将新规则插入至指定链的指定位置;
-D:delete,删除指定链上的指定规则;有两种指定方式:
(1)指定匹配条件;
(2)指定规则编号;
-R:replace,替换指定链上的指定规则;
查看:
-L:list,列出指定链上的所有规则;
-n:numberic,以数字格式显示地址和端口号;
-v:verbose,显示详细信息;还有-vv,-vvv,显示更详细信息
--line-numbers:显示规则编号;
-x:exactly,显示计数器计数结果的精确值;
匹配条件:
基本匹配:
[ ! ] -s,--src,--source IP|Netaddr:检查报文中源IP地址是否符合此处指定的地址范围;
[ ! ] -d,--dst,--destination IP|Netaddr:
-p,--protocol {tcp|udp|icmp}:检查报文中的协议,即ip首部中的protocols所标识的协议;
-i,--in-interface IFACE:数据报文的流入接口;仅能用于PREROUTING,INPUT及FORWARD链上;
-o,--out_interface IFACE:数据报文的流出接口;仅能用于FORWEARD,OUTPUT及POSTROUTING链上。
扩展匹配:-m match_name --spec_options
例如:-m tcp --dport 22
扩展就是使用额外的匹配库文件,如下:
其中,大写的是target,小写的是匹配规则
隐式扩展:对于-p protocol指明的协议进行的扩展,如tcp、udp、icmp等,可省略-m选项
-p tcp :
--dport PORT [-PORT]:目标端口,可以是单个或连续多个端口
--sport PORT [-PORT]:
--tcp-flags LIST1 LIST2:检查LIST1所指明的所有标志位,且这其中,LIST2标识出的所有标志位必须为1,而余下的必须为0,没有LIST1中指明的,不做检查;
SYN,ACK,FIN,RST,PSH,URG
--tcp-flags SYN,ACK,FIN,RST SYN 简写 --syn,tcp三次握手链接的第一次握手
-p udp:
--dport、--sport
-p icmp :
--icmp-type
可用数字表示其类型:0——echo-reply,8——echo-request
type | code | Description | query | error |
---|---|---|---|---|
0 | 0 | Echo Reply——回显应答(Ping应答) | x | |
3 | 0 | Network Unreachable——网络不可达 | x | |
3 | 1 | Host Unreachable——主机不可达 | x | |
3 | 2 | Protocol Unreachable——协议不可达 | x | |
3 | 3 | Port Unreachable——端口不可达 | x | |
3 | 4 | Fragmentation needed but no frag. bit set——需要进行分片但设置不分片比特 | x | |
3 | 5 | Source routing failed——源站选路失败 | x | |
3 | 6 | Destination network unknown——目的网络未知 | x | |
3 | 7 | Destination host unknown——目的主机未知 | x | |
3 | 8 | Source host isolated (obsolete)——源主机被隔离(作废不用) | x | |
3 | 9 | Destination network administratively prohibited——目的网络被强制禁止 | x | |
3 | 10 | Destination host administratively prohibited——目的主机被强制禁止 | x | |
3 | 11 | Network unreachable for TOS——由于服务类型TOS,网络不可达 | x | |
3 | 12 | Host unreachable for TOS——由于服务类型TOS,主机不可达 | x | |
3 | 13 | Communication administratively prohibited by filtering——由于过滤,通信被强制禁止 | x | |
3 | 14 | Host precedence violation——主机越权 | x | |
3 | 15 | Precedence cutoff in effect——优先中止生效 | x | |
4 | 0 | Source quench——源端被关闭(基本流控制) | ||
5 | 0 | Redirect for network——对网络重定向 | ||
5 | 1 | Redirect for host——对主机重定向 | ||
5 | 2 | Redirect for TOS and network——对服务类型和网络重定向 | ||
5 | 3 | Redirect for TOS and host——对服务类型和主机重定向 | ||
8 | 0 | Echo request——回显请求(Ping请求) | x | |
9 | 0 | Router advertisement——路由器通告 | ||
10 | 0 | Route solicitation——路由器请求 | ||
11 | 0 | TTL equals 0 during transit——传输期间生存时间为0 | x | |
11 | 1 | TTL equals 0 during reassembly——在数据报组装期间生存时间为0 | x | |
12 | 0 | IP header bad (catchall error)——坏的IP首部(包括各种差错) | x | |
12 | 1 | Required options missing——缺少必需的选项 | x | |
13 | 0 | Timestamp request (obsolete)——时间戳请求(作废不用) | x | |
14 | Timestamp reply (obsolete)——时间戳应答(作废不用) | x | ||
15 | 0 | Information request (obsolete)——信息请求(作废不用) | x | |
16 | 0 | Information reply (obsolete)——信息应答(作废不用) | x | |
17 | 0 | Address mask request——地址掩码请求 | x | |
18 | 0 | Address mask reply——地址掩码应答 |
显式扩展:使用-m指定
目标:
-j TARGET:jump至指定的TARGET:
ACCEPT:接受;
DROP:丢弃;REJECT:拒绝;RETURN:返回调用链;REDIRECT:端口重定向;
LOG:记录日志;
MARK:做防火墙标记;
DNAT:目标地址转换;
SNAT:源地址转换;
MASQUERADE:地址伪装;
。。。。。。
自定义链:自由定义链上的规则进行匹配检查;
实践测试,基本匹配:
iptables -F
iptables -X
iptables -t filter -A INPUT -d 192.168.147.128 -p tcp -j ACCEPT
# 允许任何tcp报文访问本机
iptables -t filter -A OUTPUT -s 192.168.147.128 -p tcp -j ACCEPT
# 允许本机的tcp报文访问任何其他主机
iptables -p INPUT DROP
iptables -p OUTPUT DROP
iptables -p FORWARD DROP
# 将filter表上的三个链默认规则改为DROP,默认为ACCEPT。
iptables -A INPUT -d 192.168.147.128 -p icmp -j ACCEPT
# 允许icmp报文访问本机,即允许其他主机ping本机
# 此时其他主机ping本机时还是超时,因为在OUTPUT链上还是默认拒绝icmp的
iptables -A OUTPUT -s 192.168.147.128 -p icmp -j ACCEPT
# 允许icmp报文流出本机
iptables -L -n --line-number # 显示规则号
iptables -D INPUT 2 # 删除INIPUT链上的2号规则,默认是filter表
iptables -D OUTPUT 2 # 删除OUTPUT链上的2号规则
-o指定出接口,-i指定入接口,对于INPUT链,只能指定-i,即只能指定入接口,对OUTPUT链,只能指定-o出接口。
扩展匹配:
iptables -I INPUT -d 192.168.147.128 -p tcp --dport 22 -j ACCEPT
# 允许任何主机对本机22端口的访问
iptables -I OUTPUT -s 192.168.147.128 -p tcp --sport 22 -j ACCEPT
# 允许本机的22号端口的报文流出
# 一般对本机的配置规则,都要考虑INPUT和OUTPUT两个链
此时,任何主机访问本机的22端口是允许的,访问其他端口也是允许的,如80端口
将规则2删除
此时,网页无法访问。
设置本机可以ping其他主机,而其他主机不能ping自己:
iptables -A OUTPUT -s 192.168.147.128 -p icmp --icmp-type 8 -j ACCEPT
# 允许本机的icmp报文类型为8的报文流出,即icmp的请求报文允许流出
iptables -A INPUT -d 192.168.147.128 -p icmp --icmp-type 0 -j ACCEPT
# 允许icmp的应答报文流入本机
# 一定要注意,对本机的规则配置要考虑进出两个方向的设置。