在某个项目中,pfsense和tinc是分开部署的,管理员可以通过tinc访问到pfsense,最近pfsense 2.3.3又把tinc纳入了官方repo,所以打算直接将tinc部署在pfsense中。然而部署完毕后发现,pfsense的tinc可以正常启动,并且能够ping通其它tinc节点,但是其它tinc节点ping不通pfsense。原拓扑结构如下:

tinc topology
$ sudo tcpdump -nvi tun0
tcpdump: listening on tun0, link-type NULL (BSD loopback), capture size 65535 bytes
18:16:22.266476 IP (tos 0x0, ttl 64, id 27429, offset 0, flags [none], proto ICMP (1), length 84)
    10.9.1.1 > 10.9.4.1: ICMP echo request, id 42611, seq 442, length 64
18:16:23.276482 IP (tos 0x0, ttl 64, id 32258, offset 0, flags [none], proto ICMP (1), length 84)
    10.9.1.1 > 10.9.4.1: ICMP echo request, id 42611, seq 443, length 64
18:16:24.286223 IP (tos 0x0, ttl 64, id 12784, offset 0, flags [none], proto ICMP (1), length 84)
    10.9.1.1 > 10.9.4.1: ICMP echo request, id 42611, seq 444, length 64

发现只有icmp echo,没有icmp reply。难道是被某条策略阻挡了?我已经在Firewall-Rules-Floating标签页中里面添加了一条icmp全放开的策略:

floating-rule-item

没问题啊。

pfctl -sr | grep icmp检查发现

pass quick on bce0 inet proto icmp all keep state label "USER_RULE"
pass quick on bce1 inet proto icmp all keep state label "USER_RULE"
pass quick on bge0 inet proto icmp all keep state label "USER_RULE"
pass quick on bge0_vlan9 inet proto icmp all keep state label "USER_RULE"
pass quick on bge0_vlan10 inet proto icmp all keep state label "USER_RULE"
pass quick on bge0_vlan11 inet proto icmp all keep state label "USER_RULE"
pass quick on bge1 inet proto icmp all keep state label "USER_RULE"

嗯,为何限定了网卡?再检查webUI,发现还真是:

floating-setting-real

理想的情况下应该是:

floating-setting-expect

通过pfctl -sr查看到的应该是:

pass quick inet proto icmp all keep state label "USER_RULE"

因为pfsense默认情况下在图形界面中显示不了tun[1]接口,因而无法通过图形界面针对该接口创建策略。所以在floating的icmp全放开这条策略中无法选择tun0这个接口,接着我尝试着全部取消所有接口的选择,发现不行!必须得保留一个,这绝对是一个bug,咋办,只好删掉整条策略新建一条。

终于解决了策略的问题,可是从其它节点仍然ping不通此节点的tun0接口。经检查发现,原来之前已经有一条静态路由指向了原tinc节点:

$ sudo netstat -rn4
...
10.9.0.0/16         192.168.8.100      UGS        bce1

这个是导致没有回程路由的原因,于是我在webUI删掉这一条静态路由,然而仍然无法ping通,这就奇怪了。再用netstat -rn4,仍然看到该路由,难道又是pfsense的bug?我决定在命令行下试一下:

$ sudo route delete -net 10.9.0.0/16 192.168.8.100
route: writing to routing socket: Address already in use
delete network 10.9.0.0 fib 0: gateway uses the same route

what?耍了一番google fu,发现原来tinc启动后创建了tun0端口,该端口的ip地址为10.9.4.0/24,于是pfsense自动生成了直连路由。之前的静态路由包含了10.9.4.0/24这个网段,所以无法直接删除这条静态路由,原因是:无法删除直连路由。解决的办法也很简单,杀掉tincd进程,然后手工删掉静态路由,接着再启动tincd进程。简言之,重启pfsense即可。至此,解决pfsense的icmp不可达问题。

小结一下:

  • the book of pf应成为每一个pfsense高阶用户的案头书

  • pfsense的webUI在使用方面提供了便利性的同时,也掩盖了很多细节,命令行才是排错最好的工具,pftop、tcpdump、pfctl -sr都是你的良师益友;

  • 在pfsense的floating中创建策略有一个bug:一旦选择了网卡,后续如果修改该策略的时候,无法全部取消网卡选择,至少要保留一块。假如需要实现真正的pass quick in any只能删掉整条策略,然后新建;

  • 无法删除直连路由;


1. tinc启动的时候会自动创建该接口