ipfw介绍
功能
根据文档可知, iptables实际上就是一个ip包过滤管理器, 结合之前做过的防火墙经验(modsecurity), 实际上就是一个本地防火墙, 认真研究iptables命令文档, 你会发现它的实际逻辑和防火墙是真的非常像.
- 通过定义一系列的规则链条来进行数据的防护, 每一种类型的链条处理不同的数据
- input(入包), forword(通过包), output(本地生成包), 类似waf上请求响应的规则处理
- 在完成基本包过滤基础上增加一个额外的包修改, 包转发等功能
iptables本身仅仅是一个客户端代理, 一个命令行工具, 只有将一些安全设置指定到对应的安全框架中, 此时其和安全框架共同组成了防火墙, 这个安全框架叫netfilter. netfilter算是主机防火墙或者软件防火墙, 而waf等是网络防火墙或硬件防火墙, 前者主要实现下面三个功能:
- 网络地址转发
- 数据包内容修改
- 数据包过滤
iptables通过链概念, 表分类, 规则等概念, 并结合前两者实现了数据的处理, 这些概念会在后面提及, 这里先简单的介绍下表, 链, 规则的关系:
- 每一个表包含内部链, 也可以包含用户自定义链
- 每一个链是一个规则列表, 对相应包进行pattern(模式匹配)和action
- 每条规则定义了如何处理相匹配的包, 这被称为target(action)
- 每一条链可以被多个表关联.
让我们将功能和上面术语结合在一起:
- 涉及包内容过滤时: 使用INPUT/OUTPUT 链来进行ACCEPT, REJEST, DROP.
- 涉及包转发时: 使用PREROUTING, FORWARD, POSTROUTING链来进行包转发
注意, 并非所有的链组合成一个串行结构, 可能是条件结构, 并行结构等, 例如:
- 进入本机报文经过链: PREROUTING->INPUT
- 经由本机转发报文: PREROUTING -> FORWARD -> POSTROUTING
- 本机发出的报文: OUTPUT -> POSTROUTING
命令
iptables命令格式如下:
1 2 3 4 5 6 7 8
| iptables -[ACD] chain rule-specification [options], [A-append D-删除 C-check] iptables -I chain [rulenum] rule-specification [options] (I-插入) iptables -R chain rulenum rule-specification [options] (替换) iptables -D chain rulenum [options] (Delete, 可以将删除的规则指定为链中的序号) iptables -LFZ 链名 [选项] (L-显示所有链规则, 默认所有链所有规则, F-清空, Z-清空链中所有计数器) iptables -[NX] 指定链 (N-new chain, 创建新链, X-delete chain, 删除用户自定义链, 被引用无法删除) iptables -P chain target [options] (P-设置链目标规则) iptables -E old-chain-name new-chain-name (E-rename chain, 重命名链)
|
整体命令格式可以总结如下: iptables [CMD] rulenum [options], 其中CMD就是上面所述, 其本身也归属于options, 下面简单的介绍一下options.
options
- commands: 这些选项指定执行明确的动作, 一般而言, 只能指定一个选项
- paramater: 使用参数指定一个特定的规则, 常常用于add, delete, replace, append, check等命令中.
- other: 其他特殊选项信息
这里简单的介绍下参数选项信息:
1 2 3 4 5 6 7
| -p [!] protocol 指定规则或包检查准备处理的协议类型, 可以是协议号或者协议名, !表示相反规则, 0 表示所有 -s [!] address[/mask] 指定source address, 可以是主机,网络名,IP 名 -d [!] address[/mask] 指定目标address -j target 指定规则target(类似action, 见下文介绍) -i [!] name 指定包进入或转发的网络接口名, 指定后包从该接口进入 -o [!] name 指定包出口 [!] -f 处理分片包时, 只处理第二以及之后的片
|
其他选项信息:
1 2 3 4
| -v 详细输出 -n 数字形式输出 -x 显示包和字节计数器的精确值 --line-numbers 当列表显示规则时, 在每个规则的前面加上行号(规则在链中位置)
|
安装配置
- 重启, 停止, 打开防火墙:
/etc/init.d/iptables start/stop/restart
- 永久性关闭/打开防火墙
1 2 3 4 5 6 7 8
| chkconfig --level 35 iptables off /etc/init.d/iptables stop iptables -P INPUT DROP
chkconfig --list chkconfig --level 235 iptables on
|
- centos下iptables操作
1 2 3 4 5 6 7 8 9 10 11 12 13
| systemctl stop firewalld.service systemctl disable firewalld.service yum install iptables-services systemctl enable iptables
systemctl status iptables.service systemctl stop iptables.service systemctl status iptables.service
service iptables restart
|
开启端口: vim /etc/sysconfig/iptables, 之后增加端口到相应文件中
链和表
链
链包含内部定义链和用户自定义链, 每个链都是一系列的规则, 不同的链在不同的关卡中进行着不同的包过滤检查机制, 内部定义链:
- prerouting (经由路由, 公网进入当前内网时)
- input
- output
- forward
- postrouting (经由路由, 内网通往外网时)
自定义链条不能单独使用, 其需要被某个默认的链条当做target调用之后才能作为默认链的某一个补充来进行包处理.
表
将具有相同功能的规则聚集在一起, 形成table, 这是一个逻辑概念, 从而高效的进行表的管理, 实际进行包过滤的时候还是基于链来完成, 当然链中的每一条规则则归属于不同的table. 目前有四种功能的表:
- filter表: 负责包过滤, 实现防护墙机制
- nat表: 网络地址转发
- mangle表: 包修改和重新封装
- raw表: 关闭nat表上启用的连接追踪机制
其中过滤功能有:
- 哪些 IP 可访问
- 哪些 IP 不能访问
- 允许哪些端口
- 禁止访问特定端口
一般而言, 用户自定义链中的规则在特定的table中
- prerouting: raw, mangle, nat表, 路由上也一般不做包过滤, 仅做包转发
- input: mangle, filter, nat表
- output: mangle, filter, nat, raw表
- forward: mangle, filter表
- postrouting: mangle, nat表
另外, 默认情况下, 每一个链中的不同表规则存在优先级问题, 一般来说: raw > mangle > nat > filter. 默认情况下, 查询规则时都是基于表去查找当前拥有的链路和规则信息的, 即上面信息的相反对应关系.
数据流
数据经过防火墙的数据流图如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ┌────────────────────────────┐ │ protocol stack │ └─▲────────────────────────┬─┘ │ │ │ │ │ │ ┌──┴──┐ ┌───▼──┐ raw mangle │input│ │output│ mangle nat └──▲──┘ └───┬──┘ nat filter │ │ filter │ │ │ │ │ │ │ │ ┌───────────┐ │ ┌───────┐ │ ┌───────────┐ ─────►prerouting ├────┴─────────►forward├──────┴────────►postrouting├─────► └───────────┘ route └───────┘ └───────────┘ raw mangle mangle mangle filter nat nat ───────────────────────────────────────────────────────────────────►
|
另外, 如果在 LINUX 上想要主机支持转发功能, 需要内核开启IP_FORWARD 功能.
规则结构
类似modsecurity防护策略一样, 链表内的规则也是由pattern和action组成.
- 匹配条件: 分为基本匹配条件和扩展匹配条件
- 基本匹配条件: 源地址Source IP, 目标地址Destination IP
- 扩展匹配条件: 例如源端口, 目的端口等
- 处理动作: 在iptables中称为target, 动作称为基本动作和扩展动作
- ACCEPT: 允许数据包通过
- DROP: 丢包
- REJECT: 拒绝
- SNAT: 源地址转换, 解决内网用户用同一个公网地址上网的问题
- MASQUERADE: SNAT的一种特殊形式, 用于动态,临时 IP 上
- DNAT: 目标地址转换
- REDIRECT: 本地端口映射
- LOG: 记录日志并传递给下一条规则
3. 命令
查询命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| iptables -t filter -L iptables -t raw -L iptables -t mangle -L iptables -t nat -L
iptables -L
iptables -L INPUT
iptables -vL INPUT
iptables -nvL INPUT
iptables --line-number -nvL INPUT
iptables -F INPUT
|
输出项
当命令中包含-v时会输出详细的规则信息:
- pkts: 该规则匹配到的包数量
- bytes: 该规则匹配到的报文总大小
- target: 规则对应的动作
- prot: 规则对应的协议
- opt: 规则对应的选项
- in: 数据包由哪个网卡流入
- out: 数据包由哪个网卡流
- source: 规则对应的源地址, 例如 IP, 网段, 默认显示anywhere, 名称解析
- destination: 规则对应的目的地址, 例如 IP, 网段, 默认为anywhere
处理这些输出信息之外, 在头部还有一些计数信息, 表示策略, 所有包统计信息
- policy ACCEPT: 当前链的默认策略, 这里表示通过
- packets: 当前链默认策略匹配到的包的数量
- bytes: 当前链默认策略匹配到的所有包的大小总和
工作场景 1: 禁止某个IP地址访问我们的主机
配置: 需要在 INPUT 链上定义规则, 根据 2.3 的数据流可以知道进入本机的数据
包流量会经过 PREROUTING和INPUT 链处理, 但是PREROUTING链不存在filter表中的
规则, 即天生不支持过滤, 所以只能在 INPUT 中定义.
规则操作
- 增加规则命令, 具体例子可见4.1节中的ping命令规则添加
1 2 3 4 5 6
| iptables -t filter -I INPUT -p icmp -s 192.168.0.100 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 23 -s 192.168.0.100 -j DROP
iptables -t filter -I INPUT 2 -p telnet -s 192.168.0.100 -j ACCEPT
|
- 删除规则命令, 指定序号或者根据匹配条件/动作进行删除
1 2 3 4 5 6
| iptables -t filter -D INPUT 2
iptables -t filter -D INPUT -s 192.168.0.100 -j DROP -p tcp -dport 23
iptables -t filter -F
|
- 更改规则
1 2 3 4
| iptables -t filter -R INPUT 1 -s 192.168.0.100 -p tcp --dport 23 -j REJECT
iptables -t filter -P FORWARD DROP
|
- 保存规则, 默认情况下上面的命令在重启iptables或者重启服务器之后都会重置
1 2 3 4 5 6
| service iptables save
iptables-save > /etc/iptables.rules
iptables-restore < /etc/sysconfig/iptables
|
匹配条件
上面规则命令中都涉及到包的匹配逻辑, 那么匹配条件都有哪些呢? 除了源地址还有哪些匹配条件?
- 指定源地址(单个或者多个)
1 2 3 4 5 6 7 8 9 10
| iptables -t filter -I INPUT -s 192.168.0.100 -j DROP
iptables -t filter -I INPUT -s 192.168.0.10,192.168.0.101 -j DROP
iptables -t filter -I INPUT -s 192.168.0.0/16 -j DROP
iptables -t filter -I INPUT ! -s 192.168.0.100 -j ACCEPT
|
- 目标地址(适用于多网卡, 多 IP 情况)
1 2
| iptables -t filter -I INPUT -d 192.168.0.103 -p icmp -j DROP
|
- 协议类型
1 2 3 4 5
| iptables -t filter -I INPUT -s 192.168.0.100 -p tcp -j REJECT
iptables -t filter -I INPUT -d 192.168.0.103 -j DROP
|
- 网卡接口
1 2 3 4
| iptables -t filter -I INPUT -i eth0 -p icmp -j DROP
iptables -t filter -O OUTPUT -o eth0 -p icmp -j DROP
|
- 指定源端口和目的端口(扩展匹配条件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| iptables -t filter -I INPUT -s 192.168.0.100 -p tcp -m tcp --dport 23 -j REJECT
iptables -t filter -I INPUT -s 192.168.0.100 -p tcp --dport 23 -j REJECT
iptables -t filter -I INPUT -s 192.168.0.100 -p tcp --sport 22 -j REJECT
iptables -t filter -I INPUT -s 192.168.0.100 -p tcp --dport 22:25 -j REJECT
iptables -t filter -I INPUT -s 192.168.0.100 -p tcp --dport 80: -j REJECT
iptables -t filter -I INPUT -s 192.168.0.100 -p tcp -m multiport --dport 22,36,80 -j REJECT
|
扩展模块
除了上面讲解的基本扩展模块用于扩展匹配条件, 还有很多其他扩展模块极大的丰富了iptables的功能.
- iprange: 一段连续的ip地址范围, 用于匹配源地址, 目标地址
1 2 3 4
| iptables -t filter -I INPUT -m iprange --src-range 192.168.0.100-192.168.0.105 -j DROP
iptables -t filter -I INPUT -m iprange --dst-range 192.168.0.100-192.168.0.105 -j DROP
|
- string: 指定匹配的字符串, 用于报文全文匹配, 需要指定匹配算法
1 2
| iptables -t filter -I INPUT -m string --algo bm --string "bifeng" -j REJECT
|
- time: 根据时间段匹配报文, 报文如果在该时间段内达到或者发出, 则设置规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 \ --timestop 12:00:00 -i REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays Mon,Tue -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 \ --timestop 12:00:00 --weekdays 6,7 -i REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --datestart 2021-05-01 \ --datestart 2021-05-05 -j REJECT
|
- connlimit: 限制每一个 IP地址同时连接到server端的数量, 默认所有客户端 IP, 单 IP 连接限制
1 2 3 4
| iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-mask 24 -j REJECT
|
- limit: 类似connlimit, 对报文到达速率进行限制, 限制单位时间内流入包数量
1 2 3
| iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT iptables -t filter -A INPUT -p icmp -j REJECT
|
配置和实例
阻止ping
有如下两台机器:
1 2 3 4 5
| # 1. 其中, 通过mac ping Ubuntu mac(192.168.0.100) --> ubuntu(192.168.0.103) # 2. 查看ubuntu防火墙上的收到的包信息(iptables -nvL INPUT) Chain INPUT (policy ACCEPT 1854 packets, 992K bytes) pkts bytes target prot opt in out source destination
|
现在, 如果希望仅仅mac所在 IP 访问当前机器, 可以在ubuntu上设置如下信息:
1 2 3 4 5 6 7 8 9 10
|
iptables -t filter -I INPUT -s 192.168.0.100 -j DROP
iptables -t filter -I INPUT -p ICMP -s 192.168.0.100 -j DROP
iptables -nvL INPUT
|
输出如下:
1 2 3
| Chain INPUT (policy ACCEPT 92 packets, 6584 bytes) pkts bytes target prot opt in out source destination 76 6384 DROP icmp -- * * 192.168.0.100 0.0.0.0/0
|
链顺序
在 4.1 中我们增加了一个DROP动作的规则, 那么如果我们在该规则的后面再添加一条ACCEPT
的规则, 那么是否可以ping通目标主机呢?
1 2 3 4
| iptables -A INPUT -p icmp -s 192.168.0.100 -j ACCEPT
iptables -nvL INPUT
|
输出如下:
1 2 3 4
| Chain INPUT (policy ACCEPT 62 packets, 4483 bytes) pkts bytes target prot opt in out source destination 6476 544K DROP icmp -- * * 192.168.0.100 0.0.0.0/0 0 0 ACCEPT icmp -- * * 192.168.0.100 0.0.0.0/0
|
让我们再次增加一条新规则, 现在将规则插入到链首部
1 2 3 4 5 6
| iptables -I INPUT -p icmp -s 192.168.0.100 -j ACCEPT
iptables --line-number -nvL INPUT
iptables -nvL INPUT
|
输出如下:
1 2 3 4 5
| Chain INPUT (policy ACCEPT 102 packets, 6504 bytes) pkts bytes target prot opt in out source destination 12 1008 ACCEPT icmp -- * * 192.168.0.100 0.0.0.0/0 6581 553K DROP icmp -- * * 192.168.0.100 0.0.0.0/0 0 0 ACCEPT icmp -- * * 192.168.0.100 0.0.0.0/0
|
所以规则的顺序非常重要, 可以使用--line-number查看链上各个规则的顺序, 如果希望新增加的
规则在中间插入, 只需要指定序号即可:
1 2
| iptables -t filter -I INPUT 1 -p icmp -s 192.168.0.100 -j DROP
|
白名单机制
默认情况下, 所有链的策略都是ACCEPT, 新增加的链规则都是 DROP, REJECT, 这就是黑名单机制,这导致上面的频率限制等会出现问题, 未匹配的规则实际上默认还是走了 ACCEPT, 所以上面所有命令的!操作都有点怪.
我们可以设置白名单方式, 将所有链的默认规则设置为DROP, 在一个个增加相应规则, 确保所有流量都在自己的控制范围之内, 但是如果直接将所有链规则设置为DROP, 有时候可能导致一个问题, 当不小心清除所有链规则时, 好了, 管理员自己无法连接远程服务器了, 所以最好的白名单方式:
- 最好在每一个链的末尾增加一个REJECT 规则即可
业务场景
1 2 3 4
| iptables -I INPUT -s 192.168.199.0/24 -p tcp -dport 8989 -j Accept
iptables -I INPUT -s 192.168.199.3/16 -j Drop
|
查看当前防火墙允许接受的所有协议(或者端口号)
1 2 3 4 5 6 7 8
| /etc/init.d/iptables status 或者 iptables -L
-> 如果没有显示防火墙规则,则表示没有设置防火墙策略; -> 即使服务器运行,如果防火墙规则没有设置,则iptables处于"无效状态"
|
临时打开指定的端口: iptables -A INPUT -p tcp --dport 21 -j ACCEPT
引用