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命令格式如下:
| 12
 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: 其他特殊选项信息
这里简单的介绍下参数选项信息:
| 12
 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  处理分片包时, 只处理第二以及之后的片
 
 | 
其他选项信息:
| 12
 3
 4
 
 | -v      详细输出-n      数字形式输出
 -x      显示包和字节计数器的精确值
 --line-numbers      当列表显示规则时, 在每个规则的前面加上行号(规则在链中位置)
 
 | 
安装配置
- 重启, 停止, 打开防火墙: /etc/init.d/iptables start/stop/restart
- 永久性关闭/打开防火墙
| 12
 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操作
| 12
 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. 默认情况下, 查询规则时都是基于表去查找当前拥有的链路和规则信息的, 即上面信息的相反对应关系.
数据流
数据经过防火墙的数据流图如下:
| 12
 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. 命令
查询命令
| 12
 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命令规则添加
| 12
 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
 
 | 
- 删除规则命令, 指定序号或者根据匹配条件/动作进行删除
| 12
 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
 
 | 
- 更改规则
| 12
 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或者重启服务器之后都会重置
| 12
 3
 4
 5
 6
 
 | service iptables save
 
 iptables-save > /etc/iptables.rules
 
 iptables-restore < /etc/sysconfig/iptables
 
 | 
匹配条件
上面规则命令中都涉及到包的匹配逻辑, 那么匹配条件都有哪些呢? 除了源地址还有哪些匹配条件?
- 指定源地址(单个或者多个)
| 12
 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 情况)
| 12
 
 | iptables -t filter -I INPUT -d 192.168.0.103 -p icmp -j DROP
 
 | 
- 协议类型
| 12
 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
 
 | 
- 网卡接口
| 12
 3
 4
 
 | iptables -t filter -I INPUT -i eth0 -p icmp -j DROP
 
 iptables -t filter -O OUTPUT -o eth0 -p icmp -j DROP
 
 | 
- 指定源端口和目的端口(扩展匹配条件)
| 12
 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地址范围, 用于匹配源地址, 目标地址
| 12
 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: 指定匹配的字符串, 用于报文全文匹配, 需要指定匹配算法
| 12
 
 | iptables -t filter -I INPUT -m string --algo bm --string "bifeng" -j REJECT
 
 | 
- time: 根据时间段匹配报文, 报文如果在该时间段内达到或者发出, 则设置规则
| 12
 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 连接限制
| 12
 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, 对报文到达速率进行限制, 限制单位时间内流入包数量
| 12
 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
有如下两台机器:
| 12
 3
 4
 5
 
 | # 1. 其中, 通过mac ping Ubuntumac(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上设置如下信息:
| 12
 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
 
 | 
输出如下:
| 12
 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通目标主机呢?
| 12
 3
 4
 
 | iptables -A INPUT -p icmp -s 192.168.0.100 -j ACCEPT
 
 iptables -nvL INPUT
 
 | 
输出如下:
| 12
 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
 
 | 
让我们再次增加一条新规则, 现在将规则插入到链首部
| 12
 3
 4
 5
 6
 
 | iptables -I INPUT -p icmp -s 192.168.0.100 -j ACCEPT
 
 iptables --line-number -nvL INPUT
 
 iptables -nvL INPUT
 
 | 
输出如下:
| 12
 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查看链上各个规则的顺序, 如果希望新增加的
规则在中间插入, 只需要指定序号即可:
| 12
 
 | iptables -t filter -I INPUT 1 -p icmp -s 192.168.0.100 -j DROP
 
 | 
白名单机制
默认情况下, 所有链的策略都是ACCEPT, 新增加的链规则都是 DROP, REJECT, 这就是黑名单机制,这导致上面的频率限制等会出现问题, 未匹配的规则实际上默认还是走了 ACCEPT, 所以上面所有命令的!操作都有点怪.
我们可以设置白名单方式, 将所有链的默认规则设置为DROP, 在一个个增加相应规则, 确保所有流量都在自己的控制范围之内, 但是如果直接将所有链规则设置为DROP, 有时候可能导致一个问题, 当不小心清除所有链规则时, 好了, 管理员自己无法连接远程服务器了, 所以最好的白名单方式:
- 最好在每一个链的末尾增加一个REJECT 规则即可
业务场景
| 12
 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
 
 | 
查看当前防火墙允许接受的所有协议(或者端口号)
| 12
 3
 4
 5
 6
 7
 8
 
 | /etc/init.d/iptables status
 或者
 iptables -L
 
 
 -> 如果没有显示防火墙规则,则表示没有设置防火墙策略;
 -> 即使服务器运行,如果防火墙规则没有设置,则iptables处于"无效状态"
 
 | 
临时打开指定的端口: iptables -A INPUT -p tcp --dport 21 -j ACCEPT
引用