PHP Repository Manager
netfilter 与 iptables
netfilter
是 linux 默认的防火墙,在 2.4 之后的版本正式进入内核。netfilter
使用四个表(Table)来存放控制信息包过滤处理的规则集。每张表由链(Chain)组成,每条链又包含了多条规则(rule)。
iptables
是用来编辑操作这些表的一个工具。iptables
包中也包含了针对 IPv6 的工具ip6tables
。
四个表及其包含的链:
- filter
- INPUT
- FORWARD
- OUTPUT
- nat
- PREROUTING
- POSTROUTING
- OUTPUT
- mangle
- PREROUTING
- INPUT
- FORWARD
- OUTPUT
- POSTROUTING
- raw
- PREROUTING
- OUTPUT
filter 机制
filter
是netfilter
中最重要的机制,其任务是执行数据包的过滤操作。具有三种内建链:
- INPUT - 来自外部的数据包(访问本机)
- OUTPUT - 发往外部的数据包(本机访问外部)
- FORWORD - “路过”本机的数据包,转发到其他设备
链中规则的匹配方式遵循first match
。filter
会根据数据包特征从相应链中的第一条规则开始逐一进行匹配。只要遇到满足特征的规则后便不再继续。
每条链在最底端都定义了默认规则。默认规则只会有一种状态:ACCEPT
或者DROP
。默认为ACCEPT
。
iptables 命令参数
格式:
iptables -操作方式 [链名] [条件匹配] [选项]
iptables -[ACD] chain rule-specification [options]
iptables -I chain [rulenum] rule-specification [options]
iptables -R chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LS] [chain [rulenum]] [options]
iptables -[FZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)
常用操作方式:
-L(--list)
[chain] 列出所有规则或指定链的规则-A(--append)
chain 在指定链中添加新规则-C(--check)
chain 检查规则是否存在-D(--delete)
chain rule_num 删除链中匹配的规则-F(--flush)
[chain] 清除指定链或者全部链中的规则-P(--policy)
chain 设置指定链的默认策略-R(--replace)
chain rule_num 替换指定链中特定行的规则,第一行行数为 1
常用选项:
-p(--protocol)
proto 指定协议,如tcp
udp
icmp
-j(--jump)
target 规则的目标(??),如ACCEPT
DROP
REJECT
-s(--source)
address[/mask] 数据包源 IP,可为单 IP 或 CIDR 网段或域名-d(--destination)
address[/mask] 数据包目的 IP,可为单 IP 或 CIDR 网段或域名--dport
port 目的端口,必须指明-p
--sport
port 来源端口,必须指明-p
--line-numbers
显示行号
关于
-p
配置的上层协议,可参考/etc/protocols
state 模块
state
模块实现了“连接跟踪”功能,用来解决某些情况下防火墙内主机对外建立链接的问题。
state
模块定义了四种数据包链接状态,分别为ESTABLISHED
NEW
RELATED
INVALID
四种。在 TCP/IP 标准的定义中,UDP 和 ICMP 数据包是没有链接状态的,但是在 state 模块的定义中,任何数据包都有连接状态。
ESTABLISHED 状态
只要数据包能够成功穿过防火墙,则之后的所有数据包(包括响应数据包)都会被标记为是ESTABLISHED
状态。
当我们设置防火墙 INPUT 链的默认策略为DROP
时,防火墙内主机很多服务,如 ssh 客户端基本上就无法与外面的 ssh 服务端建立连接了。原因很简单,ssh 客户端使用的端口是随机的,防火墙无法预知客户端会使用哪一个端口发起链接。因此即使客户端发出了请求,ssh 服务端返回的相应数据包也会被防火墙的默认策略拦截。
ESTABLISHED 状态可以很轻易的解决此问题,见#解决应用程序无法从防火墙主机上对外建立新连接的问题
NEW 状态
每一条链接中的地一个数据包的状态定义为NEW
。
RELATED 状态
RELATED
状态的数据包其含义是指,被动产成的应答数据包,且此数据包不属于当前任何链接。换一种说法就是,只要应答的数据包是因为本机发起的连接送出 vhu 一个数据包,导致了另一条连接的产生,那么这个新连接的所有数据包都属于RELATED
状态。
以 ubuntu 上上的 tracepath 工具为例,在检测本机与目的主机间跳数时,tracepath 是通过发送 TTL 值从 1 递增的tcp
数据包来检测每一跳。路径中的路由器因 TTL 减为 0 而回送了一个ICMP
数据包(ICMP Type 11),该数据包就属于 RELATED 状态。
INVALID 状态
INVALID
状态指的是状态不明的数据包,即不属于ESTABLISHED
NEW
RELATED
三种类型的数据包。所有的INVALID
数据包都应该视为恶意数据包。
实例
丢弃 icmp 协议包(禁止 ping)
通过此规则实现禁止 ping 本机的效果
iptables -A INPUT -p icmp -j DROP
解决应用程序无法从防火墙主机上对外建立新连接的问题
iptables -A INPUT -p tcp -m state ESTABLISHED -j ACCEPT