一. netfilter
1. 什么是entfilter 和 iptables
- netfilter指整个项目名
- 在这个项目里面,netfilter特指内核中的netfilter框架,
- iptables指用户空间的配置工具。
- netfilter在协议栈中添加了5个钩子,允许内核模块在这些钩子的地方注册回调函数,这样经过钩子的所有数据包都会被注册在相应钩子上的函数所处理,包括修改数据包内容、给数据包标记 或者丢掉数据包等。
- netfilter框架负责维护钩子上注册的处理函数或者模块,以及它们的优先级。
- iptables是用户空间的一个程序,通过netlink和内核的netfilter框架打交道,负责往钩子上配置回调函数。
- netfilter框架负责在需要的时候动态加载其它的内核模块, 有 ip_conntrack、nf_conntrack、NAT subsystem等。
通常使用中 可能会感觉iptables代表了整个项目, 代表了防火墙, 但是在开发者中, 可能netfilter 才是整个项目.
2. netfilter 钩子 (hooks)
- 内核协议栈中,有5个跟netfilter有关的钩子,数据包经过每个钩子时,都会检查上面是否注册有函数,如果有的话,就会调用相应的函数处理该数据包.
2.1 5个钩子
- NF_IP_PRE_ROUTING:
- 接收的数据包刚进来,还没有经过路由选择,即还不知道数据包是要发给本机还是其它机器。
- NF_IP_LOCAL_IN:
- 已经经过路由选择,并且该数据包的目的IP是本机,进入本地数据包处理流程。
- NF_IP_FORWARD:
- 已经经过路由选择,但该数据包的目的IP不是本机,而是其它机器,进入forward流程。
- NF_IP_LOCAL_OUT:
- 本地程序要发出去的数据包刚到IP层,还没进行路由选择。
- NF_IP_POST_ROUTING:
- 本地程序发出去的数据包,或者转发(forward)的数据包已经经过了路由选择,即将交由下层发送出去。
2.2 位置图
|
| In
↓
+-----------------+
| IP_PRE_ROUTING |
+-----------------+
|
↓
+_________________+ +---------------+
| Route table | ---------> | IP_LOCAL_IN |
+_________________+ +---------------+
| |
|
| +_______________+
| | local |
| +_______________+
| |
| |
↓ ↓
+---------------+ +---------------+
| IP_FORWARD | | IP_LOCAL_OUT |
+---------------+ +---------------+
| |
|-----------------------------+
|
↓
+-----------------+
| IP_POST_ROUTING |
+-----------------+
|
| Out
↓
- 上面显示的可以看出, 一个数据包只会经过 下面三种路径的一种.
- 本机收到的IP是本机的数据包: IP_PRE_ROUTING -> IP_LOCAL_IN
- 本机收到目的地IP 不是本地的: IP_PRE_ROUTING -> IP_FORWARD -> IP_POST_ROUTING
- 本机发出的数据包: IP_LOCAL_OUT -> IP_POST_ROUTING
2.3 iptables 中的表(tables)
- iptables 是使用表(tables) 来分配管它的规则的(rule) , 根据rule 的作用划分了几个表, 比如用啦过滤数据包 的rule 放在了 filter 表中, 用来处理 地址转换的 rule 放在了 nat 表中, 其中rule 就是 应用在 netfilter 钩子上的函数, 用来修改 数据包的内容或者过滤数据包, 目前 iptables 支持的表有:
-
filter
- filter 表内的 rule 用来过滤数据, 用来控制让那些数据可以通过, 那些数据不可以通过.
-
nat
- nat 表内的 rule 用来控制网络地址转换, 控制要不要进行地址过滤, 以及如何修改源地址和目的地址, 从而影响数据包的路由, 达到连通的目的, 是路由器的必备功能.
-
Mangle
- 该表内的 rule 用于修改IP数据包头, 如修改 TTL, 同时也可以为数据包添加一些标记, 便于后续其他模块 对数据包处理,( 添加标记是指 网内核skb 结构中添加, 而不是给IP数据包加东西)
-
raw 在 natfilter 里面有个 connection tracking功能, 用来追踪所有的连接, 而且可以看到 raw 表内的 rule 功能给数据包打的标记, 从而控制那些数据包不被 connection tracking 追踪
-
security 在cnetos7 中新加的, 用于设置和 SElinux 相关, 主要设置 一些SELinux 标记, 便于和 SELinux 相关的模块来处理数据包.
2.4 链
-
根据不同功能的 rule 在不同的表内, iptables 将表中的rule 在分类, 让 rule 属于 不同的链(chain), 有 chain来决定什么时候触发 chain 上的 那些rule.
-
iptables 的5个链分别对应5个钩子:
- PREROUTING:
- 数据包经过NF_IP_PRE_ROUTING 会触发 chain 上的rule
- INPUT
- 数据包经过 IP_LOCAL_IN 时会触发 chain 上的 rule
- FORWARD
- 数据包经过 IP_FORWARD 时 会触发 chain 的rule
- OUTPUT
- 数据包经过 IP_LOCAL_OUT时 会触发chain 的rule
- POSTROUTING
- 数据包经过 IP_POST_ROUTING 时会触发 chain 的rule
- PREROUTING:
-
每个表都可以有多个 chains , 但是并不表示每个表都包含了多个 chains, 应为有些表上的 chains 上时没有意义的, 如 raw 上只有 connection tracking 有意义.
2.5 每个表包含的 chain
|
| In
|
↓ ++---------------------++
+-----------------+ || raw ||
| IP_PRE_ROUTING | ------>|| (connection trak) ||
+-----------------+ || mangle ||
| || nat (DNAT) ||
| ++---------------------++
↓ ++-------------++
+_________________+ +---------------+ || mangle ||
| Route table | ---------> | IP_LOCAL_IN | --------> || filter ||
+_________________+ +---------------+ || security ||
| | || nat {SNAT} ||
| | ++-------------++
| |
| +_______________+
| | local |
| +_______________+
| | ++---------------------++
| | || raw ||
++----------++ ↓ ↓ || (connection track) ||
|| mangle || +---------------+ +---------------+ || mangle ||
|| filter || <--| IP_FORWARD | | IP_LOCAL_OUT | --------> || nat(DNAT) ||
|| security || +---------------+ +---------------+ || filter ||
++----------++ | | || security ||
|-----------------------------+ ++---------------------++
|
↓ ++----------++
+-----------------+ ||mangle ||
| IP_POST_ROUTING | -----> ||nat(SNAT) ||
+-----------------+ || ||
| ++----------++
| Out
↓
- 这里以 NF_IP_PRE_ROUTING 为例:
- 数据包到了这里, 首先会执行raw 表中的 PREROUTING (chain) 里面的 rule,
- 然后执行 connection tracking, 接着执行 managle 表中 PREROUTING 中的 rule,
- 最后执行 nat(DNAT) 表中的 PREROUTING 里的rule
- 以 filter 为例:
- 只能注册在 IP_LOCAL_IN, IP_FORWARD, 和 IP_LOCAL_OUT中, 所以只支持 INPUT, FORWARD 和OUTPUT 三个 chain
3. iptables 中的规则(Rules)
- rule 存放在表的忒丁 chain 上, 每个 rule 都有两部分信息.
- Matching
- matching 是如何匹配一个数据包, 匹配条件很多, 比如, 协议类型, 源/目的 地址, 源/目的 端口, in/out 接口, 保内的数据以及连接状态.
- Targets
- target 是用于匹配到数据包后 如何做处理
- DROP: 丢弃数据包, 不做任何处理
- RETURN: 跳出当前chaing, 该 chain内的后续rule 不执行
- QUEUE: 将数据包放入用户空间, 由用户程序处理
- ACCEPT: 同意数据包通过, 执行后续 rule
- 跳转到其他用户自定义的 chain 执行
- target 是用于匹配到数据包后 如何做处理
- Matching
4. iptables 语法
4.1 语法和选项
- 语法:
iptables [-t table] OPTION [chain] rule-specification
- -t table 指定表名
- OPTION 指定选项操作
- chain 指定链chain
- rule-speci 规则说明
4.2 选项
- table
filter: 默认表( 不使用-t 指定表时的默认), 包含的链有 INPUT, FORWARD, OUTPUT
nat: 在创建新的连接时, 会查看此表. 包含的链有 PREROUTING, OUTPUT, POSTROUTING
mangle: 用于修改 数据包, 包含的链有: PREROUTING, OUTPUT, INPUT, FORWARD, POSTROUTING
raw: 该表用于和 NOTRACCK 配合设置耿总路由的豁免, 具有需要较高的优先级的钩子上注册, 因此 ip conntrack 或者其他表调用之前, 内置的链有 PREOUTING, OUTPUT
security: 用于设置强制访问网络规则, 配合 selinux 规则使用.
- OPTIONS:
# 规则相关
-A: --append 追加规则到所选择的链的末端, 当 源/目的 地址为多个时, 会为每个可能的地址配备一个规则.
-I: --insert 再选中的链中插入规则, 可以选择规则号, 如果没有指定则默认插入到 第一条
-D --delete 删除一条或多规则, 可以删除规则号, 或者匹配规则
-C --check 检查选中链 是否存在和规范的规则,
-R --replace 替换选中链中的 规则, 如果 源/目的 地址有多个, 会设置失败, 规则号从 1开始
# 链相关
-N --new-chain chain 创建一个新的用户定义链.
-L --list 列出选中链的所有规则, 如果没有选择链, 则列出所有, 常用于配合 -n (不使用 dns解析),
-F --flush 清空选中链的 所有规则
-X --delete-chain 删除用户自定义的空链.
-E --rename-chain 重命名链
-P --policy chain 指定链上到的 默认策略(ACCEPT, DROP, REJECT)
# 重要参数
-i: --in-interface 指定接受 数据包的接口, (仅用作INPUT, FORWARD, PREROUTING 链), 可以使用 ! 符号表示取反,
-o --out-interface 指定发出数据包的接口 (作用 OUTPUT, FORWARD, OUTROUTING 链), 可用 ! 取反
-p: --protocol 指定协议,
--sport: 源端口
--dport: 目的端口
--icmp-type: 指定协议为 icmp 的类型,(Ping)
-s: --source address 指定该条规则的定的源, 可以是 主机名, 网络名, ip网段(掩码), 也可以是 ip地址
-d: --destination addr 指定该条规则的 目的地, 地址和 source 一样
-m: --match match 指定要使用的匹配项, 测试特定的扩展模块, 匹配的合集构成了条件
-j: --jump target 指定给你规则目标, 即, 如果匹配成功, 如何去做, 目标可以是用户定义的链, 或者一个扩展.
-g: --goto chain 指定用户的 链中继续处理 和 jump 不同, 汇报不会继续.
# 其他选项
-v: --verbose 更详细的显示
-w: --wait 设置抓用锁, 等待时间
-n: --numeric 数字输出, ip和 端口号 使用 数字显示
-m
指定匹配模块以及扩扎模块
mulitiport: 指定多端口, 最大15个, 端口可以是 N-M,或范围, 这些端口只能是同一个协议下的. 如 udp, tcp, dccp, sctp
--dport 目的端口
--sport 源端口
iprange: 指定ip范围
--src-range 192.168.1.100-192.168.1.200 # 范围内的源ip
--dest-range
time: 如果分组到达时间在给定范围内, 则匹配, 所有选项都可以设置,
该项可以设置定时允许访问网络, 定时关闭访问.
--datestart hh:mm[:ss] 开始时间
--datestop hh:mm[:ss] 结束时间
--monthdays: 指定每月的 day1,day2... 通过匹配
--weekdays: 指定每周的 day1, day2... 通过匹配
icmp: 如果协议是icmp , 则可以用这个选项
--icmp-type {type[/code] |typename}
允许指定ICMP烈性, 可以是数字类型, 名称, 代码, 或二者ICMP类型之一 iptables -p icmp -h
mac: 源端mac 匹配
limit: 限制, 该模块用作有限速率匹配, 可以结合日志做限速日志,
--limit 速率[秒/分/时/天][second/minute/hour/day]
最大平均速率, 指定值, 默认是3小时
--limit-burst NUM
匹配最大的初始分组, 当达到上面设置的值, 将可以突破 NUM 次
hashlimit: hashlimit 是使用hash 算法来记录匹配一组连接的速率.
分组可以由每个主机组(源/目的 地址) 和/或 端口来匹配.
可以使用N package.
length: 用与匹配长度.
string: 对报文中的应用层数据做字符串模式匹配检测, (通过算法实现)
--algo(bm|kmp): 字符匹配查找时使用的算法
--string 'STRING' 查找的字符
--hex-string "HEX_STRING" : 使用16进制格式
connlimit: 每个IP并发连接数量限制
--connlimit-upto n 连接数小于 n 匹配
--connlimit-above n 连接数大于 n 匹配
state: 追踪请求和相应之间报文状态:
5种状态:
INVALID: 无法识别的连接
ESTABLISHED 已建立的连接
NEW, 新连接请求
RELATED, 相关联的连接 的一个新请求
UNTRACKED 未追踪的连接
规则:
对进入的 ESTABLISHED 都应该放行
对出去的 ESTABLISHED 都应该放行
检查管理 进入状态的 NEW 连接
拒绝 进出 的 INVAIED
ipvs: 匹配ipvs 连接特性
--ipvs: 分组属于ipvs 连接
--vproto proto : 匹配vip 协议, 按 编号或名称, 如 TCP
--vaddr: vip 地址,
--vport: 匹配vip 端口号
--vdir: vip 报文流向
--vmethod: ipvs 转发方式
- 处理动作
ACCEPT: 允许数据包通过
DROP: 丢弃数据包, 不回应
REJECT: 拒绝数据包通过, 会返回响应信息
LOG: 在日志中记录信息, 并放给下一个规则
QUEUE: 防火墙将数据包交给用户空间
RETURN: 防火墙执行当前链的 后续 Rule, 并返回到调用链
REDIRECT: 端口从定向
MARK: 做防火墙标记
DNAT: 目标地址转化
SNAT: 源地址转换
MASQUEREAD: 地址伪装
5. iptables 实战示例
- 查看当前防火墙状态
- 首先为ssh 端口开放
- 此时可以看到默认规则是accept, 将其改为 DROP 然后测试
- 开放 TCP 的 80端口
- 此时会发现由于设置了
-P OUTPUT DROP
所以本机无法建立新的连接. - 所以需要设置
-P OUTPUT ACCEPT
, 不过此处我使用了-m state --state NEW,ESTABLISHED -j ACCEPT
对新建立的连接和 已建立的连接,放行
- 不让其他主机ping 本机, 但是本机可以ping 其他地址
- 这里需要准备规则有
-
- 禁止其他地址的 icmp 协议进入, 或者本机 INPUT表默认是 DROP.
-
- 本机 OUTPUT 需要允许 ICMP协议包, 或者允许新建的连接和已建立的连接 (state NEW,ESTABLISHED)
-A OUTPUT -p icmp -j ACCEPT
-
6. iptables nat 转发实例
6.1 环境
-
网络:
- 外网: 192.168.10.0/24
- 内网: 192.168.20.0/24
-
服务端:
- 外网IP: 192.168.10.11/24
- 内网IP: 192.168.20.11/24
-
客户端:
- IP: 192.168.20.3/24
-
服务机
- 客户机
6.2 配置操作
- 服务端开启内核的 ip 转发
- 需要将服务端的 内网接入数据包配置转发,
- 将客户端的 默认路由设置为 服务端的内网IP
6.3 操作
- 服务端开启内核的转发
[root@node10011 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
[root@node10011 ~]# grep forward /etc/sysctl.conf
net.ipv4.ip_forward = 1
[root@node10011 ~]# sysctl -p
-------------------
# 或临时生效
[root@node10011 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
- 添加IP 转发规则
iptables -t nat -I POSTROUTING -d 192.168.20.0/24 -j ACCEPT --to 192.168.10.11
- 客户端添加默认路由信息
[fangfc@node10003 ~]$ ip route
169.254.0.0/16 dev eno33554960 scope link metric 1003
192.168.20.0/24 dev eno33554960 proto kernel scope link src 192.168.20.3
[fangfc@node10003 ~]$ sudo ip route add default via 192.168.20.11 dev eno33554960
[fangfc@node10003 ~]$
[fangfc@node10003 ~]$ ip route
default via 192.168.20.11 dev eno33554960
169.254.0.0/16 dev eno33554960 scope link metric 1003
192.168.20.0/24 dev eno33554960 proto kernel scope link src 192.168.20.3
- 添加DNS
- vi /etc/resolv.conf
- 测试
END