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)等。配置防火墙的主要工作就是添加、修改和删除这些规则。

rules

更详细的规则:

rules

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:发送到网卡接口之前。如下图:

流量flow

  1. 到本机某进程的报文:PREROUTING –> INPUT
  2. 由本机转发的报文:PREROUTING –> FORWARD –> POSTROUTING
  3. 由本机的某进程发出报文(通常为响应报文):OUTPUT –> POSTROUTING

路由决策是指判断数据包的目的地是否是本机,如果是则进入 INPUT Chain,否则进入 FORWARD Chain;PREROUTING。

POSTROUTIONG 和 FORWARD 只有作为路由器使用时才会被调用,正常电脑就只会经过 INPUT 和 OUTPUT。

每个 Table 都含有几个预定义 Chain:
chain

对于不同 Table 的同名 Chain,执行的优先级为(从高到低):

  • raw
  • mangle
  • nat
  • filter

其对应的关系如下:

table/chain raw mangle nat filter表
PREROUTING
INPUT × × ×
FORWARD × ×
OUTPUT
POSTROUTIONG × ×
  1. PREROUTING 的规则可以存在于:raw表,mangle表,nat表。
  2. INPUT 的规则可以存在于:mangle表,filter表,(centos7中还有nat表,centos6中没有)。
  3. FORWARD 的规则可以存在于:mangle表,filter表。
  4. OUTPUT 的规则可以存在于:raw表mangle表,nat表,filter表。
  5. POSTROUTING 的规则可以存在于:mangle表,nat表。
  • raw 表中的规则可以被哪些链使用:PREROUTING,OUTPUT
  • mangle 表中的规则可以被哪些链使用:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
  • nat 表中的规则可以被哪些链使用:PREROUTING,OUTPUT,POSTROUTING(centos7中还有INPUT,centos6中没有)
  • filter 表中的规则可以被哪些链使用:INPUT,FORWARD,OUTPUT

将内置的所有 Chain 串起来看就象下图:

执行顺序

其详细图片如下:
Linux网络栈

  • 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 -A INPUT -s 10.8.0.0/16 -d 172.16.55.7 -p tcp --dport 80 -j DROP

查看iptables列表:

1
iptables -nL

链管理

  • -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选项指定扩展匹配的类型,常见的有以下几种:

  1. 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
  2. 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
  3. 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;


iptables 学习总结
https://randzz.cn/4f5d1998aae8/iptables-学习总结/
作者
Ezreal Rao
发布于
2023年12月30日
许可协议