MacOS配合pfctl实现dnat以及filter:修订间差异

来自三线的随记
无编辑摘要
(Admin移动页面MacOS配合pfctl实现dnatMacOS配合pfctl实现dnat以及filter:content added)
(没有差异)

2021年6月20日 (日) 00:07的版本

摘要

Packet Filter (from here on referred to as PF) is OpenBSD's system for filtering TCP/IP traffic and doing Network Address Translation.

pf是OpenBSD的产物

pf的规则语法非常遵循行为顺序: Rules must be in order: options, normalization, queueing, translation, filtering


通过pf在macOS上实现dnat

1. 首先需要允许IP转发

sysctl -w net.inet.ip.forwarding=1

2. 然后这里通过anchor的形式引入自定义规则方便维护, 当然也可以将需要的规则直接写入/etc/pf.conf文件中,注意macOS在升级的时候会覆盖/etc/pf.conf文件

touch /etc/pf.anchors/my_anchor

3. my_anchor文件中写入如下规则实现DNAT(pf规则允许定义使用变量)

zt_peer_wanip = 223.5.5.5
zt_peer_wanport = 21089

## 将发往114.114.114.114 9988端口的udp报文DNAT到114.114.114.114:53
rdr pass on lo0 proto udp from any to 114.114.114.114 port 9988 -> 114.114.114.114 port 53

## 通过变量的形式定义DNAT规则
rdr pass on lo0 proto udp from any to $zt_peer_wanip $zt_peer_wanport -> $zt_peer_wanip port 53

# change route to local interface
pass out route-to lo0 proto udp from any to 114.114.114.114 port 9988


# 通过变量的形式定义重路由规则
pass out route-to lo0 proto udp from any to $zt_peer_wanip port $zt_peer_wanport

4. 将/etc/pf.conf文件改写以加载anchor(下文所示规则中一部分的规则是macOS原有的规则,保留不动)

#
# Default PF configuration file.
#
# This file contains the main ruleset, which gets automatically loaded
# at startup.  PF will not be automatically enabled, however.  Instead,
# each component which utilizes PF is responsible for enabling and disabling
# PF via -E and -X as documented in pfctl(8).  That will ensure that PF
# is disabled only when the last enable reference is released.
#
# Care must be taken to ensure that the main ruleset does not get flushed,
# as the nested anchors rely on the anchor point defined here. In addition,
# to the anchors loaded by this file, some system services would dynamically
# insert anchors into the main ruleset. These anchors will be added only when
# the system service is used and would removed on termination of the service.
#
# See pf.conf(5) for syntax.
#

#
# com.apple anchor point
#
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
nat-anchor my-redirect

rdr-anchor "com.apple/*"
rdr-anchor my-redirect

dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"


# my-redirect
anchor "my-redirect"
load anchor "my-redirect" from "/etc/pf.anchors/my_anchor"

5. 启用pf并加载规则

pfctl -vF all ; pfctl -vef /etc/pf.conf

6. [debug] 这个时候使用tcpdump之类的抓包工具能够在lo0网卡上看到相关流量,以及在流量出口网卡能够看到被dnat后的报文

Related commands

enable pf

pfctl -e

disable pf

pfctl -d

通过command传递rule

echo "pass out route-to (lo0 127.0.0.1) proto tcp and port 80 from any to any" | sudo pfctl -ef -

清空所有

pfctl -vF all

从文件中加载规则

pfctl -vf /etc/pf.conf


如上文规则example所示,pf结合dnat可以实现很多玩法,而且pf的规则定义能力还是相当强大的甚至规则能够指定到某些user视角上

包括但不限于:

  1. 在一些网络需要登陆认证才能使用的场所(如麦当劳 星爹爹等),同时这些网络的53端口是全白名单端口随意通讯的话(也就是未认证前全网53端口放行),可以将你的流量通过53端口转发出去绕过认证( 例如如果你有zerotier网络,可以将你的MOON节点流量以及一些有动态公网IP的DIRECT通道建立流量通过udp 53端口转发出去以建立直连通道,然后将未认证网络的设备的默认网关改为你的zt网络当中的其他设备即可绕过认证上网) [为什么要这么大费周章去绕过认证上网?对于公共场合的网络,如果采用绕过认证的方式去联网的话,其实你的联网方式就会起到类似使用VPN的效果,除了能够防止你的个人信息因在wifi认证页面填写而导致泄漏以外,还能给你的联网通讯叠加一定程度的安全buff]
  2. 通过pf实现类似iptables效果的透明代理(将全部80和443端口的流量转发到某些proxy服务上)
  3. (发挥脑洞..)