iptables
- iptables 规则组成
- 四张表 + 五条链 (Hook point) + 规则
- 表: filter /nat/mangle /raw
- Filter: 访问控制、规则匹配
- Nat: 地址转发
- 链: PREROUTING / INPUT / OUTPUT / FORWARD / POSTROUTING
- 规则
- 数据包访问控制: ACCEPT / DROP / REJECT
- 数据包修改: SNAT / DNAT
一些常用的参数:
| table | command | chain | Paramater & Xmatch | target
iptables | -t filter | -A(--append) | INPUT | -p(--protocol) tcp | -j(--jump) ACCEPT
| nat | -D(--delete) | FORWARD | -s(--source) | DROP
| | -L(--list) | OUTPUT | -d(--destination) | REJECT
| 默认值 | -F(--flush) | PREROUTING | --sport | DNAT
| filter | -P(--policy) | POSTROUTING | --dport | SNAT
| | -I(--insert) | | --dports |
| | -R(--replace)| | -m(--match)tcp |
| | -n(--numeric)| | state |
| | | | multiport |
- 四张表 + 五条链 (Hook point) + 规则
- 表: filter /nat/mangle /raw
- Filter: 访问控制、规则匹配
- Nat: 地址转发
- 链: PREROUTING / INPUT / OUTPUT / FORWARD / POSTROUTING
- 规则
- 数据包访问控制: ACCEPT / DROP / REJECT
- 数据包修改: SNAT / DNAT
| table | command | chain | Paramater & Xmatch | target
iptables | -t filter | -A(--append) | INPUT | -p(--protocol) tcp | -j(--jump) ACCEPT
| nat | -D(--delete) | FORWARD | -s(--source) | DROP
| | -L(--list) | OUTPUT | -d(--destination) | REJECT
| 默认值 | -F(--flush) | PREROUTING | --sport | DNAT
| filter | -P(--policy) | POSTROUTING | --dport | SNAT
| | -I(--insert) | | --dports |
| | -R(--replace)| | -m(--match)tcp |
| | -n(--numeric)| | state |
| | | | multiport |
几个关于 filter 表的场景
场景一
- 规则 1: 对所有的地址开放本机 tcp 协议的 80, 22, 10-21 端口的访问
- 规则 2: 允许对所有的地址开放本机的基于 ICMP 协议的数据包访问
- 规则 3: 其他未被允许的端口则禁止访问
#iptables -I INPUT -p tcp --dport 80 -j ACCEPT
#iptables -I INPUT -p tcp --dport 22 -j ACCEPT
#iptables -I INPUT -p tcp --dport 10:21 -j ACCEPT
#iptables -I INPUT -p icmp -j ACCEPT
#iptables -A INPUT -j REJECT
- 存在两个问题
- 不能访问环回地址
- 无法进行外部访问
解决方法如下:
#iptables -I INPUT -i lo -j ACCEPT
#iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Consider a NEW packet a telephone call before the receiver has picked up. An ESTABLISHED packet is their, “Hello.” And a RELATED packet would be if you were calling to tell them about an e-mail you were about to send them. (The e-mail being RELATED.)
In case my analogy isn’t so great, I personlly think the man pages handles it well:
NEW – meaning that the packet has started a new connection, or otherwise associated with a connection which has not seen packets in both directions, and
ESTABLISHED – meaning that the packet is associated with a connection which has seen packets in both directions,
RELATED – meaning that the packet is starting a new connection, but is associated with an existing connection, such as an FTP data transfer, or an ICMP error.
- 附加规则:允许指定 ip 访问
#iptables -I INPUT -p tcp -s 10.10.188.233 --dport 80 -j ACCEPT
#iptables -I INPUT -p tcp --dport 80 -j ACCEPT
#iptables -I INPUT -p tcp --dport 22 -j ACCEPT
#iptables -I INPUT -p tcp --dport 10:21 -j ACCEPT
#iptables -I INPUT -p icmp -j ACCEPT
#iptables -A INPUT -j REJECT
- 存在两个问题
- 不能访问环回地址
- 无法进行外部访问
解决方法如下:
#iptables -I INPUT -i lo -j ACCEPT
#iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Consider a NEW packet a telephone call before the receiver has picked up. An ESTABLISHED packet is their, “Hello.” And a RELATED packet would be if you were calling to tell them about an e-mail you were about to send them. (The e-mail being RELATED.)
In case my analogy isn’t so great, I personlly think the man pages handles it well:NEW – meaning that the packet has started a new connection, or otherwise associated with a connection which has not seen packets in both directions, and
ESTABLISHED – meaning that the packet is associated with a connection which has seen packets in both directions,
RELATED – meaning that the packet is starting a new connection, but is associated with an existing connection, such as an FTP data transfer, or an ICMP error.
- 附加规则:允许指定 ip 访问
#iptables -I INPUT -p tcp -s 10.10.188.233 --dport 80 -j ACCEPT
场景二
ftp 主动模式 + ssh port + ICMP protocol 配置:
#iptables -I INPUT -p tcp --dport 21 -j ACCEPT
#iptables -I INPUT -p tcp --dport 22 -j ACCEPT
#iptables -I INPUT -P icmp -j ACCEPT
#iptabels -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#iptabels -A INPUT -j REJECT
思考:为什么不需要打开 22 端口?下一篇解答。
ftp 被动模式
-
方法一 – 需监听高端口
- 1
#iptables -I INPUT -p tcp --dport 21 -j ACCEPT
- 2 配置 vsftp 的被动随机端口是 50000 — 60000
- pasv_min_port=50000
- pasv_max_port=60000
- 3
#iptables -I INPUT -p tcp --dprot 50000:60000 -j ACCEPT
-
方法二 –使用链接追踪模块
- 内核启用 nf_conntrack_ftp 模块
- 临时启用
#modprobe nf_conntrack_ftp
- 添加内核模块启动参数
IPTABLES_MODULES="nf_conntrack_ftp"
#iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#iptables -I INPUT -p tcp --dport 21 -j ACCEPT
#iptables -I INPUT -p tcp --dport 21 -j ACCEPT
#iptables -I INPUT -p tcp --dport 22 -j ACCEPT
#iptables -I INPUT -P icmp -j ACCEPT
#iptabels -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#iptabels -A INPUT -j REJECT
思考:为什么不需要打开 22 端口?下一篇解答。
ftp 被动模式
- 方法一 – 需监听高端口
- 1
#iptables -I INPUT -p tcp --dport 21 -j ACCEPT
- 2 配置 vsftp 的被动随机端口是 50000 — 60000
- pasv_min_port=50000
- pasv_max_port=60000
- 3
#iptables -I INPUT -p tcp --dprot 50000:60000 -j ACCEPT
- 1
- 方法二 –使用链接追踪模块
- 内核启用 nf_conntrack_ftp 模块
- 临时启用
#modprobe nf_conntrack_ftp
- 添加内核模块启动参数
IPTABLES_MODULES="nf_conntrack_ftp"
- 临时启用
#iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#iptables -I INPUT -p tcp --dport 21 -j ACCEPT
- 内核启用 nf_conntrack_ftp 模块
场景三
-
要求一:员工在公司内部 (10.10.155.0/24, 10.10.188.0/24) 能访问服务器上的任何服务。
-
要求二:外网 === 拨号到 ==> VPN 服务器 ====> 内网 FTP / SAMBA / NFS / SSH
-
要求三: HTTP 服务需要允许公网访问
-
允许本地访问,外网 + 本地环回地址
-
允许已监听状态数据包通过,10.10.155.0/24 / 10.10.188.0/24
-
允许规则中允许的数据包通过,PPTP 端口 1723 / HTTP 端口 80 / ICMP 数据包
-
拒绝未被允许的数据包
#iptables -I INPUT -i lo -j ACCEPT
#iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#iptables -A INPUT -s 10.10.155.0/24 -j ACCEPT
#iptables -A INPUT -s 10.10.188.0/24 -j ACCEPT
#iptables -A INPUT -p tcp --dport 80 -j ACCEPT
#iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
#iptables -I INPUT -p icmp -j ACCEPT
#iptables -A INPUT -j REJECT
要求一:员工在公司内部 (10.10.155.0/24, 10.10.188.0/24) 能访问服务器上的任何服务。
要求二:外网 === 拨号到 ==> VPN 服务器 ====> 内网 FTP / SAMBA / NFS / SSH
要求三: HTTP 服务需要允许公网访问
允许本地访问,外网 + 本地环回地址
允许已监听状态数据包通过,10.10.155.0/24 / 10.10.188.0/24
允许规则中允许的数据包通过,PPTP 端口 1723 / HTTP 端口 80 / ICMP 数据包
拒绝未被允许的数据包
#iptables -I INPUT -i lo -j ACCEPT
#iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#iptables -A INPUT -s 10.10.155.0/24 -j ACCEPT
#iptables -A INPUT -s 10.10.188.0/24 -j ACCEPT
#iptables -A INPUT -p tcp --dport 80 -j ACCEPT
#iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
#iptables -I INPUT -p icmp -j ACCEPT
#iptables -A INPUT -j REJECT
iptables nat 表规则配置
分类 功能 作用链
SNAT 源地址转换 出口 POSTROUTING
DNAT 目标地址转换 进口 PREROUTING
SNAT 转发
- 三台机器 A (Client, 10.10.177.233) B (Gatway, eth0: 10.10.188.232 /eth1:10.10.177.232) C (server, 10.10.188.173)
- B 设置
- 内核
net.ipv4.ip_forward=1
#iptables -t nat -A POSTROUTING -s 10.10.177.0/24 -j SNAT --to 10.10.188.232
- A 设置
- 添加 10.10.177.232 为网关
DNAT 转发
- 10.10.188.232:80 <==> 10.10.177.233:80
#iptables -t nat -A PREROUTING -d 10.10.188.232 -p tcp --dport 80 -j DNAT --to 10.10.177.233:80
思考:本地端口 (不经过网卡的数据包) 如何转发?依旧下一篇。
分类 | 功能 | 作用链 |
---|---|---|
SNAT | 源地址转换 | 出口 POSTROUTING |
DNAT | 目标地址转换 | 进口 PREROUTING |
- 内核
net.ipv4.ip_forward=1
#iptables -t nat -A POSTROUTING -s 10.10.177.0/24 -j SNAT --to 10.10.188.232
- 添加 10.10.177.232 为网关
#iptables -t nat -A PREROUTING -d 10.10.188.232 -p tcp --dport 80 -j DNAT --to 10.10.177.233:80
防止 CC 攻击
-
connlimit 模块
- 作用:限制每一个客户端 ip 的并发连接数
- 参数:
--connlimit-above n
n 为限制并发个数
- 例子
#iptables -I INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT
- 控制并发 http 访问
#iptables -I INPUT -p tcp --dport 80 -s 10.10.163.232 -m connlimit --connlimit-above 10 -j REJECT
-
limit 模块
- 作用:限速,控制访问
- 例子
#iptables -A INPUT -m limit --limit 3/hour
--limit-burst
默认值为 5
- 允许 10 个,超过 10 个分钟允许 1 个 icmp 数据包
#iptables -A INPUT -p icmp -m limit --limit 1/m --limit-burst 10 -j ACCEPT
#iptables -A INPUT -p icmp -j DROP
connlimit 模块
- 作用:限制每一个客户端 ip 的并发连接数
- 参数:
--connlimit-above n
n 为限制并发个数 - 例子
#iptables -I INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT
- 控制并发 http 访问
#iptables -I INPUT -p tcp --dport 80 -s 10.10.163.232 -m connlimit --connlimit-above 10 -j REJECT
limit 模块
- 作用:限速,控制访问
- 例子
#iptables -A INPUT -m limit --limit 3/hour
--limit-burst
默认值为 5
- 允许 10 个,超过 10 个分钟允许 1 个 icmp 数据包
#iptables -A INPUT -p icmp -m limit --limit 1/m --limit-burst 10 -j ACCEPT
#iptables -A INPUT -p icmp -j DROP
------------
数据包的流向
- 表 (tables)
- 链 (chains)
- 表由链组成,链是一些按顺序排列的规则的列表
- 默认的 filter 表包含 INPUT, OUTPUT 和 FORWARD 3 条内建的链
- nat 表包含 PREROUTING, POSTROUTING 和 OUTPUT 链
- 链的默认规则通常设置为 ACCEPT,如果想确保任何包都不能通过规则集,那么可以重置为 DROP
- 默认的规则总是在一条链的最后生效
- 规则 (rules)
- 数据包的过滤基于规则
- 规则由一个目标(数据包包匹配所有条件后的动作)和很多匹配(导致该规则可以应用的数据包所满足的条件)指定
- 一个规则的典型匹配事项是数据包进入的端口(例如:eth0 或者 eth1)、数据包的类型(ICMP, TCP, 或者 UDP)和数据包的目的端口
- 目标 (target) 使用 -j 或者 –jump 选项指定
- 目标可以是用户定义的链(例如,如果条件匹配,跳转到之后的用户定义的链被继续处理)、一个内置的特定目标或者是一个目标扩展
- 如果目标是内置目标,数据包的命运会立刻被决定并且在当前表的数据包的处理过程会停止
- 内置目标是 ACCEPT, DROP, QUEUE 和 RETURN, 目标扩展是 REJECT 和 LOG
- 如果目标是用户定义的链,并且数据包成功穿过第二条链,目标将移动到原始链中的下一个规则
- 目标扩展可以被终止(像内置目标一样)或者不终止(像用户定义链一样)
- 数据包的过滤基于规则
- 模块 (modules)
- 有许多模块可以用来扩展 iptables,例如 connlimit, conntrack, limit 和 recent。这些模块增添了功能,可以进行更复杂的过滤。
这里的内容是关于数据包是以什么顺序、如何穿越不同的链和表的。
下图简要描述了网络数据包通过 iptables 的 nat 与 filter 表的过程.
第一个路由策略包括决定数据包的目的地是本地主机(这种情况下,数据包穿过 INPUT 链),还是其他主机(数据包穿过 FORWARD 链);中间的路由策略包括决定给传出的数据包使用那个源地址、分配哪个接口;最后一个路由策略存在是因为先前的 mangle 与 nat 链可能会改变数据包的路由信息。
数据包通过路径上的每一条链时,链中的每一条规则按顺序匹配;无论何时匹配了一条规则,相应的 target/jump 动作将会执行。最常用的 3 个 target 是 ACCEPT, DROP , 或者 jump 到用户自定义的链。只有内置的链拥有默认的策略,用户自定义的链没有默认的策略 (Policy, 当封包不在设定的规则之内时,则该封包的通过与否,是以 Policy 的设定为准)。
在任何时候,若 DROP target 的规则实现完全匹配,那么被匹配的数据包会被丢弃,不会进行进一步处理。如果一个数据包在链中被 ACCEPT,那么它也会被所有的父链 ACCEPT,并且不再遍历其他父链。然而,要注意的是,数据包还会以正常的方式继续遍历其他表中的其他链。
一些乱七八糟的知识
- 分类
- 静态 NAT (Static NAT)
- 动态地址 NAT (Pooled NAT)
- 网络地址端口转换 NAPT (Port-Level NAT)
- 网络地址端口转换 NAPT (Network Address Port Translation) 则是把内部地址映射到外部网络的一个 IP 地址的不同端口上。它可以将中小型的网络隐藏在一个合法的 IP 地址后面。NAPT 与动态地址 NAT 不同,它将内部连接映射到外部网络中的一个单独的 IP 地址上,同时在该地址上加上一个由 NAT 设备选定的端口号
- 包含 SNAT 与 DNAT
- 源 NAT (Source NAT, SNAT): 修改数据包的源地址。源 NAT 改变第一个数据包的来源地址,它永远会在数据包发送到网络之前完成,数据包伪装就是一个 SNAT 的例子
- 目的 NAT (Destination NAT, DNAT): 修改数据包的目的地址。DNAT 刚好与 SNAT 相反,它是改变第一个数据懈的目的地地址,如平衡负载、端口转发和透明代理就是属于 DNAT
- 应用
- NAT 主要可以实现以下几个功能:数据包伪装、平衡负载、端口转发和透明代理
- 数据伪装:可以将内网数据包中的地址信息更改成统一的对外地址信息,不让内网主机直接暴露在因特网上,保证内网主机的安全。同时,该功能也常用来实现共享上网
- 端口转发:当内网主机对外提供服务时,由于使用的是内部私有 IP 地址,外网无法直接访问。因此,需要在网关上进行端口转发,将特定服务的数据包转发给内网主机
- 负载平衡:目的地址转换 NAT 可以重定向一些服务器的连接到其他随机选定的服务器
- 失效终结:目的地址转换 NAT 可以用来提供高可靠性的服务。如果一个系统有一台通过路由器访问的关键服务器,一旦路由器检测到该服务器当机,它可以使用目的地址转换 NAT 透明的把连接转移到一个备份服务器上
- 透明代理: NAT 可以把连接到因特网的 HTTP 连接重定向到一个指定的 HTTP 代理服务器以缓存数据和过滤请求。一些因特网服务提供商就使用这种技术来减少带宽的使用而不用让他们的客户配置他们的浏览器支持代理连接
- NAT 主要可以实现以下几个功能:数据包伪装、平衡负载、端口转发和透明代理
- 原理
- 地址转换
- 连接跟踪
- 端口转换
NAT 是如何进行地址转换的:
- 私有网中的主机 192.168.1.2 向公共网中的主机 202.20.65.4 发送了 1 个 HTTP 请求 (Dst=202.20.65.4,Src=192.168.1.2),他是一个 IP 包
- 当 IP 包经过 NAT 网关时,NAT Gateway 会将 IP 包的源 IP 转换为 NAT Gateway 的公共 IP 并转发到公共网,此时 IP 包 (Dst=202.20.65.4,Src=202.20.65.5) 中已经不含任何私有网 IP 的信息。
- 由于 IP 包的源 IP 已经被转换成 NAT Gateway 的公共 IP ,Web Server 发出的响应 IP 包 (Dst= 202.20.65.5,Src=202.20.65.4) 将被发送到 NAT Gateway
- 这时,NAT Gateway 会将 IP 包的目的 IP 转换成私有网中主机的 IP,然后将 IP 包 (Des=192.168.1.2,Src=202.20.65.4) 转发到私有网
对于通信双方而言,这种地址的转换过程是完全透明的。如果内网主机发出的请求包未经过 NAT,那么当 Web Server 收到请求包,回复的响应包中的目的地址就是私网 IP 地址,在 Internet 上无法正确送达,导致连接失败。
在上述过程中,NAT Gateway 在收到响应包后,就需要判断将数据包转发给谁。此时如果子网内仅有少量客户机,可以用静态 NAT 手工指定;但如果内网有多台客户机,并且各自访问不同网站,这时候就需要连接跟踪 (connection track)。
还是以上述 Client 访问 Web Server 为例:
当仅有一台客户机访问服务器时,NAT Gateway 只须更改数据包的源 IP 或目的 IP 即可正常通讯。但是如果 Client A 和 Client B 同时访问 Web Server,那么当 NAT Gateway 收到响应包的时候,就无法判断将数据包转发给哪台客户机。此时,NAT Gateway 会在 Connection Track 中加入端口信息加以区分,即端口转换。 如果两客户机访问同一服务器的源端口不同,那么在 Track Table 里加入端口信息即可区分,如果源端口正好相同,那么在时行 SNAT 和 DNAT 的同时对源端口也要做相应的转换。
当仅有一台客户机访问服务器时,NAT Gateway 只须更改数据包的源 IP 或目的 IP 即可正常通讯。但是如果 Client A 和 Client B 同时访问 Web Server,那么当 NAT Gateway 收到响应包的时候,就无法判断将数据包转发给哪台客户机。此时,NAT Gateway 会在 Connection Track 中加入端口信息加以区分,即端口转换。 如果两客户机访问同一服务器的源端口不同,那么在 Track Table 里加入端口信息即可区分,如果源端口正好相同,那么在时行 SNAT 和 DNAT 的同时对源端口也要做相应的转换。
NAT 表
一段数据流的第一个包会流经这个表,此后其余的包都自动会做相同的处理。实际的 target 分为以下几类:
- DNAT
- SNAT
- MASQUERADE
- REDIRECT
MASQUERADE
的作用与 SNAT
完全一样。对于每个匹配的包,MASQUERADE
都会查找可用的 IP 地址,而不像 SNAT
使用的 IP 地址是配置好的。使用
MASQUERADE
也有好处,就是可以使用通过 PPP、 PPPoE、SLIP 等拨号得到的地址,这些地址可是由 ISP 的 DHCP 随机分配的。- 数据包在用户空间的四种状态
- 连接跟踪记录
- TCP / UDP / ICMP 连接
- 缺省的连接操作
- 复杂协议和连接跟踪
在内核中,数据包的状态随着协议的不同而不同。但是在内核外部,也就是用户空间里,只有四种状态。
State (状态) | Explanation (解释) |
---|---|
NEW | NEW 说明这个包是我们看到的第一个包。意思就是,这是 conntrack 模块看到的某个连接第一个包,它即将被匹配了。比如,我们看到一个 SYN 包,是我们所留意的连接的第一个包,就要匹配它。第一个包也可能不是 SYN 包,但它仍会被认为是 NEW 状态。这样做有时会导致一些问题,但对某些情况是有非常大的帮助的。例如,在我们想恢复某条从其他的防火墙丢失的连接时,或者某个连接已经超时,但实际上并未关闭时。 |
ESTABLISHED | ESTABLISHED 已经注意到两个方向上的数据传输,而且会继续匹配这个连接的包。处于 ESTABLISHED 状态的连接是非常容易理解的。只要发送并接到应答,连接就是 ESTABLISHED 的了。一个连接要从 NEW 变 为 ESTABLISHED,只需要接到应答包即可,不管这个包是发往防火墙的,还是要由防火墙转发的。ICMP 的错误和重定向等信息包也被看作是 ESTABLISHED,只要它们是我们所发出的信息的应答。 |
RELATED | RELATED 是个比较麻烦的状态。当一个连接和某个已处于 ESTABLISHED 状态的连接有关系时,就被认为是 RELATED 的了。换句话说,一个连接要想是 RELATED 的,首先要有一个 ESTABLISHED 的连接。这个 ESTABLISHED 连接再产生一个主连接之外的连接,这个新的连接就是 RELATED 的了,当然前提是 conntrack 模块要能理解 RELATED。ftp 是个很好的例子,FTP-data 连接就是和 FTP-control 有 RELATED 的。还有其他的例子,比如,通过 IRC 的 DCC 连接。有了这个状态,ICMP 应答、FTP 传输、DCC 等才能穿过防火墙正常工作。注意,大部分还有一些 UDP 协议都依赖这个机制。这些协议是很复杂的,它们把连接信息放在数据包里,并且要求这些信息能被正确理解。 |
INVALID | INVALID 说明数据包不能被识别属于 哪个连接或没有任何状态。有几个原因可以产生这种情况,比如,内存溢出,收到不知属于哪个连接的 ICMP 错误信息。一般地,我们 DROP 这个状态的任何东西。 |
UNTRACKED | 简单的说,若一个包在 raw 表中被表记为 NOTRACK target,那么在状态机制中就会显示 UNTRACKED。这也意味着所有 RELATED 连接不会被看到。因此当处理 UNTRACKED 连接时候,有些东西已定要小心,因为像依赖于 ICMP 等的信息不会在状态机制中显示。 |
若安装了连接跟踪模块 (ip_conntrack),
#tail /proc/net/ip_conntrack
,则会看到类似的消息:tcp 6 117 SYN_SENT src=192.168.1.6 dst=192.168.1.9 sport=32775
dport=22 [UNREPLIED] src=192.168.1.9 dst=192.168.1.6 sport=22
dport=32775 [ASSURED] use=2
conntrack 模块维护的所有信息 (实际出现的信息中,ASSURED 与 UNREPLIED / SYN_SENT 并不同时出现) 都包含在这个例子中了,通过塔可以知道特定的连接处在何种状态。
首先显示的是协议,这里是 TCP,接着是十进制的 6 (TCP 协议类型代码是 6),之后的 117 是这条 conntrack 的生存时间,它会被由规律的消耗,直到收到这个连接的更过的包;此时,这个值就被设为当时那个状态的缺省值。接下来的是这个连接在当前时间点的状态。上面的例子说明这个包处在状态 SYN_SENT,这个值是 iptables 显示的,以便我们好理解,而内部用的值稍有不同。SYN_SENT 说明我们正在观察的这个连接只在一个方向发送了一 TCP SYN 包。再下面是源地址、目的地址、源端口和目的端口。其中有个特殊的词 UNREPLIED,说明这个连接还没有收到任何回应。最后,是希望接收的应答包的信息,他们的地址和端口和前面是相反的。
当连接出现双向流量的时候,conntrack 会擦除 [UNREPLIED] 标志,然后重置它。这个名词 ([UNREPLIED]) 告诉我们还没有建立双向连接,建立连接后,它将会被末尾的 [ASSURED] 替代。
[ASSURED] 表示当连接跟踪表满时,这条记录不会被擦除。
首先显示的是协议,这里是 TCP,接着是十进制的 6 (TCP 协议类型代码是 6),之后的 117 是这条 conntrack 的生存时间,它会被由规律的消耗,直到收到这个连接的更过的包;此时,这个值就被设为当时那个状态的缺省值。接下来的是这个连接在当前时间点的状态。上面的例子说明这个包处在状态 SYN_SENT,这个值是 iptables 显示的,以便我们好理解,而内部用的值稍有不同。SYN_SENT 说明我们正在观察的这个连接只在一个方向发送了一 TCP SYN 包。再下面是源地址、目的地址、源端口和目的端口。其中有个特殊的词 UNREPLIED,说明这个连接还没有收到任何回应。最后,是希望接收的应答包的信息,他们的地址和端口和前面是相反的。
当连接出现双向流量的时候,conntrack 会擦除 [UNREPLIED] 标志,然后重置它。这个名词 ([UNREPLIED]) 告诉我们还没有建立双向连接,建立连接后,它将会被末尾的 [ASSURED] 替代。
[ASSURED] 表示当连接跟踪表满时,这条记录不会被擦除。
- TCP – 有状态协议
- 连接的建立
- 一个 TCP 连接是经过三次握手协商才建立起来。整个会话由一个 SYN 包开始,然后是一个 SYN/ACK 包,最后是一个 ACK 包。此时,会话才建立成功,能够发送数据。
- 连接的关闭
- 一般情况下,在发出最后一个 ACK 包之前,连接 (双向连接) 是不会关闭。
- 连接关闭后,进入 TIME_WAIT 状态,缺省时间是两分钟 (这个时间存在的原因是为了让数据包通过各种规则的检查、通过拥挤的路由器,从而到达目的地)。
- 如果一个包是被 RST 重置的,就直接变为 CLOSE 了。RST 包是不需要确认的,它会直接关闭连接。
Ubuntu 16.04.1 LTS 下,TCP 连接建立时 conntrack 显示的信息
[NEW] tcp 6 120 SYN_SENT src=192.168.0.3 dst=104.236.143.213 sport=53630 dport=80 [UNREPLIED] src=104.236.143.213 dst=192.168.0.3 sport=80 dport=53630
[UPDATE] tcp 6 60 SYN_RECV src=192.168.0.3 dst=104.236.143.213 sport=53630 dport=80 src=104.236.143.213 dst=192.168.0.3 sport=80 dport=53630
[UPDATE] tcp 6 432000 ESTABLISHED src=192.168.0.3 dst=104.236.143.213 sport=53630 dport=80 src=104.236.143.213 dst=192.168.0.3 sport=80 dport=53630 [ASSURED]
内部状态
State | Timeout value |
---|---|
NONE | 30 minutes |
ESTABLISHED | 5 days |
SYN_SENT | 2 minutes |
SYN_RECV | 60 seconds |
FIN_WAIT | 2 minutes |
TIME_WAIT | 2 minutes |
CLOSE | 10 seconds |
CLOSE_WAIT | 12 hours |
LAST_ACK | 30 seconds |
LISTEN | 2 minutes |
这些值并不是绝对的,它们可能随着内核版本的变化而变化,当然也可以通过修改 proc file-system 里面的系统来修改。
- UDP – 无状态协议
- 尽管 UDP 无状态,因为它没有任何连接建立和关闭的过程,而且大部分是无序列号的。但内核仍然可以对 UDP 连接设置状态。
- UDP 连接的状态
IMCP 一个非常重要的作用是告诉 UDP / TCP 连接或正在建立的连接发生了什么,这时候 ICMP 的应答被认为是 RELATED 的。上图的主机不可达 (Network Unreachable, TCP 连接) 与 网络被禁止 (Net Prohibited, UDP 连接) 就是例子。
当发送一个 SYN 包到某一地址,防火墙认为它的状态是 NEW。但是目标网络有问题不可达,路由器就会返回网络不可达的信息,这就是 RELATED 的。
当 UDP 连接遇到问题时,同样也会用响应的 ICMP 信息返回,它们的状态也是 RELATED。
当发送一个 SYN 包到某一地址,防火墙认为它的状态是 NEW。但是目标网络有问题不可达,路由器就会返回网络不可达的信息,这就是 RELATED 的。
当 UDP 连接遇到问题时,同样也会用响应的 ICMP 信息返回,它们的状态也是 RELATED。
某些情况下,连接追踪机制并不知道如何操作一些特殊的协议,尤其在它不了解这个协议或不知道这个协议如何工作的时候。这种情况下,conntrack 使用缺省操作。
缺省操作很像对 UDP 的操作:第一个包被认作 NEW,其后的应答包等数据都是 ESTABLISHED。
缺省操作很像对 UDP 的操作:第一个包被认作 NEW,其后的应答包等数据都是 ESTABLISHED。
有些协议连接跟踪机制很难正确地跟踪它们,比如 FTP,它们都在数据包的数据域里携带某些信息,这些信息用于建立其他的连接。因此需要一些特殊的 connection tracking helper 来完成这项工作。
conntrack helper 可以被静态地编译进内核,也可以作为模块,但要该命令临时加载:
注意连接跟踪并不处理 NAT,因为要对连接做 NAT 就需要增加相应的模块。
conntrack helper 的命名原则通常为
conntrack helper 可以被静态地编译进内核,也可以作为模块,但要该命令临时加载:
modprobe nf_conntrack_*
。若要开机自动加载则需要编辑 /etc/modprobe.d
文件夹下文件。注意连接跟踪并不处理 NAT,因为要对连接做 NAT 就需要增加相应的模块。
conntrack helper 的命名原则通常为
nf_conntrack_
,即 nf_conntrack_+协议
,NAT 模块的命名类似:nf_nat_
。它们的位置在 /lib/modules//kernel/net/netfilter/
。
注:
- 从这里可知:
ip_conntrack_*
已经被重命名为nf_conntrack_*
。 - 这里指出低于 2.6.19 (包括 2.6.19) 版本的内核,helper 与 nat 模块的位置在
/lib/modules/
。/kernel/net/ipv4/netfilter/
抄还是不抄?这是一个问题。
已经写 (抄) 了三天啦,了解了工作原理,语法也就不是那么重要了…
书写规则的语法就这么一句
1
| iptables [-t table] command [match] [target/jump]
|
- [-t table]
- 可选的参数,默认为 filter
- command
- 那么多种,常用的也就那几个,
man iptables
好啦 --modprobe
– 探测并装载所使用的模块-v, --verbose
- 可用的选项与命令:
--list, --append, --insert, --delete, --replace
- 这个选项使输出详细化。与
--list
连用时,输出中包括网络接口的地址、规则的选项、TOS 掩码、字节和包计数器,其中计数器是以 K、M、G (这里用的是 10 的幂而不是 2 的幂哦) 为单位的。如果想知道到底有多少个包、多少字节,还要用到选项-x,--exact(精确的)
。如果-v
和--append,--insert,--delete,--replace
连用,iptables 会输出详细的信息告诉你规则是如何被解释的、是否正确地插入等等
- 可用的选项与命令:
- 那么多种,常用的也就那几个,
- [match]
- 通用匹配: -p /-s/-d /-i/-o /-f,–fragment (匹配被分片的包的第二片或及以后的部分)
- 隐含匹配
- 这种匹配操作是自动或隐含地装载入内核的。例如我们使用
--protocol
tcp 时,不需再装入任何东西就可以匹配只有 IP 包才有的一些特点。 - TCP matches
- –sport / –dport
- 不指定此选项,则暗示所有端口
- 使用服务名或端口号,但名字必须是在
/etc/services
中定义 - 可以使用连续的端口,如
--source-port 20:80
- 可以省略第一个端口号,默认为 0,如
--source-port :80
- 可以省略第二个端口号,默认为 65535
- 在端口号前加
!
表示取反 (注意空格),如--source-port ! 22 / --source-port ! 22:80
- 注意:这个匹配操作不能识别不连续的端口列表,如
--source-port ! 22,36,80
。这样的操作需要多端口匹配扩展来完成
- –tcp-flags
- 匹配特定的 TCP 标记
- –sport / –dport
- UDP matches
- –sport / –dport
- ICMP matches
- –icmp-type
- SCTP matches
- Stream Control Transmission Protocol
- 这种匹配操作是自动或隐含地装载入内核的。例如我们使用
- 显式匹配
- 显式匹配必须用
-m,--match
装载 - addrtype match
- aH/ESP match
- comment match
- connmark match
- conntrack math
- 连接追踪匹配
- –ctstate
- INVALID / ESTABLISHED / NEW / RELATED / SNAT / DNAT
- 比如
iptables -A INPUT -p tcp -m conntrack --ctstate RELATED
- –ctproto
- 匹配协议
- –ctorigsrc
- conntrack origin source
- IP 或 网段
- –ctorigdst
- conntrack origin destination
- –ctreplsrc
- conntrack replace source
- –ctrepldst
- conntrack replace destination
- –ctstatus
- NONE / EXPECTED / SEEN_REPLY / ASSURED
- –ctexpire
- conntrack expiration timer,单位秒
- dscp match
- ecn match
- hashlimit match
- helper match
- contrack helper
- IP range match
- –src-range
iptables -A INPUT -p tcp -m iprange --src-range 192.168.1.13-192.168.2.19
- –dst-range
- –src-range
- length match
- limit match
- limit match 的工作方式就像一个单位大门口的保安,当有人要进入时,需要找他办理通行证。早上上班时,保安手里有一定数量的通行证,来一个人,就签发一个,当通行证用完后,再来人就进不去了,但他们不会等,而是到别的地方去 (在 iptables 里,这相当于一个包不符合某条规则,就会由后面的规则来处理,如果都不符合,就由缺省的策略处理)。但有个规定,每隔一段时间保安就要签发一个新的通行证。这样,后面来的人如果恰巧赶上,也就可以进去了。如果没有人来,那通行证就保留下来,以备来的人用。如果一直没人来,可用的通行证的数量就增加了,但不是无限增大的,最多也就是刚开始时保安手里有的那个数量。也就是说,刚开始时,通行证的数量是有限的,但每隔一段时间 就有新的通行证可用。limit match 有两个参数就对应这种情况,–limit-burst 指定刚开始时有多少通行证可用,–limit 指定要隔多长时间才能签发一个新的通行证。要注意的是,我这里强调的是 “签发一个新的通行证”,这是以 iptables 的角度考虑的。在你自己写规则时,就要从这个角度考虑。比如,你指定了 –limit 3/minute –limit-burst 5,意思是开始时有 5 个通行证,用完之后每 20 秒增加一个 (这就是从 iptables 的角度看的,要是以用户的角度看,说法就是每一分钟增加三个或者每分钟只能过三个)。
- –limit
- 为 limit match 设置最大平均匹配速率
- 数值 / 时间
- 时间单位 second /minute/hour /day
- 默认值 3/hour
- –limit-burst
- 定义的是 limit match 的峰值,就是在单位时间内最多可匹配几个包
- 默认值 5
- mac match
- –mac-source
- mark match
- multiport match
- –source-port
iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110
- –destination-port
- –port
- source port + destination port
- –source-port
- owner match
- –cmd-owner / –uid-owner / –gid-owner / –pid-owner / –sid-owner
- racket type match
- realm match
- recent match
- state match
- –state
- INVALID / ESTABLISHED / NEW / RELATED
- –state
- tcpmss match
- tos match
- ttl match
- unclean match
- 显式匹配必须用
- [target/jump]
- 决定符合条件的包到何处去
- jump
- 目标是一个在同一个表内的链
- 一个例子
- 比如在 filter 表中建立一个名为 tcp_packets 的链
iptables -N tcp_packets
- 然后把它作为 jump 的目标
iptables -A INPUT -p tcp -j tcp_packets
- 比如在 filter 表中建立一个名为 tcp_packets 的链
- target
- 目标是一个具体的操作
- ACCEPT target
- CLASSIFY target
- CLUSTERIP target
- CONNMARK target
- CONNSECMARK target
- DNAT target
- –to-destination
--to-destination 192.168.1.1
--to-destination 192.168.1.1-192.168.1.10
--to-destination 192.168.1.1:80
--to-destination 192.168.1.1:80-100
- 只有指定 TCP 或 UDP 协议才能指定端口
- –to-destination
- DROP target
- DSCP target
- ECN target
- LOG target
- –log-level
- debug / info / notice / warning / warn / err / error / crit / alert / emerg / panic
- –log-prefix
- 添加的前缀
- –log-tcp-sequence
- 把包的 TCP 序列号和其他日志信息一起记录下来
- –log-tcp-options
- 记录 TCP 包头中的不同的选项
- –log-ip-options
- 记录 IP 包头中的选项
- –log-level
- MARK target
- MASQUERADE target
- –to-ports
- 指定 TCP 或 UDP 前提下,设置外出包可使用的端口
--to-ports 1025
--to- ports 1024-3000
- MIRROR target
- NETMAP target
- SNAT / DNAT 的新实现,提供了对整个私有网络 1:1 的 NAT 转换功能
- –to
iptables -t mangle -A PREROUTING -s 192.168.1.0/24 -j NETMAP --to 10.5.6.0/24
- NFQUEUE target
- NOTRACK target
- QUEUE target
- REDIRECT target
- –to-ports
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
- REJECT target
- 与 DROP 的区别在于除了阻塞包之外,还向发送者返回错误信息
- –reject-with
- icmp-net-unreachable / icmp-host-unreachable / icmp-port-unreachable / icmp-proto-unreachable / icmp-net-prohibited / icmp-host-prohibited
- 默认 port-unreachable
- RETURN target
- SAME target
- 功能与 SNAT 差不多。不同之处:
iptables -t mangle -A PREROUTING -s 192.168.1.0/24 -j SAME --to 10.5.6.7-10.5.6.9
- 一个 /24 网段,3 个 IP 地址。如果 192.168.1.20 第一次通过 10.5.6.7 的 IP 地址,那么随后的包也会通过这个地址
- –to
- 功能与 SNAT 差不多。不同之处:
- SECMARK target
- SNAT target
- –to-source
- TCPMSS target
- TOS target
- TTL target
- ULOG target
Step | Table | Chain | Comment (注释) |
---|---|---|---|
1 | 在线路上传输 (比如 Internet) | ||
2 | 进入接口 (比如 eth0) | ||
3 | raw PREROUTING | 连接追踪 (connection tracking) 起作用前,这条链起作用。例如,它被用于设置一个特定的连接,这条连接不被连接跟踪代码处理 | |
4 | 这是当连接跟踪代码起作用的时候,它将会在 The state machine 讨论 | ||
5 | mangle | PREROUTING | 这条链通常被用于对特定数据包修改 (比如,改变 TOS 等) |
6 | nat | PREROUTING | 这个链主要用来做 DNAT。不要在这个链做过滤操作,因为某些情况下包会溜过去 |
7 | 路由判断 (比如,包是发往本地的,还是需要被转发的) | ||
8 | mangle | INPUT | 在路由之后,被送往本地程序之前,在这里对特定数据包修改 |
9 | filter | INPUT | 所对这些包的过滤条件就设在这里。有以本地为目的的数据包都要经过这个链,不管他们从哪里来 |
10 | 到达本地进程或应用了 (比如服务程序或客户程序) |
(作者认为,由图可知,7 与 8 应该互换位置)
Step | Table | Chain | Comment (注释) |
---|---|---|---|
1 | 本地进程 / 应用 (比如服务程序或客户程序) | ||
2 | 路由判断:要使用哪个源地址 (source ip)、外出接口 (eth0 之类),还有其他一些信息 | ||
3 | raw | OUTPUT | 对于本地生成的包,在连接追踪起作用前,这里是你可以做工作的的地方。例如,你可以为连接做标记以便它们不会被追踪 |
4 | 对本地生成的包,这里是连接追踪起作用的地方。比如状态的改变等等。它将会在 The state machine 讨论 | ||
5 | mangle | OUTPUT | 在这可以对特定数据包修改。建议不要在这做过滤,可能有副作用哦 |
6 | nat | OUTPUT | 这个链对从防火墙本身发出的包进行 DNAT 操作 |
7 | 路由判断:因为先前的 mangle 与 cat 可能改变了数据包的路由信息 | ||
8 | filter | OUTPUT | 对本地发出的包过滤 |
9 | mangle | POSTROUTING | 在离开主机之前,决定对包进行怎样的处理。两种包会经过这里:防火墙自身产生的包、被转发的包 |
10 | nat | POSTROUTING | 在这里做 SNAT。但不要在这里做过滤,因为有副作用,而且有些包是会溜过去的,即使你用了 DROP 策略 |
11 | 离开接口 (比如: eth0) | ||
12 | 在线路上传输 (比如,Internet) |
Step | Table | Chain | Comment |
---|---|---|---|
1 | 在线路上传输 (比如,Internet) | ||
2 | 进入接口 (比如, eth0) | ||
3 | raw | PREROUTING | 这里可以进行设置不被连接追踪的操作 |
4 | 这里是非本地连接产生连接追踪的地方,这也会在 The state machine 章节讨论 | ||
5 | mangle | PREROUTING | 修改数据包,比如改变 TOS 等 |
6 | nat | PREROUTING | 这个链主要用来做 DNAT。不要在这个链做过虑操作,因为某些情况下包会溜过去。稍后会做 SNAT |
7 | 路由判断,比如,包是发往本地的,还是要转发的 | ||
8 | mangle | FORWARD | 包继续被发送至 mangle 表的 FORWARD 链。当我们希望在最初的路由之后、数据包发出前的下一个路由之前修改数据包才需要 |
9 | filter | FORWARD | 包继续被发送至这条 FORWARD 链。只有需要转发的包才会走到这里,并且针对这些包的所有过滤也在这里进行。注意,所有要转发的包都要经过这里,不管是外网到内网的还是内网到外网的。在你自己书写规则时,要考虑到这一点 |
(作者个人认为有必要加上这行:由图可知,这里是路由决策) | |||
10 | mangle | POSTROUTING | 这个链也是针对一些特殊类型的包 (译者注:参考第 8 步,我们可以发现,在转发包时,mangle 表的两个链都用在特殊的应用上)。这一步 mangle 是发生在所有路由判断结束之后,但此时包还在本地上 |
11 | nat | POSTROUTING | 这个链就是用来做 SNAT 的,当然也包括 Masquerade (伪装)。但不要在这儿做过滤,因为某些包即使不满足条件也会通过 |
12 | 离开接口 (比如: eth0) | ||
13 | 又在线路上传输了 (比如,LAN) |
主要的资料来源于下面的两本《Iptables Tutorial》。中文版比较旧,而英文版也有一些错误。还参考了鸟哥与 ArchLinux 文档。
讲真,ArchLinux 文档基本概念部分介绍得不错,但是竟然也有错的 =_= 渣翻译,嫌弃.jpg (于是我把 遍历链 (Traversing Chains) 部分给修改了下,改正了一些错误,添加上自己的理解。虽然我翻译得也渣…)
讲真,ArchLinux 文档基本概念部分介绍得不错,但是竟然也有错的 =_= 渣翻译,嫌弃.jpg (于是我把 遍历链 (Traversing Chains) 部分给修改了下,改正了一些错误,添加上自己的理解。虽然我翻译得也渣…)
No comments:
Post a Comment