iptables 学习总结
前言
好久没更新blog了,一是因为非常忙,一直忙着写代码,二是忙着搞k8s的一些问题。先说一下最近碰到的问题,我们k8s集群内的pod要和集群外可以通过ip直接互相访问(我们用的cni插件是kube-router),于是就要解决两个问题:
- ingress 入向:入向流量的话,如果想让集群外的服务直接通过ip访问到pod,目前我们想到的方式是直接指路由,比如 10.0.1.0/24 网段的pod在node001上,那么我们就给路由表上写一个 10.0.1.0/24 —> node001。
- egress 出向:出向基本不用管,只要不特别设置,都不会有问题。
但是!!!出向的时候,由于iptables的作用,pod出向ip会被做snat。我们拿不到具体pod的ip,只能拿到的是宿主机的Ip,也就是node ip,虽然我们可以通过conntrack -L
命令拿到所有转换关系,但是这也太傻了。所以我就来研究了一下iptables,毕竟不是专业的运维(我只是个开发。。),很多东西都不太懂,学习之后记录一下!
防火墙分类
从逻辑上讲。防火墙可以大体分为主机防火墙和网络防火墙。
- 主机防火墙:针对于单个主机进行防护。
- 网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网。
网络防火墙和主机防火墙并不冲突,可以理解为,网络防火墙主外(集体), 主机防火墙主内(个人)。
从物理上讲,防火墙可以分为硬件防火墙和软件防火墙。
- 硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高。
- 软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能低,成本低。
netfilter
iptables其实不是真正的防火墙,我们可以把它理解成一个客户端代理,用户通过iptables这个代理,将用户的安全设定执行到对应的”安全框架”中,这个”安全框架”才是真正的防火墙,这个框架的名字叫netfilter。
之所以网上一些大段 iptables 操作脚本看起来复杂迷惑,就是 iptables 设计得非常灵活,不仅仅可以当防火墙,还可以进行端口转发,ip 分组过滤等等复杂的功能,甚至可以把它当成微型的编程语言,所以我们要先俯瞰 iptables 整体的操作逻辑,之后再陷入细节时才不会慌张。
netfilter才是防火墙真正的安全框架(framework),netfilter位于内核空间。iptables其实是一个命令行工具,位于用户空间,我们用这个工具操作真正的框架。netfilter/iptables(下文中简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。
Netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有如下功能:
- 网络地址转换(Network Address Translate)
- 数据包内容修改
- 数据包过滤
所以说,虽然我们使用service iptables start启动iptables”服务”,但是其实准确的来说,iptables并没有一个守护进程,所以并不能算是真正意义上的服务,而应该算是内核提供的功能。
我们知道iptables是按照规则来办事的,我们就来说说规则(rules),规则其实就是网络管理员预定义的条件,规则一般的定义为”如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。
更详细的规则:
iptables
table chain rule
最简单的说法就是 Table 由很多个 Chain 组成,而 Chain 由一些 Rule 串起来组成, 所以称之为”链“。
Rule 就是对于请求一个断言,如果请求满足断言就执行指定的操作(官方文档中称这个操作为目标,Target),举个例子,”如果请求来自 192.168.19.123,就将其拒绝“,这就是一个 Rule,而”拒绝“就是一个目标,常见的目标有接受,拒绝,转发,调用另一个 Chain 等等。
请求会在 Chain 中自上而下遍历,直到遇到一个匹配的 Rule,然后调用它的目标。
四表五链
iptables 中 Table 的数目是规定死的四个:
- filter:过滤功能
- nat:端口映射,地址映射等
- mangle:用于对特定数据包的修改
- raw:优先级最高的 Table
还有五个预定义的 Chain:
- PREROUTING:数据包进入路由表之前
- INPUT:通过路由表后目的地为本机
- FORWARD:通过路由表后,目的地不为本机
- OUTPUT:由本机产生,向外转发
- POSTROUTIONG:发送到网卡接口之前。如下图:
- 到本机某进程的报文:PREROUTING –> INPUT
- 由本机转发的报文:PREROUTING –> FORWARD –> POSTROUTING
- 由本机的某进程发出报文(通常为响应报文):OUTPUT –> POSTROUTING
路由决策是指判断数据包的目的地是否是本机,如果是则进入 INPUT Chain,否则进入 FORWARD Chain;PREROUTING。
POSTROUTIONG 和 FORWARD 只有作为路由器使用时才会被调用,正常电脑就只会经过 INPUT 和 OUTPUT。
每个 Table 都含有几个预定义 Chain:
对于不同 Table 的同名 Chain,执行的优先级为(从高到低):
- raw
- mangle
- nat
- filter
其对应的关系如下:
table/chain | raw | mangle | nat | filter表 |
---|---|---|---|---|
PREROUTING | √ | √ | √ | √ |
INPUT | × | √ | × | × |
FORWARD | × | √ | × | √ |
OUTPUT | √ | √ | √ | √ |
POSTROUTIONG | × | √ | √ | × |
- PREROUTING 的规则可以存在于:raw表,mangle表,nat表。
- INPUT 的规则可以存在于:mangle表,filter表,(centos7中还有nat表,centos6中没有)。
- FORWARD 的规则可以存在于:mangle表,filter表。
- OUTPUT 的规则可以存在于:raw表mangle表,nat表,filter表。
- POSTROUTING 的规则可以存在于:mangle表,nat表。
- raw 表中的规则可以被哪些链使用:PREROUTING,OUTPUT
- mangle 表中的规则可以被哪些链使用:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
- nat 表中的规则可以被哪些链使用:PREROUTING,OUTPUT,POSTROUTING(centos7中还有INPUT,centos6中没有)
- filter 表中的规则可以被哪些链使用:INPUT,FORWARD,OUTPUT
将内置的所有 Chain 串起来看就象下图:
其详细图片如下:
- ACCEPT:允许数据包通过。
- DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应。
- REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。
- SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
- MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
- DNAT:目标地址转换。
- REDIRECT:在本机做端口映射。
- LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。
语法规则
iptables [-t table] COMMAND [chain] CRETIRIA -j ACTION
- -t table,是指操作的表,filter、nat、mangle或raw, 默认使用filter
- COMMAND,子命令,定义对规则的管理
- chain, 指明链路
- CRETIRIA, 匹配的条件或标准
- ACTION,操作动作,见上边的代码段中的内容
例如,不允许10.8.0.0/16网络对80/tcp端口进行访问:
1 |
|
查看iptables列表:
1 |
|
链管理
- -N, –new-chain chain:新建一个自定义的规则链;
- -X, –delete-chain [chain]:删除用户自定义的引用计数为0的空链;
- -F, –flush [chain]:清空指定的规则链上的规则;
- -E, –rename-chain old-chain new-chain:重命名链;
- -Z, –zero [chain [rulenum]]:置零计数器;
- -P, –policy chain target, 设置链路的默认策略
规则管理
- -A, –append chain rule-specification:追加新规则于指定链的尾部;
- -I, –insert chain [rulenum] rule-specification:插入新规则于指定链的指定位置,默认为首部;
- -R, –replace chain rulenum rule-specification:替换指定的规则为新的规则;
- -D, –delete chain rulenum:根据规则编号删
查看规则
- -L, –list [chain]:列出规则;
- -v, –verbose:详细信息;
- -vv, -vvv 更加详细的信息
- -n, –numeric:数字格式显示主机地址和端口号;
- -x, –exact:显示计数器的精确值;
- –line-numbers:列出规则时,显示其在链上的相应的编号;
- -S, –list-rules [chain]:显示指定链的所有规则;
查看规则的一般内容:
匹配条件
匹配条件包括通用匹配条件和扩展匹配条件。
- 通用匹配条件是指针对源地址、目标地址的匹配,包括单一源IP、单一源端口、单一目标IP、单一目标端口、数据包流经的网卡以及协议。
- 扩展匹配条件指通用匹配之外的匹配条件。
通用匹配条件
[!] -s, --source address[/mask][,...]
:检查报文的源IP地址是否符合此处指定的范围,或是否等于此处给定的地址;[!] -d, --destination address[/mask][,...]
:检查报文的目标IP地址是否符合此处指定的范围,或是否等于此处给定的地址;[!] -p, --protocol protocol
:匹配报文中的协议,可用值tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh 或者 “all”, 亦可以数字格式指明协议;[!] -i, --in-interface name
:限定报文仅能够从指定的接口流入;only for packets entering the INPUT, FORWARD and PREROUTING chains.[!] -o, --out-interface name
:限定报文仅能够从指定的接口流出;for packets entering the FORWARD, OUTPUT and POSTROUTING chains.
扩展匹配条件
隐含扩展匹配条件
-p tcp
:可直接使用tcp扩展模块的专用选项;
[!] --source-port,--sport port[:port]
匹配报文源端口;可以给出多个端口,但只能是连续的端口范围 ;
[!] --destination-port,--dport port[:port]
匹配报文目标端口;可以给出多个端口,但只能是连续的端口范围 ;
[!] --tcp-flags mask comp
匹配报文中的tcp协议的标志位;Flags are: SYN ACK FIN RST URG PSH ALL NONE;
mask
:要检查的FLAGS list,以逗号分隔;
comp
:在mask给定的诸多的FLAGS中,其值必须为1的FLAGS列表,余下的其值必须为0;
[!] --syn: --tcp-flags SYN,ACK,FIN,RST SYN
-p udp
:可直接使用udp协议扩展模块的专用选项:
[!] --source-port,--sport port[:port]
[!] --destination-port,--dport port[:port]
-p icmp
[!] --icmp-type {type[/code]|typename}
0/0:echo reply
8/0:echo request
显式扩展匹配条件
必须用-m option选项指定扩展匹配的类型,常见的有以下几种:
multiport
以离散或连续的 方式定义多端口匹配条件,最多15个;
[!] --source-ports,--sports port[,port|,port:port]...
:指定多个源端口;
[!] --destination-ports,--dports port[,port|,port:port]...
:指定多个目标端口;1
iptables -I INPUT -d 172.16.0.7 -p tcp -m multiport --dports 22,80,139,445,3306 -j ACCEPT
iprange
以连续地址块的方式来指明多IP地址匹配条件;[!] --src-range from[-to]
[!] --dst-range from[-to]
1
# iptables -I INPUT -d 172.16.0.7 -p tcp -m multiport --dports 22,80,139,445,3306 -m iprange --src-range 172.16.0.61-172.16.0.70 -j REJECT
time
匹配数据包到达的时间
--timestart hh:mm[:ss]
--timestop hh:mm[:ss]
[!] --weekdays day[,day...]
[!] --monthdays day[,day...]
--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
--kerneltz:使用内核配置的时区而非默认的UTC;