OpenWRT防火墙工具fw3之NAT篇
NAT的原理
网卡收到数据包,首先进行的是DNAT检查,检查数据包的包头是否符合DNAT的规则,如果符合,将数据包的包头目的地址(包括端口,后文不在赘述)按规则替换。
替换完目的地址后,根据新的包头匹配路由表进行路由,确定数据包从哪个端口出去。
路由完成后再检查是否符合源地址替换规则(SNAT),如果符合源地址替换规则,则按照规则将数据包做SNAT,然后将新的数据包按照路由送出网卡。注意:上述描述的是数据包的目的地址不是本机,而是需要本机转发的报文。
OpenWRT下的netfilter管理工具
Linux下的防火墙和NAT功能是通过netfilter内核模块实现的,iptables是一个用来与内核层的netfilter交互的用户层工具,但是iptables是一个命令行工具,为了方便从配置文件中获取过滤信息,OpenWRT开发了一套与iptables同地位的netfilter管理工具fw3,这个工具侧重于从uci格式的配置文件中获取过滤信息下发到内核的netfilter中去。
1. fw3配置文件
阅读本小节需要具备uci配置文件格式知识。
fw3的配置文件默认为/etc/config/firewall。
2. 数据包的目的地址转换(DNAT)
DNAT就是对数据包的目的地址进行转换,目的地址包含目的IP地址、目的端口。即从一个五元组变化为另一个五元组,生成一个新的数据包。五元组里面的5个数据任意组合可以作为过滤条件,即从所以数据包中筛选生效数据包的过滤条件。
(目的IP | 源IP | 目的端口 | 源端口 | 协议类型) --> (新目的IP | 源IP | 新目的端口 | 源端口 | 协议类型)
举个例子 1:
config redirect
option target DNAT
option src wan
option dest lan
option proto tcp
option src_dport 2222
option src_dip 192.168.8.20
option src_ip 192.168.9.20
option src_port 3333
option dest_ip 192.168.10.20
option dest_port 22
option enabled 1
上述配置翻译成iptables命令如下:
iptables -t nat -A zone_wan_prerouting -p tcp -s 192.168.9.20/255.255.255.255 -d 192.168.8.20/255.255.255.255 -m tcp --sport 3333 --dport 2222 -m comment --comment "@redirect[0]" -j DNAT --to-destination 192.168.10.20:22
翻译成白话就是告诉内核:
如果遇到“源地址192.168.8.20,目的地址192.168.8.20,源端口3333,目的端口2222”的数据包,修改成“源地址192.168.168.8.20,目的地址192.168.10.20,源端口3333,目的端口22”的数据包。
| option name | 含义 |
|---|---|
| target | 本条规则的动作[DNAT|SNAT] |
| src | 数据包的来源接口,对应zone节点的定义 |
| dest | 数据包的目的接口,对应zone节点的定义 |
| proto | 要过滤的数据包的协议, [tcp|udp|tcpudp] |
| src_dport | 在做地址替换之前的数据包目的端口 |
| src_ip | 在做地址替换之前的数据包源IP地址 |
| src_dip | 在做地址替换之前的数据包目的IP地址 |
| src_port | 在做地址替换之前的数据包的源端口 |
| dest_ip | 地址替换之后的数据包目的IP地址 |
| dest_port | 地址替换之后的数据包目的端口地址 |
举个例子 2:
config redirect
option target DNAT
option src wan
option dest lan
option proto tcp
option src_dport 2222
option src_dip 192.168.8.20
option dest_port 22
option enabled 1
上述配置翻译成iptables命令如下:
iptables -t nat -A zone_wan_prerouting -p tcp -d 192.168.8.20/255.255.255.255 -m tcp --dport 2222 -m comment --comment "@redirect[0]" -j REDIRECT --to-ports 22
翻译成白话就是告诉内核:
如果遇到“目的地址192.168.8.20,目的端口2222,协议为tcp”的数据包,修改成“源地址保持,目的地址192.168.10.20,源端口保持,目的端口22,协议为tcp”的数据包。
对比例子1和例子2的区别: 例子2的对数据包的过滤范围要宽,只关心目的地址和目的端口。我们可以任意的放宽检测条件来对数据包进行过滤
注意:DNAT只做目的地址、目的端口的转换。
3. 数据包的源地址转换(SNAT)
举个例子 1
config redirect
option target SNAT
option src wan
option dest lan
option proto tcp
option src_dport 2222
option src_dip 192.168.8.20
option src_ip 192.168.9.20
option src_port 3333
option dest_ip 192.168.10.20
option dest_port 22
option enabled 1
翻译成iptables命令:
iptables -t nat -A zone_lan_postrouting -p tcp -s 192.168.9.20/255.255.255.255 -d 192.168.10.20/255.255.255.255 -m tcp --sport 3333 --dport 22 -m comment --comment "@redirect[0]" -j SNAT --to-source 192.168.8.20:2222
翻译成白话:
当遇到“源地址192.168.9.20,目的地址192.168.10.20,源端口3333,目的端口22,协议为TCP”的数据包时,将其源地址和源端口修改为(192.168.8.20,2222)
(,192.168.9.20,22,3333,tcp) --> (,192.168.8.20,22,2222,tcp)
注意:在源地址转换里,option参数的意义与在目的地址转换里有些不同,区别如下:
| option选项 | 在DNAT中的含义 | 在SNAT中的含义 |
|---|---|---|
| src_dport | 原数据包的目的端口 | 做源端口替换后的端口号 |
| src_dip | 原数据包的目的地址 | 做源地址替换后的目的地址 |
| dest_ip | 做目的地址替换后的目的地址 | 原数据包的目的地址 |
| dest_port | 做目的地址替换后的目的端口 | 原数据包的目的端口 |