工控网络基础入门篇之IPTables 防火墙(一)

netfilter 是 linux 内核的一个模块,这个模块当于 linux 系统的防火墙,它会对所有进出 linux 系统的网路数据进行管理,netfilter 防火墙模块的结构如下图所示:

我们可以看到棕色框1框住的部分就是 iptables 的几个 “链”,分别是 PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING,大致讲一下这几个链的工作流程。当一个数据通过网络接口进入系统之后,首先进入 PREROUTING 链进行处理。PREROUTING 链中根据对数据的不同处理,分别把处理方法写在 mangle 表和 nat 表中,mangle 表一般用于对数据添加标签方便后面的链处理,nat 表一般是进行网络地址转换和转发的动作2。

在经过两道 PREROUTING 链处理之后,数据会根据需求分别交给 INPUT 和 FORWARD 链处理。 INPUT 链再经过打标签,过滤等动作后,再把数据交给上层应用的协议栈去处理。例如我们可以在 INPUT 链末端把数据交给我们写的一个应用,在应用中分析和提取数据,当应用处理过数据之后,就要把数据返还到 OUTPUT 链,OUTPUT 链再经过一次 NAT 表看是否要转址 (只是要经过,不一定真的会发生转址操作),然后交给 POSTROUTING 链。

FORWARD 链一般只是经过 filter 表的过滤筛选就会把数据交给 POSTROUTING 链,从 OUTPUT 链过来的数据和从 FORWARD 链过来的数据经过 POSTROUTING 链处理后就交给了后面的输出设备了。

netfilter 是 linux 内核模块的名称,可是用户要如何操作这个模块,给防火墙添加和修改规则呢? 这里用到的就是 iptables,netfilter 才是防火墙的实体,iptables 是这个实体的管理工具。因为二者的结合非常紧密,所以我们一般都习惯性的称之为 iptables 防火墙。

1、IPSET 概念

在讲 iptables 的功能之前,我们先引入一个额外的概念:ipset。ipset 和前面讲的 table 有点像,但更好理解,它就是一个存储了 IP 值的数组,一般以内存变量的形式驻留在系统内存中,一重启就会消失。要建立一个 ipset,我们可以 ipset 的 create 命令:

ipset  create  vpn  iphash  -exist

这里表示建立一个名叫 VPN 的 iphash 类型的 ipset,iphash 类型的 IPSET 可以存储 65535 个 IP 地址,-exist表示如果这个叫这个名字的 ipset 已经存在了,就跳过不建立了。

如果要把一个 IP(例如 8.8.8.8) 加入一个 IPSET(例如刚刚建立的 vpn set),那就是: 

ipset  add  vpn  8.8.8.8

如果要删除,把 add 改成 del 就行了

ipset  del  vpn  8.8.8.8

如果我们要清空整个 ipset,就用 flush 选项: 

ipset  flush  vpn

如果我们要测试一个 IP(还是 8.8.8.8) 在不在 IPSET(还是 vpn set) 里,就用 TEST 选项: 

ipset  test  vpn  8.8.8.8

2、 iptables 的 mark 功能

 我们前面说了,要把访问被封锁网站数据加入一个 table 让它走 VPN 接口,首先就要对数据打上标签,那么如何用 iptables 给数据打上标签呢? 我们得先把所有被封锁网站的 IP 加入一个 IPSET,然后我们再用 iptables 的一个名叫 set 的模块来对这个 IPSET 进行打标签的操作。下面是 man page 上对这个模块的说明:

set 

This  module  matches  IP  sets  which  can  be  defined  by  ipset (8).

[ --match -set  setname  flag[,flag ]...

where flags are the comma separated list of src and/or dst specifications and there can be no more than six of them. Hence the command

iptables  -A  FORWARD  -m  set  --match -set  test  src ,dst 

will match packets , for which (if the set type is ipportmap ) the source address and destination port pair can be found in the specified set. If the set type of the specified set is single dimension (for example ipmap ), then the command will match packets for which the source address can be found in the specified set.

我们实际的命令是: 

iptables  -t  mangle  -I  PREROUTING  -m  set  --match -set  vpn  dst  -j  MARK  --set -mark  1

解释说明: 

1. iptables -t mangle 默认情况下 iptables 是对 filter 表操作的,如果要指定某个表,就要用 -t 选项。-t mangle 表示我们操作 mangle 表,为什么是 mangle 表? 因为 PREROUTING 链是存放在 mangle 表里的,默认的 filter 表里没有 PREROUTING 链,那为什么是 PREROUTING 链呢? 往下看。 

2. -I,I 表示 insert,也就是插入一条规则。 

3. PREROUTING 不管是从外部网线输入的数据,还是从我们从电脑上发出的数据,对于路由来说都是输入的数据,这里的进和出是从路由的角度来看的,原始数据进来,处理过的数据输出,和你是上传还是下载无关。我们也知道 PREROUTING 链是整个防火墙链的最前端,如果我们要从源头上处理数据,就需要对这个链动手。 

4. -m set 表示调用 set 模块,所有调用模块的格式都是 “-m 模块名”。

5. –match-set vpn dst,表示匹配一个名叫 vpn 的 ipset,dst 表示这是目标地址,因为我们要访问的那些被封锁的服务器对路由来说只可能是目的地而不是源头 (src),src 是我们自己。 

6. -j MARK,-j 是一个通用选项,表示把数据交给后面的动作进行处理,也就是 MARK。

7. –set-mark 1,这是 iptables 的一个叫 CONNMARK 的 extension 提供的功能,就是给数据打上标签了。

iptables 的规则插入是有顺序的,如果在 -I 后面指定一个规则号,就表示在这个规则号前面插入一条规则,如果不指定规则号,就表示在所有规则的最前面插入一条规则。

而 iptables 规则,是从最前面的规则开始一个个尝试的,如果一个数据和前面的某条规则匹配上了,后面的规则就对他无效了,所以你最后插入的规则其实是优先级最高的规则。如果你要加入一条优先级不是那么高的规则,可以用 -A,Append,表示在特定或所有规则后面加入这条规则。所以插入规则的命令格式是:

iptables  -t  表名  -I  链名\  规则号\  规则

在用 iptables 添加了规则之后,如果想看看这些规则是否添加成功,以及他们的顺序,可以用这个命令:

iptables  -t  表名  -L  链名

如果要删除一条规则,就用 -D 选项,后面可以跟规则号表示删除指定规则号,如果不跟规则号,则从最上面 (最优先) 的 0 号规则开始删除。

iptables  -t  表名  -D  链名\  规则号

如果你的自定义规则已经太多太乱,你想把整个链里的规则都清空,就用 -F,flush 选项 

iptables  -t  表名  -F  链名

所以现在我们已经知道了可以让一个 table 里的数据走 VPN 接口,也知道了如何把打标签的数据加入一个 table,也知道了如何把一个 IPSET 的数据都打上标签,那么,如何把被封锁网站的 IP 加入一个 IPSET 呢? 这里我们还是先把 IPTABLES 的其他功能讲完吧,等到下一节我们再处理这个问题。