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 -P
iptables -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
模式。