iptables - 处理数据包的工具

四表五链

四表

  • raw:关闭 nat 表上启用的连接追踪机制, 对应内核模块: iptable_raw
  • mangle:负责拆解报文, 修改及重新封装, 对应内核模块: iptables_mangle
  • nat:负责地址转换, 对应内核模块: iptables_nat
  • filter:负责过滤, 对应内核模块: iptables_filter
  • 优先级: raw --> mangle --> nat --> filter

五链

  • 分为 prerouting, input, output, forward, postrouting
  • 请求报文(到本机): --> prerouting --> input
  • 请求报文(转发): client --> prerouting --> forward --> postrouting --> 其他主机
  • 响应报文: output --> postrouting -->

链、表关系图示

image


自定义链

  • 属于 iptables 用法的一种,即和原生表有关,又和原生链有关
  • 优点:可以将规则批量操作,删除变为取消引用,降低风险,可快速恢复

使用

查看

  • -t 指定要查看的表,默认是filter
  • -n 限制为IP格式(不进行dns解析)
  • -L 指定要查看的链,默认是所有
  • -v 显示详细信息
  • -x 显示字节大小
  • --line-number 显示条目行号
# 查看 nat 表,所有链信息
iptables -t nat -L -n

# 查看 nat 表,Input 链信息
iptables -t nat -L INPUT -n

# 显示行号,常用于配合删除使用
iptables -t nat -L INPUT -n --line-numbers

添加

  • iptables -t <表名> <添加模式> <链名> [插入序号] <条件1> [<条件2>...] <动作>

  • 添加模式

    • -A 追加到顺序最后
    • -I 指定插入序号后,插入到序号位置(其余后移),未指定插入序号则插入到首位
# 追加规则“源地址为 192.168.1.4 的数据包允许通过”到nat表yang链(自定义链)
iptables -t nat -A yang -s 192.168.1.4 -j ACCEPT

# 插入规则“源地址为 192.168.1.3 的数据包允许通过”到nat表yang链(自定义链)的3号位置
iptables -t nat -I yang 3 -s 192.168.1.3 -j ACCEPT

删除

  • iptables -t <表名> <删除模式> <链名> [删除序号] [<条件1> <条件2>...]
  • 删除模式
    • -D 根据序号删除规则条目
    • -F 无需指定序号,清空指定的链或表中的所有规则
# 创建规则备用
iptables -t nat -A yang -s 192.168.1.1 -j ACCEPT
iptables -t nat -A yang -s 192.168.1.2 -j ACCEPT
iptables -t nat -A yang -s 192.168.1.3 -j ACCEPT
iptables -t nat -A yang -s 192.168.1.4 -j ACCEPT

# 根据序号删除
[root@master ~]# iptables -t nat -L yang -n --line-numbers
Chain yang (0 references)
num  target     prot opt source               destination
1    ACCEPT     all  --  192.168.1.1          0.0.0.0/0
2    ACCEPT     all  --  192.168.1.2          0.0.0.0/0
3    ACCEPT     all  --  192.168.1.3          0.0.0.0/0
4    ACCEPT     all  --  192.168.1.4          0.0.0.0/0
[root@master ~]# iptables -t nat -D yang 2

# 验证执行结果
[root@master ~]# iptables -t nat -L yang -n --line-numbers
Chain yang (0 references)
num  target     prot opt source               destination
1    ACCEPT     all  --  192.168.1.1          0.0.0.0/0
2    ACCEPT     all  --  192.168.1.3          0.0.0.0/0
3    ACCEPT     all  --  192.168.1.4          0.0.0.0/0

# 根据规则删除
[root@master ~]# iptables -t nat -A yang -s 192.168.1.4 -j ACCEPT

# 验证执行结果
[root@master ~]# iptables -t nat -L yang -n --line-numbers
Chain yang (0 references)
num  target     prot opt source               destination
1    ACCEPT     all  --  192.168.1.1          0.0.0.0/0
2    ACCEPT     all  --  192.168.1.3          0.0.0.0/0

# 清空
[root@master ~]# iptables -t nat -F yang

# 验证执行结果
[root@master ~]# iptables -t nat -L yang -n --line-numbers
Chain yang (0 references)
num  target     prot opt source               destination

导入导出

# 导出
iptables-save > iptables.conf

# 导入
iptables-restore < iptables.conf

开机应用

# 方法1,通过 /etc/rc.local 定义开机后导入操作
# 操作省略

# 方法2,通过定义 eth0-iptables 文件定义网卡引入 iptables 规则
# 操作省略

自定义链

# 创建自定义链
iptables -t filter -N yang

# 为自定义链定义规则
iptables -t filter -A yang -s 192.168.1.1 -j ACCEPT

# 关联到原生链,规则生效
iptables -t filter -A FORWARD -j yang

# 取消关联,规则失效(自定义链仍然存在)
iptables -t filter -D FORWARD -j yang

# 清空自定义链中的规则
iptables -t filter -F yang

# 删除自定义链
iptables -t filter -X yang

规则、条件、动作

规则

  • 规则是由条件+动作组合而成
  • 当规则匹配时, 根据规则定义的方法处理数据包, 如果数据包头符合这样的条件, 就"如此"处理这个数据

条件

源地址或目的地址(-s/-d)

  • -s 或者 -d 不指定默认都是 0.0.0.0/0
# 单一 IP
iptables -t filter -A INPUT -s 192.168.248.79 -j ACCEPT

# 多个 IP
iptables -t filter -A INPUT -s 192.168.248.79,192.168.248.80 -j ACCEPT

# IP 段
iptables -t filter -A INPUT -s 192.168.248.79/24 -j ACCEPT

# 反选
iptables -t filter -A INPUT ! -s 192.168.248.79 -j ACCEPT
# 注: 这个条目的意思是,原地址不为 192.168.248.79 的流量被放行
# 并没有对原地址为 192.168.248.79 的流量做限制,示例这里还是会放行(使用默认策略)
# ---- "源地址不是 192.168.248.79 会通过" 和 "源地址是 192.168.248.79 不通过" 是不同的 ----

# 目的地址为 192.168.248.80 的数据包都会被丢弃
iptables -t filter -A INPUT -d 192.168.248.80 -j DROP

地址段(-m iprang --src-range/--dst-range)

# -m 指定 iprange 模块, 横线连接 ip 收尾, 支持 ! 反选
iptables -t filter -A INPUT -m iprange --src-range 192.168.248.75-192.168.248.78 -j REJECT

端口(-p tcp/udp --dport/--sport)

# 端口匹配属于扩展匹配条件
# 使用它必须指定 -p, 本例中是 tcp 协议
# -m 建议写全, 不写的话默认使用 -p 的协议同名模块
# 拒绝源地址为 192.168.248.79 且目的端口为 22 的流量
iptables -t filter -A INPUT -s 192.168.248.79 -p tcp -m tcp --dport 22 -j REJECT

# 支持反选,拒绝原地址为 192.168.248.79 且目的端口不为 22 的流量 
iptables -t filter -A INPUT -s 192.168.248.79 -p tcp -m tcp ! --dport 22 -j REJECT

# 范围端口
# [start]:[end]
# :22 0-22, 25: 25-65535
iptables -t filter -A INPUT -s 192.168.248.79 -p tcp -m tcp --dport 22:25 -j REJECT

# 离散端口, 支持范围选择用法
iptables -t filter -A INPUT -s 192.168.248.79 -p tcp -m multiport --dport 22,25:90,993,3306 -j REJECT

协议(-p)

# 丢弃来自 192.168.248.80 的 tcp 请求
iptables -t filter -I INPUT -s 192.168.248.80 -p tcp -j DROP

# 支持如下: tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh
# 不指定协议类型时,默认表示所有类型的协议都会被匹配到,与使用-p all的效果相同。

网卡(-i/-o)

# 丢弃来自 em1 的 icmp 请求
iptables -t filter -I INPUT -i em1 -p icmp -j DROP

# prerouting, input, forward 因为有数据包流入, 有 -i 选项
# forward, output, postrouting 因为有数据包流出, 有 -o 选项

动作

  • accept, 允许数据包通过
  • drop, 丢弃数据包, 不会受到拒绝消息, 会受到超时消息
  • reject, 拒绝数据包通过, 会受到拒绝消息
  • snat, 原地址转换
    • masquerade, 是 snat 的一种特殊形式, 用于动态, 临时会变的 ip 上
  • dnat, 目的地址转换
  • redirect, 本机做端口映射

accept、drop

  • 常规用法见上

reject

  • 拒绝并返回拒绝理由

  • 只能绑定在 filter 表中(也就是只能对应 input 、output、forward三个链)

  • 通过 --reject-with 指定返回信息,

    • icmp-net-unreachable
    • icmp-host-unreachable
    • icmp-port-unreachable[default]
    • icmp-proto-unreachable
    • icmp-net-prohibited
    • icmp-host-pro-hibited
    • icmp-admin-prohibited
    点击查看代码
    iptables
    
    

snat、dnat

  • SNAT 只能应用到 input、postrouting 链上
  • DNAT 只能应用到 prerouting、output 链上
# 数据包发送时, 修改源地址, 从75改为80
iptables -t nat -A POSTROUTING -s 192.168.248.75 -j SNAT --to-source 192.168.248.80

# 数据包接收时, 修改目的地址, 从80改为75
iptables -t nat -A PREROUTING -d 192.168.248.80 -j DNAT --to-destination 192.168.248.75

# 修改目的地址和端口, 从80:80改为75:8080
iptables -t nat -A PREROUTING -d 192.168.248.80 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.248.75:8080

其他示例

根据时间限制

点击查看代码
# --timestart:用于指定时间范围的开始时间,不可取反
# --timestop:用于指定时间范围的结束时间,不可取反

# --datestart:用于指定日期范围的开始日期,不可取反
# --datestop:用于指定日期范围的结束时间,不可取反

# --weekdays:用于指定”星期几”,可取反
# --monthdays:用于指定”几号”,可取反

# 9:00 - 19:00 不能访问 http 和 https
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT

# 周六周日, 不能访问 http
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --weekdays 6,7 -j REJECT
# 22,23 号, 不能访问 http
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --monthdays 22,23 -j REJECT
# 除 22,23 号, 不能访问 http
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time ! --monthdays 22,23 -j REJECT
# 9:00 - 18:00, 周六周日不能访问 http
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT
# 22,23,24,25,26,27,28 号中的周五, 不能访问 http
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
# 2020-01-01 - 2021-01-01 不能访问 http
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --datestart 2020-01-01 --datestop 2021-01-01 -j REJECT

根据连接数限制

点击查看代码
# 单 IP 访问 22 端口, 超过两个连接则拒绝
iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT

# --connlimit-mask, 子网掩码位数
# 相同网段掩码的 IP, 同时访问不超过 2 个
iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -m connlimit --connlimit-above 2 --conlimit-mask 27 j REJECT

根据链接频率限制

涉及"令牌桶"概念
我们可以这样想象,有一个木桶,木桶里面放了5块令牌,而且这个木桶最多也只能放下5块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔6秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足5块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在5块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有5个报文想要入关,那么这5个报文就去木桶里找令牌,正好一人一个,于是他们5个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了6秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到5个令牌,并且一直保持着5个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑

点击查看代码
# --limit 10/minute 每分钟允许 10 个包通过
# 还可以是 /second /hour /day
iptables -t filter -I INPUT 2 -p icmp -m limit --limit 10/minute -j ACCEPT

# 对桶内最多装多少令牌进行限制, "桶内最多装 3 块令牌"
iptables -t filter -I INPUT 2 -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT

根据报文状态限制

stat 模块把报文分为 5 个状态

  • NEW, 连接中的第一个包
  • ESTABLISHED, NEW 后边的所有包
  • RELATED, 有关联性的包
  • INVALID, 非正常状态
  • UNTRACKED, 非正常状态
点击查看代码
# 为了防止别人主动连接我们, 所以我们只放行 ESTABLISHED 状态的包即可(有特殊情况可以放开 REELATED 限制)
iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

总结

  1. 顺序很重要, 链顺序, 表顺序, 规则条目顺序
  2. 相同服务的规则, 严格的放在后边
  3. 相同严格的情况下, 被匹配次数多的放在后边
  4. 同一条目中多个匹配条件是与的关系
  5. 作为防火墙要考虑双向性, 内->外, 外->内
  6. 默认策略建议为ACCEPT
posted @ 2024-06-12 18:01  难德糊涂  阅读(109)  评论(0)    收藏  举报