Introduction
-
iptables是Linux系统一个工具集。通过它我们可以配置、管理网络流量规则。值得注意的是这里包括入站流量、出战流量。 -
iptables保障了系统的安全性,给过滤流量以及网络地址转换制定了规则. -
iptables主要存在以下几个概念:Table(表): Filter, NAT, Mangle, Raw ;默认 Filter 也是我们常用的防火墙设置Chains(链路): 链是数据包匹配的规则列表。常见的链包括 Input(用于传入的数据包)、Output(用于传出的数据包)和 Forward(用于经过系统路由的数据包)。Rules(规则): 规则用于定义数据包在链中的处理方式。规则由一组条件和一个关联的操作组成,这些操作可以是 Accept、Drop 或 RejectTarget(目标动作):目标是当规则匹配时可以采取的行动。常见的目标包括 Accept(允许一个数据包),Drop(丢弃一个数据包)和 Reject(拒绝一个数据包并发送错误消息)。
-
iptables 的命令格式如下
shell
iptables [ -t 表名] [COMMAND] [链名] [条件匹配] [-j 目标动作或跳转]
TABLE
Table分为四类:Filter、Nat、Mangle、Raw。Table的加载顺序: Raw>Mangle>Nat>Filter

-
我的个人理解是
TABLE就是功能场景,我们使用iptables最常用的场景就是Filter,用来对端口的出入站进行控制。 -
其中
TABLE对应iptables中命令的-t参数 , 默认情况下-t可以不填,不填的话默认就是-t Filter.
COMMAND
Command就是告诉iptables接下来需要做什么? 比如告诉iptables新增一条规则 or 删除一条规则过滤功能。




source、destination分别对应的是-s、-d两个参数,这里我们可以设置 IP 地址也可以设置网络地址192.168.0.135、192.168.0.135/24。- 我们可以通过
-s设置指定 IP 范围。
CHAINS
-
Chains在每个Table下的概念,主要归纳为- PREROUTING : 数据包进入路由表之前
INPUT: 本机入站流量OUTPUT: 本机出站流量FORWARD: 将数据转发到本机的其他网卡设备上- POSTROUTING : 数据包离开路由表之后,或者进入网卡之前。
-
其中中间三条
INPUT、OUTPUT、FORWARD三个在 Filter 中使用最频繁,而我们常规的 iptables 只有INPUT使用最频繁的。 -
上面介绍的四种表中并不是每个都有五条链的。下面介绍下每张表分别有哪些链条(四表五链)。
| Table | Chains |
|---|---|
| Filter | INPUT 、 OUTPUT 、 FORWARD |
| Nat | PREROUTING 、INPUT 、OUTPUT 、FORWARD、POSTROUTING |
| Mangle | PREROUTING 、INPUT 、 OUTPUT 、 FORWARD |
| Raw | PREROUTING 、OUTPUT |
RULES
- 其中最主要的就是规则。每次进出站都是通过匹配规则执行相应动作的。
shell
sudo iptables -I INPUT -p tcp -m multiport --dport 80,443,1883,3306,5432,8700,8743,8080,8848,18080,8999,3000 -j ACCEPT
- 上面的命令就是针对所有的入站针对指定的多个端口进行放行。其中的规则就是
-p。这里是针对协议。除了针对协议 以外还有如下配置:
| 匹配参数 | 说明 |
|---|---|
| -p | 指定规则协议,如 tcp, udp,icmp 等,可以使用 all 来指定所有协议 |
| -s | 指定数据包的源地址参数,可以使 IP 地址、网络地址(子网掩码方式)、主机名 |
| -d | 指定目的地址(同-s) |
| -i | 输入接口 , 网卡设置 |
| -o | 输出接口 , 网卡设置 |
| -m | 扩展字段 |
什么叫扩展条件?
- 还是看上面我们的命令,除了
-p这个条件指定的是 tcp 模式,我们还注意到-m就是我们提到的扩展条件。意思就是有了-m我们就可以使用二级条件,比如后面紧跟的--dport。因为在-m一级条件中已经指明了multiport所以在二级命令中我们添加了多个端口。这样就避免我们多次添加端口过滤了。
| 命令 | 作用 | 显示 | |
|---|---|---|---|
| tcp | --sport : 源端口;--dport : 目标端口; --tcp-flags: TCP 握手阶段拦截,SYN,ACK,RST 等; --syn :第一次握手 | NO | |
| udp | --sport : 源端口;--dport : 目标端口; | ||
| icmp | 8 : 输出请求。; 0 : 输出响应 | ||
| state | 用于连接状态的检测;NEW , ESTABLISHED, RELATED ,INVALID . | ||
| multiport | --dport : 多个目标端口; --sport : 多个目标源端口; --ports : 多个源&目端口 | ||
| limit | --limit : 速率,如--limit 3 表示 1 分钟不超过 3 个数据包;--limit-burst : 峰值 | ||
| connlimit | --connlimt-above n : 连接数超过 n | ||
| iprange | --src-range 192.168.0.100-192.168.0.200 : 源 IP 范围; --dst-range 类似 | ||
| mac | --mac-source mac 地址限制 | ||
| string | --algo [bm | kmp] 匹配算法; --string pattern : 正则匹配 //TODO 不明白 | |
| recent | 用不上 |
markdown
| | |

JUMP
jump对应的是我们命令模式中的-j,也可以叫做Target,这个在iptables -L n中能够体现。 主要就是三个动作ACCEPT、DROP、REJECT ` 。
| Jump | Description |
|---|---|
| ACCEPT | 允许数据包通过。 |
| DROP | 直接丢弃数据包,不给出任何回应信息。 |
| REJECT | 拒绝数据包通过,必须时会给数据发送端一个响应信息。 |
| LOG | 在/var/log/messages 文件中记录日志信息,然后将数据包传递给下一条规则。 |
| QUEUE | 防火墙将数据包移交到用户空间 |
| RETURN | 防火墙停止执行当前链中的后续 Rules,并返回到调用链(the calling chain) |
Common Command
iptables -A: 添加一个规则iptables -D: 删除一个规则.iptables -L: 查看 Chains 中的规则列表 :iptables -L INPUT. ;在每个 Chain 的最后还会输出默认策略是啥,这里对应iptables -Piptables -F: 清空 Chains 中所有规则.iptables -P: 给 Chains 设置默认策略 (e.g., ACCEPT or DROP).service iptables save或iptables-save > /etc/sysconfig/iptables: 保存当前 iptables 规则,以便在系统重启时自动加载。
shell
iptables -A INPUT -p tcp --dport 1000:2000 -j ACCEPT # 1000~2000 端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # 80
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 443
-
指定位置添加 : `iptables -I INPUT 2 -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-
允许远程连接:
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
Brief Summary

FILTER
- 上面大段的介绍全都是基于
Filter表展开的。所以这里我们直接跳过吧。
NAT
Network Address Translation网络地址转换。- 我们大部分使用它来流量代理转换,类似于 nginx 一样。
Scene
- 实现 A 服务器流量转发到 B 服务器上。
- 192.168.0.135:80
- 192.168.0.190:81
- 针对上面两个服务端口实现,135 上的 80 端口流量全部转发到
190上的 81 端口。
Prefix Conditions
- 首先我们得开启内核支持。临时开启的话只需要保证
/proc/sys/net/ipv4/ip_forward文件内容为1。 - 如果是永久生效的话,我们得保证
/etc/sysctl.conf中存在net.ipv4.ip_forward=1配置。echo 1 > /proc/sys/net/ipv4/ip_forward- echo "net.ipv4.ip_forward=1" >>
/etc/sysctl.conf - 上述无误后我们重启即可。
systemctl restart network
- 最终我们查看下配置是否支持转发
sysctl net.ipv4.ip_forward

Operation
shell
iptables -t nat -A PREROUTING -d 192.168.0.135/32 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.190:81;
iptables -t nat -A POSTROUTING -d 192.168.0.190/32 -p tcp --dport 81 -j SNAT --to-source 192.168.0.135;
- 最后我们验证下
telnet 192.168.0.135 8700会看到信息展示190的信息。具体我就不展示了,因为没有实际操作。
MANGLE
Mangle的主要功能是修改数据包。

-
假设上面是我们内部的网络拓扑图,我们内网有台代理服务器作为网关存在
Proxy. 在这台服务上存在三个网口分别是enth0: 内网、enth1:美国、enth2:韩国。 -
这也就意味着
Proxy这台服务器可以同时连接美国和韩国的网络的同时还存在一组内网。
Scene
- 现在在内网的一台设备
Client想要实现所有通过内网访问的 80 端口都映射到美国网络中,而所以通过 UDP 协议访问的 53 端口全部走韩国路线。
Operation
- 这就需要我们针对不同的协议端口进行打标签,从而才能区分出来该如何进行路由。而打标签就是我们
iptables Mangle表来实现修改数据包功能。
shell
iptables -t mangle -A PREROUTING -i enth0 -p tcp --dport 80 -j MARK --set- mark 1
iptables -t mangle -A PREROUTING -i enth0 -p udp --dport 53 -j MARK --set- mark 2
- 上面的配置就会在进路由分发之前给两个端口协议打上 mark 标签。动态路由就涉及到
ip rule和ip route的知识,这里就直接贴代码
shell
ip rule add from all fwmark 1 table 10
ip rule add from all fwmark 2 table 20
- 可以看出只要是 mark=1 的就会走 route=10 的路由策略。
shell
ip route add default via 10.0.20.21 dev enth1 table 10
ip route add default via 10.0.20.22 dev enth1 table 20
FQA
开放端口后依然无法访问问题

--reject-with icmp-host-prohibited. 不难发现在上述的防火墙列表上存在icmp-host-prohibited.ICMP (Internet Control Message Protocol).这个是拒绝连接的提示信息。对应的错误信息提示 code 应该是Host Prohibited.。
shell
iptables -A INPUT -p tcp --dport 80 -j REJECT --reject-with icmp-host-prohibited
- 如上我们添加 80 端口拒绝连接并做出响应的提示,值得注意的是给出提示其实也是信息不安全的,所以如果我们想绝对的安全那就直接将
Reject换成Drop模式。