# 5. 如何用iptables改包头

### introduction

`iptables` 这个东西在容器生态中使用的非常广, 比如举个例子, 容器端口的映射, K8s-service的实现中, 多多少少都参与了一些. 这一节不会说的特别深, 主要是想让你意识到世界上有这样一种工具存在

## xxx\_filter

iptable的底层实现是`netfilter`, 这个工具作用于协议栈(补充一些协议栈相关的知识, 协议栈控制"网络流程", 也就是收包, 发包, 转发控制等等操作), 这个工具负责往各个节点上挂钩子, 比如作用于转发流程的钩子等等.一共有5个位置可以挂钩子:

* pre/post-routing
* in/out-put
* forward

### 协议栈之旅(钩子之旅)

现在我们把思路拓宽一些, 这些钩子能帮你做到: 包过滤, 地址伪装, 地址转换, 代理, 现在假设有一个包被送到了协议栈, 那么接下来会发生什么呢? 我们会:

* 先经过prerouting链, 如果确实有用户在这里挂了函数, 那么内核将对这个包做目的地址转换(DNAT), 做完以后根据目的地址, 内核检查本地路由表, 来确定这个包是发给本机上的某个进程, 还是转发给其他机器
  * **如果转发给其他机器**
    * 那么前往forward链(此时这台机器相当于一个路由器), 并遍历forward链上的所有函数
    * 目前我们还在协议栈里, 因为我们即将把这个包转发给别的机器, 因此马上就要出协议栈了, 所有出协议栈的包都会经过postrouting链, 在这个场景下, 几种可能的玩法是做源地址转换(SNAT)或地址伪装(Masq)
  * **如果不转发, 就是本机上的某个进程**
    * 那么此时会经过input链, 并到达这个进程手上, 本地的响应报文会先经过output链, 一次路由决策后(想想上一节里协议栈是怎么把包发给`tun0`的), 最终经由postrouting链离开协议栈

### iptable

现在我们已经知道了链与钩子这种东西了, ipfilter这种工具就是帮你往钩子上挂函数的, 想想netfilter的特点, 一个最大的可能似乎是拿来搭防火墙用的(非法包过滤掉), 但再想想拿来做负载均衡似乎也是有可能的.

五条链, 作用于协议栈里的五个时间点上, 钩子函数呢? 函数是什么样的, 所有的函数可以拿来归类成以下五类函数, 分别存在五张表里, 我们只介绍三个最直观最常用的:

* filter表: (这个表里的函数) 用于控制包要不要了, 是放行还是拒绝
* nat表: 可以修改包的源/目的地址&#x20;
* mangle表: 可以改包的IP头信息

### 某个iptable规则

拿到包, 前往链, 遍历函数, 然后呢? 一个规则是否要执行分成两部分: 匹配条件+动作

* 匹配条件包含: 协议类型, 源IP/端口, 目的IP/端口, 你可以从这些内容里挑出一些组合成一个条件, 用于筛选出你想要的包
* 动作包含:&#x20;
  * DROP直接丢, 什么都不做, 当做无事发生过
  * REJECT拒: 给对端返回一个`connection refused`
  * QUEUE存: 放到一个用户空间的队列里, 等待某用户程序处理
  * ....

### 玩一玩
