mac pfctl 可以实现 dnat 吗?

我 iptables 有这样一个命令。

sudo iptables -t nat -A OUTPUT -d 172.13.0.99 -p tcp --dport 8080 -j DNAT --to-destination 公网ip:80

这样当我请求 172.13.0.99 8080 端口的,时候就会将请求转发到 公网ip 对应的 80 端口上去。实际上这个 ip 172.13.0.99 是不存在的。
然后我找了很多资料,在 mac 下要用 pfctl。都是 rdr 实现。

rdr pass inet proto tcp from any to any port 8080 -> 公网ip port 80

这样实现后,访问本地 ip 或者 172.13.0.99 的 8080 都无法访问到 公网ip 对应的 80 端口。但是到将 公网ip 改成本机 ip,这条规则又是生效的。

在 v2ex 看到有人说 pfctl 只能 nat 本机。

想问问有类似经历的朋友吗,分享给我一下。

结论

经过几位大佬(还有 sf 社区外的)帮助和多次测试,最终得到结论是:pf 无法 nat 到非本机 IP 上。因此上面的 iptables 规则无法直接转化成 pf rdr 来使用。

最终使用了 Seven 大佬的建议。在本地将 lo 网卡的 ip 做别名,加一个 tcp 反向代理,通过别名 ip 来访问反向代理,间接实现了类似 iptables 所表达的功能。

感谢 @水蒸气@Seven 两位大佬对我的帮助。

阅读 512
avatarAI BotBETA
**是的,`pfctl` 在 macOS 上可以通过 `rdr` 规则实现类似 `iptables` 的 DNAT 功能,但有一些限制和需要注意的地方。**

在 macOS 上,`pfctl` 使用 `rdr` 规则来实现目的地址转换(DNAT)。然而,`pfctl` 的 `rdr` 规则默认情况下只适用于目标地址为本地接口地址或广播地址的数据包。这意味着,如果你尝试将流量重定向到非本地 IP 地址(如你例子中的 `172.13.0.99`),它不会按预期工作,除非这个 IP 地址被配置为本地接口的一部分(例如,通过别名接口)。

为了解决这个问题,你可以尝试以下方法:

1. **配置别名接口**:
   你可以为网络接口配置一个别名,将 `172.13.0.99` 分配给这个别名。然后,你可以使用 `rdr` 规则将流量从这个别名接口重定向到公网 IP。

2. **使用 `lo0`(回环接口)**:
   如果 `172.13.0.99` 只是一个内部使用的 IP 地址,并不需要在网络上实际存在,你可以考虑将它添加到 `lo0` 接口(回环接口)。这样,所有发往 `172.13.0.99` 的流量都会通过 `lo0`,然后你可以使用 `rdr` 规则将其重定向到公网 IP。

3. **调整 `rdr` 规则**:
   确保你的 `rdr` 规则正确无误,并且适用于你的网络配置。例如:

rdr pass inet proto tcp from any to any port 8080 -> 公网ip port 80


这条规则本身看起来是正确的,但它可能不会生效,因为 `172.13.0.99` 不是本地接口的一部分。如果你已经将其添加到某个接口,确保该接口是活动的,并且规则中的 "from any to any" 部分是符合你需求的(这可能允许所有来源的流量被重定向,这可能不是你想要的,具体取决于你的安全需求)。

4. **检查防火墙日志**:
使用 `pfctl -s all` 或查看系统日志来检查是否有任何相关的防火墙日志条目,这可能会提供为什么规则没有按预期工作的线索。

5. **考虑使用其他工具**:
如果 `pfctl` 的限制太多,或者你需要更复杂的网络流量管理功能,你可能需要考虑使用其他工具,如 `nftables`(在 Linux 上更常见,但可以通过一些努力在 macOS 上运行)或商业防火墙解决方案。

总之,`pfctl` 在 macOS 上确实可以实现 DNAT 功能,但有一些限制和配置要求。你可能需要调整你的网络配置或规则以满足你的需求。
2 个回答

DNAT用于将目的地址重定向到另一个IP地址,就像Linux的iptables -t nat -A PREROUTING。你的规则不生效,可能是因为系统不允许IP转发:

sudo sysctl -w net.inet.ip.forwarding=1 # 启用IP转发

添加DNAT规则:
/etc/pf.anchors/目录下创建web文件,输入这些内容:

rdr pass on 网络接口 inet proto tcp from any to 172.13.0.99 port 8080 -> 公网ip port 80

将其中的汉字换成你需要的接口和IP。并且在/etc/pf.conf中添加对anchor的引用:

rdr-anchor "web"
load anchor "web" from "/etc/pf.anchors/web"

加载配置并启用PF:

sudo pfctl -f /etc/pf.conf
sudo pfctl -e

可参考这篇文章
macOS 下做 DNAT
在 Mac 上没有 iptables,但你可以使用 Mac 自带的 pf(Packet Filter)来实现类似的端口转发功能。以下是具体步骤:

1.启用 IP 转发:
启用后注意这里如果只能本机可以看我下面的补充

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

2.创建 PF 配置文件: 创建一个新的 PF 配置文件,例如 /etc/pf.anchors/http,内容如下:

rdr pass on lo0 inet proto tcp from any to 172.13.0.99 port 8080 -> 公网ip port 80

3.修改主 PF 配置文件: 编辑 /etc/pf.conf 文件,添加以下内容:

rdr-anchor "http-forwarding"
load anchor "http-forwarding" from "/etc/pf.anchors/http"

4.验证配置: 使用以下命令验证配置文件是否正确:

sudo pfctl -vnf /etc/pf.anchors/http

5.启用 PF 服务: 启用 PF 服务并加载配置:

sudo pfctl -ef /etc/pf.conf

这样,当你在本地访问 172.13.0.99:8080 时,流量会被重定向到指定的公网 IP 的 80 端口。

补充

  1. pf 的 NAT 限制:
  2. pf 只能对本机 IP 进行 NAT 转发
  3. 不能像 iptables 那样对任意目标 IP (比如不存在的 172.13.0.99) 进行 DNAT
  4. iptables vs pf 的主要区别:

    # iptables 可以这样做
    sudo iptables -t nat -A OUTPUT -d 172.13.0.99 -p tcp --dport 8080 -j DNAT --to-destination 公网ip:80
    
    # pf 只能对本机 IP 做转发
    rdr pass on lo0 inet proto tcp from any to 172.13.0.99 port 8080 -> 公网ip port 80

可以将上面步骤1.启用 IP 转发: 这一步之后为网络接口配置别名: 你可以将 172.13.0.99 配置为本地网络接口的别名。这样,pf 会将其视为本地地址,从而允许重定向。以下是具体步骤:

sudo ifconfig lo0 alias 172.13.0.99
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏