Centos7学习笔记(十七)- iptable防火墙
本文大部分内容摘录自https://www.cnblogs.com/f-ck-need-u/p/7397146.html
1、syn flood攻击查看
在linux系统中,可以用以下命令查看是否遭受syn flood攻击。
netstat -tnlpa | grep tcp | awk '{print $6}' | sort | uniq -c2、防火墙数据流入流出的基础机制
当接收外界发送的数据时,在数据从网卡流入后需要对它做路由决策,根据其目标决定是流入本机数据还是转发给其他主机,如果是流入本机的数据,则数据会从内核空间进入用户空间(被应用程序接收、处理)。当用户空间响应(应用程序生成新的数据包)时,响应数据包是本机产生的新数据,在响应包流出之前,需要做路由决策,根据目标决定从哪个网卡流出。如果不是流入本机的,而是要转发给其他主机的,则必然涉及到另一个流出网卡,此时数据包必须从流入网卡完整地转发给流出网卡,这要求Linux主机能够完成这样的转发。但Linux主机默认未开启ip_forward功能,这使得数据包无法转发而被丢弃。Linux主机和路由器不同,路由器本身就是为了转发数据包,所以路由器内部默认就能在不同网卡间转发数据包,而Linux主机默认则不能转发。
这里用2个图来解析这一过程。

此图是将这一流程,分A-E五个节点
在linux内核的netfilter中(iptables是基于netfilter的),对比上图,又可以将A-E五个节点按不同方式解释。

3、netfiler模块
在centos7中,ipv4和ipv6的netfilter模块都是放在/lib/modules/3.10.0-1127.el7.x86_64/kernel/net/netfilter/目录中的。
4、netfilter结构
要使netfilter能够工作,就需要将所有的规则读入内存中。netfilter自己维护一个内存块,在此内存块中有4个表:filter表、NAT表、mangle表和raw表。在每个表中有相应的链,链中存放的是一条条的规则,规则就是过滤防火的语句或者其他功能的语句。也就是说表是链的容器,链是规则的容器。实际上,每个链都只是一个hook函数(钩子函数)而已。
说到这里,需要纠正一个概念,Linux上的防火墙是由netfilter实现的,但是netfilter的功能不仅仅只有"防火",一般可以认为"防火"的功能只是filter表的功能。
关于这4个表,它们的结构如下:

注:从内核2.6.34开始,NAT表支持操作INPUT链。它只为SNAT服务。和snat on postrouting类似,只不过snat on input用来转换"目标是本机的数据包"的源地址。
◇ filter表:netfilter中最重要的表,负责过滤数据包,也就是防火墙实现"防火"的功能。filter表中只有OUTPUT/FORWARD/INPUT链。
◇ NAT表:实现网络地址转换的表。可以转换源地址、源端口、目标地址、目标端口。NAT表中的链是PREROUTING/POSTROUTING/OUTPUT。
◇ mangle表:一种特殊的表,通过mangle表可以实现数据包的拆分和还原。mangle表中包含所有的链。
◇ raw表:加速数据包穿过防火墙的表,也就是增强防火墙性能的表。只有PREROUTING/OUTPUT表。
由于这几个表中有重复的链,所以数据被不同链中规则处理时是由顺序的。下图是完整的数据包处理流程。

5、input、output和forward链
每个链对应的都是同名称的数据包,如INPUT链针对的是INPUT数据包。
INPUT链的作用是为了保护本机。例如,如果进入的数据包的目标是本机的80端口,且发来数据包的地址为192.168.100.9时则丢弃,这样的规则应该写入本机的INPUT链。但是要注意,这个本机指的是防火墙所在的机器,如果是硬件防火墙,那么一定会配合FORWARD链。
OUTPUT链的作用是为了管制本机。例如,限制浏览www.taobao.com网页。
INPUT和OUTPUT链很容易理解,FORWARD链起的是什么作用呢?数据包从一端流入,但是不经过本机,那么就要从另一端流出。对于硬件防火墙这很容易理解,如下图,数据总要转发到另一个网卡接口然后进入防火墙负责为其"防火"的网段。也就是说,FORWARD链的作用是保护"后端"的机器。
前文说过,Linux主机自身也有ip_forward功能用于网卡间的数据包转发,这个ip_forward和netfilter的forward链有什么区别呢?这就是防火墙的意义,当数据包需要转发时,仅使用ip_forward时将不问是非对错总是进行转发,而使用forward链时可以筛选这些需要转发的数据包,以决定是否要被转发。显然,ip_forward的功能是转发数据包,而forward链是筛选允许转发的数据包,然后让ip_forward转发。这也说明forward链要正常工作,要求开启ip_forward功能。
DMZ称为"非军事区",一般是放在两个防火墙中间做内网和外网的缓冲。有些必须对外提供服务的服务器应该放在这种区域,而不能直接放在内网,因为将其放入内网又对外提供服务,当它被外界攻击时就可以借助它(肉机)作为跳板攻陷其它内网主机。
一般构建DMZ区有以下几个要求:
内网可以访问外网。显然,内网用户需要自由地访问外网。
内网仅部分主机可以访问DMZ,此策略是为了方便内网用户使用和管理DMZ中的服务器。不应该全部放行内网访问DMZ,否则有内贼的风险。
外网不能访问内网。内网中存放的是公司内部数据,这些数据不允许外网的用户进行访问。
外网可以访问DMZ。DMZ中的服务器本身就是要给外界提供服务的。
DMZ不能访问内网。如果违背此策略,则当入侵者攻陷DMZ时,就可以进一步进攻到内网的重要数据
6、filter表
只考虑filter表的时候,防火墙处理数据包的过程如下图。

当数据包流入时,首先经过路由判决该数据包是流入防火墙本机还是转发到其他机器的。对于流入本机的数据包经过INPUT链,INPUT链所在位置是一个钩子函数,数据经过时将被钩子函数检查一番,检查后如果发现是被明确拒绝或需要丢弃的则直接丢弃,明确通过的则放行,不符合匹配规则的同样丢弃。但是钩子函数毕竟是半路劫财的角色,所以不管怎么样都要告诉一声netfilter,说这个数据包是怎样怎样的,即使是拒绝或丢弃了数据包也还是会给出一个通知。
当用户空间产生的数据包要发送出去时,首先经过OUTPUT链并被此处的钩子函数检查一番,检查通过则放行,然后经过路由决策判决从哪个接口出去,并最终从网卡流出。
例如,当外界主机请求WEB服务的时候,请求数据包流入到本机,路经INPUT链被放行。进入到本机用户空间的进程后,本机进程根据请求给出响应报文,该响应报文的源地址是本机,目标地址是外界主机。当响应报文要出去时必须先流经OUTPUT,然后经过路由决定从哪个接口出去,最终流出并路由到外界主机。
再例如ping本机地址(如127.0.0.1)的时候,ping请求从用户空间发送后,数据包从用户空间流出,于是经过路由决策发现是某网卡的地址,然后流经到OUTPUT,并从此网卡流出。但是由于ping的目标为本机地址,所以数据包仍从流出的网卡流入,并被INPUT链检查,最后返回ping的结果信息。
7、iptables命令
Usage: iptables [-t TABLE] COMMAND CHAIN [ expressions -j target ]
(汉语释义部分:
TABLE当然是指filter、raw、mangle、NAT四种表了,如上面的解释,一个表中,所拥有的链是特定的,常规的防火墙设定都是针对filter表
COMMAND部分是不可缺少的部分
expression指扩展匹配,比如用-p匹配协议,-m匹配一些特定内容
在expression后,用-j来指定整个链最终的处理结果)
iptable命令由几部分组成,当然,也可以只有COMMAND的部分。
首先来看COMMAND部分。
7.1 COMMAND与Options
COMMAND部分一般也是和Options部分结合使用。除了像-F -Z -X这种COMMAND命令可以独立使用。以下是大部分常规COMMAND和Opitons的具体解释:
COMMAND: Either long or short options are allowed. --append -A chain 链尾部追加一条规则 --delete -D chain 从链中删除能匹配到的规则 --delete -D chain rulenum 从链中删除第几条链,从1开始计算 --insert -I chain [rulenum] 向链中插入一条规则使其成为第rulenum条规则,从1开始计算 --replace -R chain rulenum 替换链中的地rulenum条规则,从1开始计算 --list -L [chain [rulenum]] 列出某条链或所有链中的规则 --list-rules -S [chain [rulenum]] 打印出链中或所有链中的规则 --flush -F [chain] 删除指定链或所有链中的所有规则 --zero -Z [chain [rulenum]] 置零指定链或所有链的规则计数器 --new -N chain 创建一条用户自定义的链 --delete-chain -X [chain] 删除用户自定义的链 --policy -P chain target 设置指定链的默认策略(policy)为指定的target --rename-chain -E old new 重命名链名称,从old到new Options: [!] --proto -p proto 指定要检查哪个协议的数据包:可以是协议代码也可以是协议名称, 如tcp,udp,icmp等。协议名和代码对应关系存放在/etc/protocols中 省略该选项时默认检查所有协议的数据包,等价于all和协议代码0 [!] --source -s address[/mask][...] 指定检查数据包的源地址,或者使用"--src" [!] --destination -d address[/mask][...] 指定检查数据包的目标地址,或者使用"--dst" [!] --in-interface -i input name[+] 指定数据包流入接口,若接口名后加"+",表示匹配该接口开头的所有接口 [!] --out-interface -o output name[+] 指定数据包流出接口,若接口名后加"+",表示匹配该接口开头的所有接口 --jump -j target 为规则指定要做的target动作,例如数据包匹配上规则时将要如何处理 --goto -g chain 直接跳转到自定义链上 --match -m match 指定扩展模块 --numeric -n 输出数值格式的ip地址和端口号。默认会尝试反解为主机名和端口号对应的服务名 --table -t table 指定要操作的table,默认table为filter --verbose -v 输出更详细的信息 --line-numbers 当list规则时,同时输出行号 --exact -x 默认统计流量时是以1000为单位的,使用此选项则使用1024为单位
iptables支持extension匹配。支持两种扩展匹配:使用"-p"时的隐式扩展和使用"-m"时的显式扩展。根据指定的扩展,随后可使用不同的选项。在指定扩展项的后面可使用"-h"来获取该扩展项的语法帮助。
"-p"选项指定的是隐式扩展,用于指定协议类型,每种协议类型都有一些子选项。常见协议和子选项如下说明:
-p tcp 子选项
子选项:
[!] --source-port,--sport port[:port]
指定源端口号或源端口范围。指定端口范围时格式为"range_start:range_end",最大范围为0:65535。
[!] --destination-port,--dport port[:port]
指定目标端口号或目标端口号范围。
[!] --tcp-flags mask comp
匹配已指定的tcp flags。mask指定的是需要检查的flag列表,comp指定的是必须设置的flag。
有效的flag值为:SYN ACK FIN RST URG PSH ALL NONE。
如果以0和1来表示,意味着mask中comp指定的flag必须为1其余的必须为0。
例如:iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST SYN
表示只匹配设置了SYN=1而ACK、FIN和RST都为0数据包,也即只匹配TCP三次握手的第一次握手。
[!] --syn
是"--tcp-flags SYN,ACK,FIN,RST SYN"的简写格式。
-p udp 子选项
子选项:
[!] --source-port,--sport port[:port]
指定源端口号或源端口范围。指定端口范围时格式为"range_start:range_end",最大范围为0:65535。
[!] --destination-port,--dport port[:port]
指定目标端口号或目标端口号范围。
-p icmp 子选项
子选项:
[!] --icmp-type {type[/code]|typename}
用于指定ICMP类型,可以是ICMP类型的数值代码或类型名称。有效的ICMP类型
可由iptables -p icmp -h获取。常用的是"echo-request"和"echo-reply",分别
表示ping和pong,数值代号分别是8和0
ping时先请求后响应:ping别人先出去8后进来0;别人ping自己,先进来8后出去0"-m"选项指定的是显式扩展。其实隐式扩展也是要指定扩展名的,只不过默认已经知道所使用的扩展,于是可以省略。例如:-p tcp --dport = -p tcp -m tcp --dport。
常用的扩展和它们常用的选项如下:
(1).iprange:匹配给定的IP地址范围。
[!] --src-range from[-to]:匹配给定的源地址范围 [!] --dst-range from[-to]:匹配给定的目标地址范围
(2).multiport:离散的多端口匹配模块,如将21、22、80三个端口的规则合并成一条。
最多支持写15个端口,其中"555:999"算2个端口。只有指定了-p tcp或-p udp时该选项才生效。
[!] --source-ports,--sports port[,port|,port:port]... [!] --destination-ports,--dports port[,port|,port:port]... [!] --ports port[,port|,port:port]... :不区分源和目标,只要是端口就行
(3).state:状态扩展。结合ip_conntrack追踪会话的状态。
[!] --state state
其中state有如下4种:
INVALID:非法连接(如syn=1 fin=1)
ESTABLISHED:数据包处于已建立的连接中,它和连接的两端都相关联
NEW:新建连接请求的数据包,且该数据包没有和任何已有连接相关联
RELATED:表示数据包正在新建连接, 但它和已有连接是相关联的(如被动模式的ftp的命令连接和数据连接)
例如:-m state --state NEW,ESTABLISHED -j ACCEPT
关于这4个状态,在下文还有更详细的描述。
(4).string:匹配报文中的字符串。
-algo {kmp|bm}:两种算法,随便指定一种
--string "string_pattern"如:
iptables -A OUTPUT -m string --algo bm --sting "taobao.com" -j DROP
(5).mac:匹配MAC地址,格式必须为XX:XX:XX:XX:XX:XX。
[!] --mac-source address
(6).limit:使用令牌桶(token bucket)来限制过滤连接请求数。
--limit RATE[/second/minute/hour/day]:允许的平均数量。如每分钟允许10次ping,即6秒一次ping。默认为3/hour。 --limit-burst:允许第一次涌进的并发数量。第一次涌进超出后就按RATE指定数来给出响应。默认值为5。
例如:允许每分钟6次ping,但第一次可以ping 10次。10次之后按照RATE计算。所以,前10个ping包每秒能正常返回,从第11个ping包开始,每10秒允许一次ping:iptables -A INPUT -d ServerIP -p icmp --icmp-type 8 -m limit --limit 6/minute --limit-burst 10 -j ACCEPT
(7).connlimit:限制每个客户端的连接上限。
--connlimit-above n:连接数量高于上限n个时就执行TARGET
如最多只允许某ssh客户端建立3个ssh连接,超出就拒绝。两种写法:
iptables -A INPUT -d ServerIP -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP iptables -A INPUT -d ServerIP -p tcp --dport 22 -m connlimit ! --connlimit-above 3 -j ACCEPT
这个模块虽然限制能力不错,但要根据环境计算出网页正常访问时需要建立的连接数,另外还要考虑使用NAT转换地址时连接数会翻倍的问题。
最后剩下"-j"指定的target还未说明,target表示对匹配到的数据包要做什么处理,比如丢弃DROP、拒绝REJECT、接受ACCEPT等,除这3个target外,还支持很多种target。以下是其中几种:
DNAT:目标地址转换 SNAT:源地址转换 REDIRECT:端口重定向 MASQUERADE:地址伪装(其实也是源地址转换) RETURN:用于自定义链,自定义链中匹配完毕后返回到自定义的前一个链中继续向下匹配

