当家庭宽带遇上公网 IP:我是如何让 AI (Ollama) 服务公开访问的

444 阅读8分钟

从公网 IP 到公网服务:我是如何一步步打通家庭服务器(Ollama on macOS)外网访问的

刚刚为我的家庭宽带申请了公网 IP,想着终于可以把家里的 NAS、网站,或者像 Ollama 这样酷炫的本地 AI 服务在外访问了!理论上,有了公网 IP,我的家庭网络就像有了一个全球唯一的地址。但实际上,从拥有 IP 到服务真正能被外网访问,我发现中间还有不少“坑”要填。

下面,我将详细记录下我解决 Ollama (运行在我的 macOS 上) 外网访问问题的全过程,覆盖从基础网络设置到特定应用配置的方方面面,希望能帮助遇到类似问题的你。

目标: 让运行在我家中 macOS 上的 Ollama 服务(默认端口 11434)可以通过我的公网 IP 或域名从外部互联网访问。

环境:

  1. 家庭宽带已开通公网 IP 地址。
  2. 路由器型号: WMA301
  3. mac电脑

第一阶段:摸索基础与端口转发的初尝试

我知道,外网访问内网服务的核心是端口转发 (Port Forwarding)。我的路由器是家庭网络的网关,它拥有那个宝贵的公网 IP。当外部请求(比如访问 http://<我的公网IP>:端口号)到达路由器时,路由器需要知道应该把这个请求交给内网的哪台设备的哪个端口。

我采取的关键步骤:

  1. 固定服务设备内网 IP:

    • 原因: 我意识到路由器的端口转发规则需要指向一个固定的内网 IP。如果我的 Mac Mini IP 通过 DHCP 自动获取,下次重启可能就变了,转发规则也就失效了。
    • 操作:
      • 我先用 ifconfig 查到了我的 Mac Mini 的内网 IP (192.168.10.104) 和 MAC 地址 (4e:60:88:c1:a5:9e)。
      • 接着,我登录了我的路由器管理界面 (192.168.10.1)。
      • 在路由器里,我找到了 "IP 与 MAC 绑定" 功能,把我的 Mac Mini 的 MAC 地址与其当前 IP (192.168.10.104) 绑定了起来。
  2. 配置端口转发规则:

    • 我在路由器管理界面里找了好一会儿,终于找到了 "虚拟服务器 (Virtual Server)" 这个选项(原来它不叫端口转发!)。
    • 我添加了一条规则:
      • 外部端口: 我想用 Ollama 的默认端口 11434,但为了先测试,有时也试了 80 端口。
      • 内部 IP 地址: 我填入了刚绑定的 Mac Mini 的 IP (192.168.10.104)。
      • 内部端口: Ollama 默认是 11434,如果是测 HTTP 就填 80
      • 协议: 我选了 TCP
      • 启用: 确保规则是开启状态。
  3. 本机和内网测试:

    • 本机 (localhost): 我在 Mac Mini 上访问 http://localhost:11434,确认服务本身在运行。
    • 内网 (IP 地址): 我用连着家里 Wi-Fi 的手机访问 http://192.168.10.104:11434这一步非常关键!

第二阶段:遭遇拦路虎 - 内网 IP 不通与双重 NAT

问题来了: http://localhost:11434 能访问,但 http://192.168.10.104:11434 却打不开!同时,外网用我的公网 IP 也访问不了。

我的排查方向一:服务监听地址

  • 诊断: 我用了 sudo lsof -i :11434 命令查看端口监听情况。输出显示 ollama 进程正在 TCP localhost:11434 (LISTEN)
  • 结论: 啊哈!localhost 意味着这个服务只接受来自本机内部的连接,它根本不理会来自局域网 IP 或公网 IP 的请求。这是很多服务的默认安全设置。我找到了导致内网 IP 访问失败的直接原因。 (解决方案我后面会说)

我的排查方向二:网络结构 - 光猫与路由器

  • 背景: 我确认了我的网络是光猫拨号,路由器接在光猫下面。
  • 问题: 我意识到这是典型的 双重 NAT (Double NAT) 结构。
    • 互联网 <--> 光猫 (公网 IP, 第一次 NAT) <--> 路由器 (私网 IP, 第二次 NAT) <--> 我的 Mac Mini
    • 外网请求到了光猫那里,光猫不知道要给我的路由器;就算知道,我只在路由器上做的端口转发也无法处理最外层的请求。
  • 最佳解决方案:光猫改桥接,路由器拨号
    • 操作: 我想办法登录了光猫(过程可能需要找超密),把连接模式从路由/PPPoE 改为了桥接 (Bridge)。然后我登录路由器,在 WAN 设置里改成 PPPoE 拨号,填上了我的宽带账号密码。
    • 效果: 这下好了!我的路由器直接获取了公网 IP,消除了双重 NAT,网络结构简化为 互联网 <--> 光猫 (桥接) <--> 路由器 (公网 IP, NAT) <--> 我的 Mac Mini。现在,只需要在路由器上做一次端口转发就行了。我最终成功实施了这种方案。
  • 备选方案 (我没选,但了解下): 在光猫和路由器上都做端口转发,或者把路由器 IP 设为光猫的 DMZ 主机。

第三阶段:攻克服务本身 - 修改 Ollama 监听地址

网络结构理顺后,我回头解决服务监听地址的问题。我需要让 Ollama 监听 0.0.0.0 (所有 IPv4 接口) 而不是 localhost

我的修改方法 (macOS & Ollama.app):

  1. 我最终采用的方案:手动设置环境变量启动
    • 原理: 在启动 ollama 命令前,在当前终端会话中设置 OLLAMA_HOST 环境变量。
    • 我的操作:
      # 在终端里
      export OLLAMA_HOST=0.0.0.0
      ollama run qwen3:14b  # 或者 ollama serve
      
    • 验证: 我运行后,立刻用 sudo lsof -i :11434 查看,监听地址果然变成了 TCP *:11434 (LISTEN)
    • 内网测试: 我赶紧访问 http://192.168.10.104:11434,成功了!

下面是ai给出的方案我没有成功

Ollama 通常通过 launchd 服务在后台运行。理论上应该修改它的服务配置文件 (.plist) 来设置环境变量 OLLAMA_HOST

  1. 定位 .plist 文件:

    • 预期位置: ~/Library/LaunchAgents/ai.ollama.ollama.plist (~ 代表我的主目录)。
    • 遇到的问题: 怪事!我居然在这个路径下没找到这个文件!
    • 我的排查:
      • 我检查了系统级目录 /Library/LaunchAgents/Library/LaunchDaemons
      • 我用了 mdfind 命令全局搜索 *ollama*.plist 文件。
      • 我用了 launchctl print gui/$(id -u)/ | grep ollama 查看 launchd 是否知道这个服务。
      • 我甚至重新打开了 Ollama.app 看它会不会生成配置文件。
      • 最终确认: 我感觉我的 Ollama 实例好像没有通过标准的 launchd 服务持久化运行,或者它的配置文件藏得太深/根本没用这种方式。
  2. 修改 .plist (理论操作,我这次没直接用上):

    • (假如我找到了文件)我会用文本编辑器打开它。
    • 在主 <dict> 标签内添加设置 OLLAMA_HOST0.0.0.0 的环境变量代码块。
    • 保存文件。
    • launchctl unload/loadbootout/bootstrap 命令重新加载服务。(但我尝试 unload/bootout 时遇到了报错,说明 launchd 这边可能有点问题)。

第四阶段:临门一脚 - 防火墙与外网测试

  1. macOS 防火墙:

    • 临时措施: 为了排除干扰,我暂时关闭了 macOS 的防火墙。
    • 验证通过后:重新开启防火墙,并在“防火墙选项”中添加规则,允许 ollama 应用或 TCP 端口 11434 的连接。安全最重要!
  2. 外网测试:

    • 方法: 必须真正的外部网络测试!我关掉手机 Wi-Fi,用移动数据流量访问。
    • 地址: http://<我的公网IP>:<路由器外部端口> (比如 http://<我的公网IP>:11434)。
    • 结果: 成功了!那一刻真是激动人心!

第五阶段:便捷性与自动化 - 脚本与后续

问题: 每次启动 Ollama 模型都要手动输入 exportollama run 两条命令,太麻烦了。

我的解决方案:创建 Shell 脚本

  1. 我用 nano 创建了一个 run_ollama_qwen.sh 文件。
  2. 写入了以下内容:
    #!/bin/bash
    echo "设置 OLLAMA_HOST=0.0.0.0 ..."
    export OLLAMA_HOST=0.0.0.0
    echo "运行 Ollama 模型: qwen3:14b ..."
    ollama run qwen3:14b 
    echo "Ollama 运行结束。"
    
  3. 保存文件。
  4. 添加执行权限:chmod +x run_ollama_qwen.sh
  5. 运行脚本:./run_ollama_qwen.sh。完美!

重要后续工作(我接下来要做的):

  • DDNS (动态 DNS): 我的公网 IP 是动态的。我需要去买个便宜的域名,然后在路由器上配置 DDNS 功能,让域名自动指向我当前的公网 IP。这样我就可以用域名访问了。
  • HTTPS: HTTP 暴露在公网太不安全了。我得研究下怎么给 Ollama 配置 HTTPS (端口 443)。这可能需要获取 SSL 证书(试试 Let's Encrypt),并可能需要用 Nginx/Caddy 做反向代理。路由器端口转发也要加上 443。

我的感悟

从一个简单的目标出发,我经历了一场网络排查和应用配置的“冒险”。这个过程让我深刻体会到:

  • 外网访问不只是端口转发那么简单: 网络结构 (NAT)、服务本身的监听配置、操作系统防火墙都是要过的坎。
  • 诊断工具是我的“瑞士军刀”: ifconfig, lsof, ps等命令帮了我大忙。
  • 内网测试是基石: 先确保服务在家里能访问,再挑战公网。
  • 搞懂监听地址太重要了: localhost vs. 内网 IP vs. 0.0.0.0,差别巨大。
  • 安全意识时刻不能松懈: 把服务暴露出去,就得想着怎么保护它。
  • 耐心和细致是关键: 排查问题得一步步来,反复验证。

希望我这次折腾的详细记录,能给你打通家庭服务的公网访问之路提供一些参考和帮助!