除非在Mac OS X上使用pf.conf激活OpenVPN连接,否则请阻止传出流量


19

除非使用pf.conf激活了我的OpenVPN连接,否则我已经能够拒绝与外部网络的所有连接。但是,如果通过关闭和打开笔记本电脑盖或重新打开和关闭Wi-Fi断开连接,则会失去Wi-Fi连接。

  • 我在Mac OS 10.8.1上。
  • 我通过Wi-Fi(从不同位置,包括公共Wi-Fi)连接到Web。
  • OpenVPN连接是使用粘度设置的。

我在下面设置了以下数据包过滤规则 /etc/pf.conf

# Deny all packets unless they pass through the OpenVPN connection
wifi=en1
vpn=tun0

block all

set skip on lo
pass on $wifi proto udp to [OpenVPN server IP address] port 443
pass on $vpn

我使用启动包过滤器服务,sudo pfctl -e并使用加载新规则sudo pfctl -f /etc/pf.conf

我还编辑/System/Library/LaunchDaemons/com.apple.pfctl.plist并更改了行<string>-f</string>以读取,<string>-ef</string>以便数据包筛选器在系统启动时启动。

一开始这一切似乎都很好:只有OpenVPN连接处于活动状态,应用程序才能连接到Web,因此我绝不会通过不安全的连接泄漏数据。

但是,如果我关闭然后重新打开笔记本电脑的机盖,或者再次打开和关闭Wi-Fi,则Wi-Fi连接将会丢失,并且在状态栏中的Wi-Fi图标中会出现一个感叹号。单击Wi-Fi图标将显示“警告:没有Internet连接”消息:

没有网际网路连线讯息

要重新建立连接,我必须断开并重新连接Wi-Fi,有时五到六次,然后“警告:没有Internet连接”消息消失,我可以再次打开VPN连接。其他时间,Wi-Fi警报会自动消失,感叹号消失,我可以再次连接。无论哪种方式,都可能需要五分钟或更长时间才能重新建立连接,这可能会令人沮丧。

删除线路block all可以解决问题(但允许不安全的连接),因此看来我阻止了Apple重新获得并确认Wi-Fi连接所需的一项服务。我试过了:

  • 通过添加pass on $wifi proto icmp all到pf.conf来启用icmp
  • 通过添加启用DNS解析 pass on $wifi proto udp from $wifi to any port 53
  • 尝试通过记录阻止的数据包(通过更改block allblock log all)来了解更多信息,但是在OS X下似乎无法进行日志记录,因为这样做sudo tcpdump -n -e -ttt -i pflog0会导致日志显示为“ tcpdump:pflog0:不存在此类设备”。

这些都无法帮助您更快地重新建立Wi-Fi连接。

我还能做些什么以确定需要什么服务才能恢复Wi-Fi连接,或者我应该在pf.conf中添加什么规则以使Wi-Fi重新连接更加可靠?


Answers:


14

通过使用Little Snitch监视网络连接,我发现Apple在后台使用mDNSResponder应用程序来检查Wi-Fi连接是否可用。mDNSResponder将UDP数据包发送到名称服务器,以检查连接性并将主机名解析为IP。

更改UDP规则,我以前允许Wi-Fi上的所有 UDP数据包允许mDNSResponder进行连接,这意味着Wi-Fi现在在断开连接后第一次重新连接。为了将来对其他人有所帮助,我最终的pf.conf包括苹果对Mountain Lion的默认规则,如下所示:

#
# com.apple anchor point
#
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"as
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"

#
# Allow connection via Viscosity only
#
wifi=en1 #change this to en0 on MacBook Airs and other Macs without ethernet ports
vpn=tun0
vpn2=tap0

block all

set skip on lo          # allow local traffic

pass on p2p0            #allow AirDrop
pass on p2p1            #allow AirDrop
pass on p2p2            #allow AirDrop
pass quick proto tcp to any port 631    #allow AirPrint

pass on $wifi proto udp # allow only UDP packets over unprotected Wi-Fi
pass on $vpn            # allow everything else through the VPN (tun interface)
pass on $vpn2           # allow everything else through the VPN (tap interface)

这意味着,不幸的是,现在可以使用少数使用UDP协议的应用程序通过Wi-Fi泄漏数据,例如ntpd(用于时间同步)和mDNSResponder。但这似乎比允许数据不受保护地通过TCP传输更好,后者是大多数应用程序所使用的。如果有人对这个设置有任何改进的建议,欢迎提出评论或进一步的答案。


这是我一直很感兴趣的东西,看到您的结果启发了我回家尝试!谢谢!
jakev'9

@SixSlayer似乎工作得很好!我将Viscosity设置为在启动和断开连接时自动连接,这使整个过程变得非常无缝。需要注意的主要事情是,显然,在操作系统更新后,pf.conf和com.apple.pfctl.plist会重置为默认值,因此值得对两者进行备份。
尼克

恕我直言,UDP的事情真是令人um目结舌。我不是网络专家,但是这可以帮助我学习,并且对控制这些细节非常着迷。我会花一些时间寻找解决方法,但是如果有人击败我,那也是一样。
jakev 2012年

这太棒了-正是我想要的。谢谢!
keo 2012年

您是否可能设法同时打开了许多OpenVPN连接,并通过它们并行路由?(以增加和增加带宽)
keo 2012年

11

您不需要允许所有 UDP。mDNS中的“ m”表示“组播”,它使用一个称为“链接本地组播地址”的特定组播目标IP地址和一个UDP端口号5353

这意味着在上面的解决方案中,您不必要地允许到所有65535 UDP端口的通信到世界上所有37亿可路由IP地址,以绕过VPN。您会惊讶于有多少应用程序使用UDP,因此您在很大程度上违背了您最初设想的目的,即当VPN断开时阻止外来流量。

为什么不使用此规则:

pass on $wifi proto udp to 224.0.0.251 port 5353

防火墙配置的一个非常重要的经验法则-通过防火墙进行例外处理时,请始终尝试使用最具体的规则。有时,有时会牺牲便利性和易用性,也就是说,您可能会发现还需要通过一些其他本地链路协议,并添加另一个特定规则。

如果您交换上述规则并发现原来的wifi问题再次出现,则您的PF可能阻止了DHCP(该协议用于自动配置网络设备的IP地址)。(在家庭网络中,通常您的宽带路由器将是您的DHCP服务器)。您需要允许DHCP的规则是:

pass on $wifi proto udp from 0.0.0.0 port 68 to 255.255.255.255 port 67

*注意:您可能需要替代0.0.0.0anyDHCPREQUEST您的计算机首先发送的数据包具有源地址,0.0.0.0因为在此阶段,您的计算机尚没有IP地址。
老实说,我更倾向于使用any。另一个选择是剔除任何源规范,即pass on $wifi proto udp to 255.255.255.255 port 67,但这意味着我们会丢失规则的源端口部分,并且尽可能具体始终是最安全的选择。

希望能有所帮助。以下是一些有用的链接:

mDNS:http : //en.wikipedia.org/wiki/Multicast_DNS#Packet_structure

DHSP:http : //en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_discovery


1

这给了我足够的背景信息,使我可以大步向前并使用pf.conf。这是我在10.8上使用的使VPN连接断开后重新连接的方法:

(我只使用以太网,但是您可以将$ lan更改为$ wifi,它应该可以工作)

lan=en0
wifi=en1
vpn=tun0
block all
set skip on lo
pass on $lan proto { udp,tcp } to 8.8.8.8
pass on $lan proto tcp to vpn.btguard.com port 1194
pass on $vpn

1

为了以 一种“简便”的方式创建PF规则,可以识别现有的活动接口,包括当前的(vpn)接口,可以使用此小型killswitch程序,

仍在进行中,但可能是识别外部IP和活动接口以正确创建防火墙规则的良好起点。

示例或使用-i(info)选项的输出:

$ killswitch -i
Interface  MAC address         IP
en1        bc:57:36:d1:82:ba   192.168.1.7
ppp0                           10.10.1.3

public IP address: 93.117.82.123

传递服务器ip -ip

# --------------------------------------------------------------
# Sat, 19 Nov 2016 12:37:24 +0100
# sudo pfctl -Fa -f ~/.killswitch.pf.conf -e
# --------------------------------------------------------------
int_en1 = "en1"
vpn_ppp0 = "ppp0"
vpn_ip = "93.117.82.123"
set block-policy drop
set ruleset-optimization basic
set skip on lo0
block all
pass on $int_en1 proto udp to 224.0.0.251 port 5353
pass on $int_en1 proto udp from any port 67 to any port 68
pass on $int_en1 inet proto icmp all icmp-type 8 code 0
pass on $int_en1 proto {tcp, udp} from any to $vpn_ip
pass on $vpn_ppp0 all

远非完美,但工作仍在进行中更多信息/代码可以在这里找到:https : //github.com/vpn-kill-switch/killswitch


0

-作为补充-

您可能要添加以下行:

pass on $wifi inet6 proto udp from any to FF02:0000:0000:0000:0000:0000:0000:00FB port 5353

允许mDNS在ipv6上运行

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.