3

iptables 实用教程

 2 years ago
source link: https://lotabout.me/2022/Horrible-Iptables-tutorials/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

最近在搞科学上网,抄了一些 iptables 的规则不管用,干脆好好学习一番,写一写我的理解。

Iptables 是一门配置语言

它是一门配置语言。用来在网络处理的各个环节里加 Hook。常见的用途是做防火墙,做流量的转发等等。

像学习其它语言一样,语言本身有语法,语法之外还需要学习库函数。iptables 的语法大概如下:

iptables [-t table] {-I | -A | -D | -R} chain rule_specification

iptables 里有 tablechain 的概念,代表机器处理网络包的各个阶段,因此在指定配置时需要先指定配置在哪个阶段生效。之后是配置处理的规则,规则语法如下:

rule-specification = [matches...] [target]

match = -m matchname [per-match-options]

target = -j targetname [per-target-options]

一个规则可以有多个 match 匹配条件,以及一个 target 作为目标。它表明当一个网络包命中这些规则时,执行 target 目标。另外,iptables 是可(由其它模块)扩展的,扩展会提供新的 match 和新的 target。我们先看一个典型示例:

iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 7892

这个规则的作用是将所有的 tcp 流量,全部转发到 7892 端口。这里的 -p tcp 条件选中 tcp 流量是 iptables 默认支持的,但 REDIRECT 转发操作是扩展提供的。

Table and Chain

要学习语言,要先了解语言背后的执行模型(类比栈、指针等),iptables 的作用是在各个环节里增加 hook,那有哪些 hook 可以用呢?先看下图[1]

--->PRE------>[ROUTE]--->FWD---------->POST------>
| ^
| |
| [ROUTE]
v |
IN OUT
| ^
v |

一个包从左侧进入系统,先到 PRE 环节。接着进入 [ROUTE] 阶段做路由,来决定包的去向。如果本机是目标地址则接收,否则尝试转发,亦或者丢弃。

对于本机接收的包,触发 IN 环节后交给对应的应用程序;转发的包在触发 FWD环节后尝试向外发包。外出的包最后还会经过 POST 环节,做最后的处理后发往网卡。

本机应用程序发出的包,会先经过 OUT 环节处理,之后经过 [ROUTE] 决定去向 [2],最终再经过 POST 环节后发出。

在这些 hook 的基础上,iptables 用 “table” 的概念来组织常见的包修改需求。例如:

  • Filter: 来做包过度
  • Nat: 做地址转换
  • Mangle: 其它的通用的包修改
  • Raw: 处理一些 connection track 生效之前的修改
# modified from https://www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO.txt

--->PRE------>[ROUTE]--->FWD---------->POST------>
Raw | Mangle ^ Mangle
ConnTrack | Filter | NAT (Src)
Mangle | |
NAT (Dst) | [ROUTE]
v |
IN Mangle OUT Filter
| NAT ^ NAT (Dst)
| Filter | Mangle
| | ConnTrack
v | Raw

具体使用时,先决定要做的修改是什么内容,决定 table 名,然后找到 hook 的时机,决定 chain 的名字。当然 iptables 允许用户增加自己的 chain,但用户增加的 chain 并不能决定 hook 的时机。

例如下面的例子里,我们要把所有流量转发到 7892 端口,我们通过 man iptables-extensions 查到,它只能加到 nat 表的 PREROUTINGOUTPUT 链,由于我们要转发入口流量,所以修改的是 PREROUTING chain。

iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 7892

REDIRECT 的限制也很容易理解,转发需要支持源、目标地址的改写,因此属于 nat 表的范畴,而它需要在路由之前做修改(否则改了也发不出去),所以只能在 PREROUTINGOUTPUT hook 里处理。

Rule 执行顺序

上面我们提到 iptables 是通过 table, chain 来组织切入点的,一个 chain 上可以配置多条规则,用户还可以自己创建 chain 来管理规则。那么 iptables 在是如何使用这些规则的呢?

正常情况下规则会一条条向下匹配,iptables 有一些特殊的 target 也提供了一些特殊的操作来在规则中跳转的能力(可以类比编程语言中的 continue, break),如下图:

iptables-order.svg
  • JUMP(-j <chain>):跳转到自定义的 chain 里
  • ACCEPT:流量通过当前 table + chain,不再匹配任何规则
  • RETURN:从当前 chain 跳出,回到上一个 chain 跳转的位置
  • DROP:丢弃流量,不再匹配任何 table 任何 chain

此外也得注意一些扩展 target 的语义,如 REDIRECT 相当于 ACCEPT;如 REJECT 相当于 DROP,会在发送终止包后丢弃数据包。实操如果发现有问题,要注意是不是规则顺序引起的。

常用的扩展

上面我们了解了 iptables 的语法和执行顺序,接下来要学习“库函数”,表面上学习库函数就是学习“扩展”提供了哪些 match 和 target,但真正的难点是学习它们背后的网络处理机制。这里我们简单提几个。

fwmark

Firewall Mark(fwmark) 可以理解成一个 iptables 的扩展,它提供了 MARKCONNMARK 的 target,允许我们把一个数据包或一个连接打上标记。之后在其它地方可以使用这个标记。

典型的使用方式是让有某个标记的流量走某个特殊的路由表[3],例如:

ip rule add fwmark 1 table 100
ip route add local default dev lo table 100

iptables -t mangle -A OUTPUT -p udp -d 198.18.0.0/16 -j MARK --set-mark 1

其中的 ip rule add fwmark 1 table 100 是创建了一张名为 100 的路由表,并指定当 fwmark 为 1 时才查这张表。而下面的规则指定了 -p udp 匹配 UDP 流量,且目标地址为 -d 198.18.0.0/16 时执行 -j MARK 操作,把数据包打上 --set-mark 1 这个标记。

成果是目标地址为 198.18.0.0/16 的 UDP 流量会查 100 路由表。

NAT: SNAT, DNAT, MASQUERADE

Network Address Translation 的变种比较多,但思路还是容易理解的。在网络隔离的情况下,如果想两个网段里交换网络包,则需要在路由器(能同时访问两个网段)里对包做地址转换,如下所示:

iptables-NAT.svg

SNAT 是换了源 IP 字段,所以一般用于出口流量;DNAT 换了目标 IP 字段,所以一般用于做“端口映射”来穿透内网。可以看到不论是 SNAT 还是 DNAT 都需要提供目标的 IP 地址。而 MASQUERADE 可以理解成 SNAT 的变种,它可以自动填写对应网卡的 IP,不需要手工指定了,一般用于路由器流量内外网转发。

另外从图里看到,无论是 SNAT 还是 DNAT,都需要维护一张 NAT 映射表,可以通过 conntrack -L 看到。如果在路由器的 SNAT 里,--to-source IP 不是本机会怎么样呢?连接会建立失败,路由还是正常记录了 NAT 映射表,但 ACK 包会直接发到 --to-source IP 上,被丢弃。

额外的,TCP 流量只有在连接建立时会查 iptables NAT 表,同个连接后续的包会沿用建立连接时的规则。



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK