pf中的nat
在pf.conf中,nat的配置有一些讲究。本文分为nat masq和port forwarding两部分,也就是linux iptables中常说的snat和dnat。
nat masq
有两种写法:
第一种
block out on em0
match out quick on em0 from 192.168.168.0/24 to any nat-to 1.2.3.4
pass out quick on em0 proto tcp from 1.2.3.4 to any port = 80
这种写法的好处是可以根据outbound数据包的类型进行nat,譬如上面的第3行,表明只有符合访问外网http的,才进行nat。
在第3行rule中,源地址应设为已映射的外网IP地址:1.2.3.4 ,而不是192.168.168.0/24 ,否则会出现nat失败的情况,举例说明:
|
match out on $wan_if from !($wan_if) to any nat-to ($wan_if)
pass out on $wan_if all
...
pass inet icmp from any to any
目的是实现内网主机访问外网时,譬如ping 221.182.235.44,将会在$wan_if上做snat,然而实际情况是,目标主机上启用tcpdump抓包,发现源地址并未改变,仍然是192.168.33.83,这意味着:
-
icmp数据包命中了pass inet icmp from any to any,然而并未做snat;
-
源地址为RFC1918地址的数据包可以在互联网上进行路由,可达到目的主机。目的地址为RFC1918地址的数据包不可在互联网上路由。
最好的做法应该是将Pass out on $wan_if all
改成pass out quick on $wan_if from $wan_if to any
。
是否正确snat可通过在$lan_if和$wan_if接口上开启tcpdump来进行检验
$ doas tcpdump -nvi <wan_if> icmp
15:10:18.770734 192.168.33.83 > 221.182.235.44: icmp: echo request (id:59fe seq:5) (DF) (ttl 63, id 0, len 84)
15:10:18.772604 221.182.235.44 > 192.168.33.83: icmp: echo reply (id:59fe seq:5) [tos 0xc0] (ttl 57, id 33332, len 84)
$ doas tcpdump -nvi <lan_if> icmp
15:10:18.770813 221.182.254.165 > 221.182.235.44: icmp: echo request (id:8ec3 seq:5) (DF) (ttl 62, id 0, len 84)
15:10:18.772540 221.182.235.44 > 221.182.254.165: icmp: echo reply (id:8ec3 seq:5) [tos 0xc0] (ttl 58, id 33332, len 84)
可以看出,在$lan_if上尚未做snat,在$wan_if上已经做snat === 第二种
block out on em0
pass out quick on em0 proto 192.168.168.0/24 to any nat-to 1.2.3.4
与match+pass相比,这种写法比较简单,差异体现在systat的结果上,match+pass的state分两条,容易分辨,单pass的state只有一条,跟普通的pass类似,比较难分辨。
-
match + pass(nat-to)下的systat
$ doas systat rules RULE ACTION DIR LOG Q IF PR K PKTS BYTES STATES MAX INFO 3 Match Out Log fxp2 61 5761 0 inet from ! (fxp2) to any 4 Pass Out Log fxp2 K 61 5761 17 inet from 221.182.254.190/32 to any
可以看出match和pass是成双出现的,能看得出是snat
-
pass(nat-to)下的systat
$ doas systat rules RULE ACTION DIR LOG Q IF PR K PKTS BYTES STATES MAX INFO 3 Pass Out Log fxp2 K 37 3893 9 inet from ! (fxp2) to any
看不出已经做了
snat
,所以,推荐使用第一种写法。 == port forwarding
需求:允许客户端访问一台内网服务器ssh服务,openbsd是防火墙。
pass in on $ext_if inet proto tcp to $ext_carp_if port 7022 \
rdr-to $vm_debn6 port ssh
pass quick on $dmz_if inet proto tcp to $vm_debn6 port ssh
pass rule有rdr-to选项时,必须指定方向:in
或out
,故不能直接写:
pass on $wan_if ...
必须写成:
pass in on $wan_if ... to $wan_if port <port> \
rdr-to $internal_server port
还需要额外增加一条:
pass on { $dmz_if, $lan_if } ... to $internal_server port <port>
如果是映射到防火墙的自有服务,写法为:
# SSH
pass in quick log inet proto tcp to $ext_if port ssh
# OpenVPN
pass in quick log inet proto udp to $ext_if port 1194
这个时候不能将$ext_if 更改成$ext_carp_if 。因为防火墙返回的数据包是以它外网卡的IP地址作为源地址,而不是虚拟的外网IP地址。因此,只能让用户直接访问防火墙的外网IP地址,不建议通过虚拟的外网IP地址来访问防火墙自身所提供的服务。
|