Linux iptables 详解

最近搭一个框架需要用到iptables做映射,学习了下iptables的原理,总结下方便以后查~。

参考并转载于以下链接:
http://www.cnblogs.com/metoy/p/4320813.html
http://www.ha97.com/4093.html

一、iptables介绍

iptables是Linux中对网络数据包进行处理的一个功能组件,就相当于防火墙,可以对经过的数据包进行处理,例如:数据包过滤、数据包转发等等,一般例如Ubuntu等Linux系统是默认自带启动的。

二、iptables结构

iptables其实是一堆规则,防火墙根据iptables里的规则,对收到的网络数据包进行处理。iptables里的数据组织结构分为:表、链、规则。

表(tables)

表提供特定的功能,iptables里面有4个表: filter表、nat表、mangle表和raw表,分别用于实现包过滤、网络地址转换、包重构和数据追踪处理。
每个表里包含多个链。

链(chains)

链(chains)是数据包传播的路径,每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一 条或数条规则。当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定 义的默认策略来处理数据包。

其整体结构如下图所示:

iptables_tables.png

表链结构

1.filter表——三个链:INPUT、FORWARD、OUTPUT
作用:过滤数据包 内核模块:iptables_filter.

2.Nat表——三个链:PREROUTING、POSTROUTING、OUTPUT
作用:用于网络地址转换(IP、端口) 内核模块:iptable_nat

3.Mangle表——五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
作用:修改数据包的服务类型、TTL、并且可以配置路由实现QOS内核模块

4.Raw表——两个链:OUTPUT、PREROUTING
作用:决定数据包是否被状态跟踪机制处理

数据包流向

前面介绍了iptables的组织结构,下面一张图介绍了一个数据包如何依次穿过iptables的各个链和表的。

iptables_process.png

基本步骤如下:

  1. 数据包到达网络接口,比如 eth0。
  2. 进入 raw 表的 PREROUTING 链,这个链的作用是赶在连接跟踪之前处理数据包。
  3. 如果进行了连接跟踪,在此处理。
  4. 进入 mangle 表的 PREROUTING 链,在此可以修改数据包,比如 TOS 等。
  5. 进入 nat 表的 PREROUTING 链,可以在此做DNAT,但不要做过滤。
  6. 决定路由,看是交给本地主机还是转发给其它主机。

后面将分为2种情况:

  1. 数据包发送给本地主机,交由本地主机上层应用处理;
  2. 将数据包转发给其他主机来处理。

第一种情况,数据包要转发给其它主机:

  1. 进入 mangle 表的 FORWARD 链,这里也比较特殊,这是在第一次路由决定之后,在进行最后的路由决定之前,我们仍然可以对数据包进行某些修改。
  2. 进入 filter 表的 FORWARD 链,在这里我们可以对所有转发的数据包进行过滤。需要注意的是:经过这里的数据包是转发的,方向是双向的。
  3. 进入 mangle 表的 POSTROUTING 链,到这里已经做完了所有的路由决定,但数据包仍然在本地主机,我们还可以进行某些修改。
  4. 进入 nat 表的 POSTROUTING 链,在这里一般都是用来做SNAT ,不要在这里进行过滤。
  5. 进入出去的网络接口。完毕。

第二种情况,数据包就是发给本地主机的,那么它会依次穿过:

  1. 进入 mangle 表的 INPUT 链,这里是在路由之后,交由本地主机之前,我们也可以进行一些相应的修改。
  2. 进入 filter 表的 INPUT 链,在这里我们可以对流入的所有数据包进行过滤,无论它来自哪个网络接口。
  3. 交给本地主机的应用程序进行处理。
  4. 处理完毕后进行路由决定,看该往那里发出。
  5. 进入 raw 表的 OUTPUT 链,这里是在连接跟踪处理本地的数据包之前。
  6. 连接跟踪对本地的数据包进行处理。
  7. 进入 mangle 表的 OUTPUT 链,在这里我们可以修改数据包,但不要做过滤。
  8. 进入 nat 表的 OUTPUT 链,可以对防火墙自己发出的数据做 NAT 。
  9. 再次进行路由决定。
  10. 进入 filter 表的 OUTPUT 链,可以对本地出去的数据包进行过滤。
  11. 进入 mangle 表的 POSTROUTING 链,同上一种情况的第9步。注意,这里不光对经过防火墙的数据包进行处理,还对防火墙自己产生的数据包进行处理。
  12. 进入 nat 表的 POSTROUTING 链,同上一种情况的第10步。
  13. 进入出去的网络接口。完毕

三、iptables操作

参考:http://www.cnblogs.com/metoy/p/4320813.html
iptables的指令图示如下:
iptables_cmd.jpg

如果使用开机转发,需要设置参数:
echo 1 > /proc/sys/net/ipv4/ip_forward

如果想开机自动设置,配置一下文件:
/etc/sysctl.conf文件中的 net.ipv4.ip_forward = 1

iptables的基本语法格式

iptables [-t 表名] 命令选项 [链名] [条件匹配] [-j 目标动作或跳转
说明:表名、链名用于指定 iptables命令所操作的表和链,命令选项用于指定管理iptables规则的方式(比如:插入、增加、删除、查看等;条件匹配用于指定对符合什么样 条件的数据包进行处理;目标动作或跳转用于指定数据包的处理方式(比如允许通过、拒绝、丢弃、跳转(Jump)给其它链处理。

iptables命令的管理控制选项

-A 在指定链的末尾添加(append)一条新的规则
-D 删除(delete)指定链中的某一条规则,可以按规则序号和内容删除
-I 在指定链中插入(insert)一条新的规则,默认在第一行添加
-R 修改、替换(replace)指定链中的某一条规则,可以按规则序号和内容替换
-L 列出(list)指定链中所有的规则进行查看
-E 重命名用户定义的链,不改变链本身
-F 清空(flush)
-N 新建(new-chain)一条用户自己定义的规则链
-X 删除指定表中用户自定义的规则链(delete-chain)
-P 设置指定链的默认策略(policy)
-Z 将所有表的所有链的字节和数据包计数器清零
-n 使用数字形式(numeric)显示输出结果
-v 查看规则表详细信息(verbose)的信息
-V 查看版本(version)
-h 获取帮助(help)

防火墙处理数据包的四种方式

ACCEPT 允许数据包通过
DROP 直接丢弃数据包,不给任何回应信息
REJECT 拒绝数据包通过,必要时会给数据发送端一个响应的信息。
LOG 用于针对特定的数据包打log,在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则
TRACE这个只能针对raw中的table,是用来对数据进行追踪的,用于debug.

iptables防火墙规则的保存与恢复

iptables-save把规则保存到文件中,再由目录rc.d下的脚本(/etc/rc.d/init.d/iptables)自动装载
使用命令iptables-save来保存规则。一般用

1
iptables-save > /etc/sysconfig/iptables

生成保存规则的文件 /etc/sysconfig/iptables,也可以用:

1
service iptables save

iptables防火墙常用的策略

  1. 拒绝进入防火墙的所有ICMP协议数据包
1
iptables -I INPUT -p icmp -j REJECT
  1. 允许防火墙转发除ICMP协议以外的所有数据包
1
iptables -A FORWARD -p ! icmp -j ACCEPT

说明:使用“!”可以将条件取反。

  1. 允许本机开放从TCP端口20-1024提供的应用服务。
1
2
iptables -A INPUT -p tcp --dport 20:1024 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 20:1024 -j ACCEPT
  1. 从一台主机转发到另一台主机

注意转发首先需要按照前面的开启转发设置

(相同端口)
从192.168.0.132:21521(新端口)访问192.168.0.211:1521端口

1
2
iptables -t nat -I PREROUTING -p tcp --dport 1521 -j DNAT --to 192.168.0.211
iptables -t nat -I POSTROUTING -p tcp --dport 1521 -j MASQUERADE

(不同端口)
不同端口转发(192.168.0.132上开通21521端口访问

1
2
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 21521 -j DNAT --to-destination 192.168.0.211:1521
iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -d 192.168.0.211 -p tcp -m tcp --dport 1521 -j SNAT --to-source 192.168.0.132

以上两条等价配置(更简单[指定网卡]):

1
2
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 31521 -j DNAT --to 192.168.0.211:1521
iptables -t nat -A POSTROUTING -j MASQUERADE

(用iptables做本机端口转发)

1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

其他一些指令可以继续查看:
http://www.cnblogs.com/metoy/p/4320813.html

我要用到的是将本地qemu仿真的一个虚拟机中的IP:PORT给映射到主机的端口上来对外服务:

qemu仿真系统IP为192.168.0.1,仿真系统与主机的桥接的网卡上,主机的ip为192.168.0.2,主机对外ip为172.18.236.82,将虚拟机中的80端口映射到主机的8080端口:

1
2
sudo iptables -t nat -A PREROUTING -d 172.18.236.82 -p tcp --dport 8081 -j DNAT --to-destination 192.168.0.1:80
sudo iptables -t nat -A POSTROUTING -d 192.168.0.1 -p tcp --dport 80 -j SNAT --to 192.168.0.2

四、python对iptables的操作包

python中有对iptables的操作包: iptc
参考主页:
https://github.com/ldx/python-iptables

Linux上安装:
针对python的:
pip install –upgrade python-iptables
针对python3的:
pip3 install –upgrade python-iptables

在python文件中导入:
import iptc

官网里面有对该包的介绍和很多例子,但没有一个所有指令的完整归纳,有些指令参数不知道在iptc包中用什么,后面总结了在加在这~

五、 iptables的debug

在对问题进行处理时,我们肯定会遇到debug的需求,针对iptables的debug主要是通过看Log.

5.1. 打开iptables的log日志

首先我们需要打开iptables的log记录功能,让系统将相应的log输出。
默认iptables的日志是输出到/var/log/message文件中,当然对没有开启log功能的时候,不会有任何log输出。
为了便于debug,我们将iptables的log输出到/var/log/iptables.log文件。
开启log输出针对不同系统会不同,主要是以下2种:

5.1.1 针对用syslog的系统

如果系统存在以下文件: /etc/syslog.conf, 我们在/etc/syslog.conf中添加以下几行:

1
2
kern.warning /var/log/iptables.log
kern.debug /var/log/iptables.log

然后重启syslog:
sudo service syslog restart

5.1.2 针对用rsyslog的系统

如果系统存在以下文件: /etc/rsyslog.conf, 我们在/etc/syslog.conf中添加以下几行:

1
2
kern.warning /var/log/iptables.log
kern.debug /var/log/iptables.log

然后重启syslog:
sudo service rsyslog restart

5.2 针对需要查看的数据,添加iptables规则使其打印log

开启log输出后,我们需要添加相应的iptables规则,使其打印我们需要的log信息,主要有2种方法:

5.2.1 TRACE方法

在前面的数据包流向图中,raw表中的链是用来对数据包进行追踪的,我们可以在其链中添加TRACE操作规则,使其对相应的流量进行追踪,例如下面的例子将追踪进入的目标地址为192.168.0.211的数据包。

1
sudo iptables -t raw -I PREROUTING -d 192.168.0.211 -j TRACE

5.2.2 LOG方法

如果想在指定的一个表的一个链中加入一条规则,当在这个链中遇到特定的数据包,则记录一条log信息。例如下面的指令将使得在nat的PREROUTING链中遇到目标地址为100.69.73.114时,则记录一条log。

1
sudo iptables -t nat -I PREROUTING -d 100.69.73.114 -j LOG --log-level 4

5.3 查看log信息

1
sudo tail -f /var/log/iptables.log