租来的 GPU 实例多数跑在容器和 NAT 网络后面,对外只开一个高位 SSH 端口,控制台上并没有一排随你勾选的端口。所以"端口映射"在实际操作里是两条路:
- SSH 本地端口转发(隧道)——不在公网上多开任何端口,本地浏览器访问
http://127.0.0.1:端口就直达实例里的服务。第一次跑通、自己一个人用、调试阶段,选这条。 - 平台公网端口映射——在控制台把容器内端口映射到公网 IP 的某个端口,拿到地址的人都能访问。需要给同事演示 WebUI、或者让外部应用调你的推理 API 时才用,代价是你得自己把鉴权补上。
两条路有一个共同前提:先弄清服务在实例里监听在哪个地址、哪个端口。走隧道时服务绑 127.0.0.1 也能正常用;走公网映射时服务必须绑 0.0.0.0,否则映射配了也连不通。下面分开说。
动手前先从控制台抄下四个信息
- 实例的公网 IP 或连接域名
- 外部 SSH 端口:常见是 2222 或 20000 以上的高位端口,一般不是 22
- 登录用户名:
root或ubuntu之类 - 私钥路径(或密码)
这些在实例详情页都能看到,通常直接给一条可复制的连接命令。第二项最容易翻车:NAT 环境下 SSH 并不在默认的 22 端口上,命令里不显式写 -p <外部SSH端口>,结果就是连接超时或被拒绝,很多人会误以为是密钥没配对。密钥生成和权限问题可以参考租的 GPU 怎么用 SSH 连接。
方案一:SSH 本地端口转发
一条命令搞定,OpenSSH 自带,本地端和实例端都不用装东西:
ssh -p 20022 -L 8188:localhost:8188 -i ~/.ssh/id_ed25519 -N [email protected]各段的意思:
-p 20022:实例对外的 SSH 端口,换成你控制台上看到的那个-L 8188:localhost:8188:冒号左边第一个数字是你本机监听的端口,中间的localhost是在实例上解析的地址,最后一个数字是实例内部服务的端口-i:私钥路径-N:只建隧道,不进交互式终端;想同时开个 shell 干活就去掉它
命令跑起来后终端会安静地挂着(这就是 -N 的正常表现),浏览器打开 http://127.0.0.1:8188 就是远端那台卡上的 ComfyUI。

几个常用端口对照:Jupyter 8888、ComfyUI 8188、vLLM 或 FastAPI 8000、TensorBoard 6006。要同时转发多个,就并列写多个 -L:
ssh -p 20022 -L 8888:localhost:8888 -L 8188:localhost:8188 -L 8000:localhost:8000 -i ~/.ssh/id_ed25519 -N [email protected]本机那个端口被占用了(比如本地已经有个 8888 的 Jupyter),改左边的数字就行,右边保持实例内部的真实端口:-L 18888:localhost:8888,然后访问 127.0.0.1:18888。
Windows 的 PowerShell 自带 OpenSSH 客户端,上面的命令原样可用;习惯 PuTTY 的话在 Connection → SSH → Tunnels 里填 Source port(本地)和 Destination(localhost:8188),选 Local 后 Add。
让隧道和服务活得久一点:隧道断了,实例里的服务不一定跟着死——前提是服务跑在 tmux、screen 或 nohup 里。如果你是在 SSH 交互终端里前台启动的 ComfyUI,SSH 一断它就退出了。稳妥的顺序是:先 SSH 进去,在 tmux 里启动服务,退出;再单独开一条 -N 的隧道命令。隧道本身断了重跑一次命令即可,给 SSH 加 -o ServerAliveInterval=60 能减少空闲被掐断的情况。
用隧道时,服务保持默认的 127.0.0.1 监听完全没问题,因为请求是从实例内部的环回地址发出去的。这也是它安全的地方:公网上没有任何新端口暴露。Jupyter 的具体启动和 token 获取可以看GPU 云服务器怎么开 Jupyter。
方案二:控制台做公网端口映射
如果平台支持把容器内端口映射到公网 IP/端口,在实例详情或创建实例时配置映射关系(容器内 8188 → 外部某端口),拿到地址后直接浏览器访问。这条路的关键不在控制台那一步,而在服务的监听地址。
映射生效的前提是容器内的服务监听在 0.0.0.0(所有网络接口)。如果它只绑在 127.0.0.1,那么来自容器外部、以及来自宿主机网络命名空间的请求都会被直接丢掉——端口映射看起来配好了,访问却是连接被拒绝。
常见工具的默认行为并不一致,需要各自加参数:
- ComfyUI 默认监听
127.0.0.1,要外部访问加--listen 0.0.0.0 - Jupyter 加
--ip=0.0.0.0(通常还要--allow-root) - vLLM / FastAPI / TGI 这类服务加
--host 0.0.0.0 - Ollama 通过环境变量
OLLAMA_HOST=0.0.0.0控制
改完记得重启服务,参数只在启动时读取。
公网暴露就要自己做防护。 端口一开,扫描器很快会找上门,而这些工具的默认安全假设是"只有本机访问":
- ComfyUI 本身没有登录鉴权,裸奔在公网上等于把这张卡的文件浏览和执行能力交出去;
- Jupyter 不要用
--NotebookApp.token=''这类关掉验证的写法,保留 token 或设密码; - vLLM 的 OpenAI 兼容接口建议开
--api-key,否则任何人都能拿你的卡跑推理,算力和流量都记在你账上。
能限定来源 IP 就限定;只是临时给人看一眼,用完把映射撤掉。
两种方式怎么选
- 自己调试、跑 ComfyUI 出图、开 Jupyter 写代码 → 隧道,零配置零暴露面。
- 同事或客户要打开 WebUI 看效果、外部程序要调你的
/v1/chat/completions→ 公网映射,配合 API key。 - 服务之间要长期互调、走脚本自动化 → 公网映射更省事,隧道每次都得先建起来。
- 拿不准的时候先用隧道跑通,确认服务本身没问题,再决定要不要往公网放。顺序反过来排查会很痛苦:你分不清是映射没生效、服务没起来,还是绑错了地址。
连不上时按这个顺序查
- SSH 本身就超时/被拒绝:几乎都是端口写错,确认
-p后面是控制台给的外部端口而不是 22;其次看密钥是否对应、本地私钥权限是否为 600。 - 隧道建起来了,浏览器打不开:先确认服务真的在跑。SSH 进实例执行
curl -I http://127.0.0.1:8188,有响应说明服务正常、问题在转发配置;没响应就是服务没启动或换了端口,翻启动日志看它实际监听的端口。 bind: Address already in use:本机端口被占,换-L左边的数字。- 公网地址打不开但隧道能通:典型的服务绑在
127.0.0.1,加上对应的--listen 0.0.0.0/--host 0.0.0.0重启。 - 页面能开但功能异常(Jupyter 反复要 token、WebSocket 断线):token 从服务启动日志里取;WebSocket 类问题优先试隧道方式,少一层转发少一层变量。
- 端口对不上:镜像自带的启动脚本可能改过默认端口,以日志里打印的为准,不要照抄文档里的数字。
用一键部署的镜像模板能省掉一部分麻烦——ComfyUI、vLLM、PyTorch、Jupyter 这些模板里的启动参数和端口是配好的,实例详情页会写明服务跑在哪个端口。可以在 NexGPU 的镜像模板页按任务挑,选模板的判断依据另见云 GPU 镜像模板怎么选;vLLM 开服的参数细节见Llama 模型部署实操。
费用和数据这两条边界
端口映射和 SSH 隧道本身不是一个单独的收费项。NexGPU 的账单只有算力、存储、流量三项,端口相关的影响落在流量上:公网映射后别人访问 WebUI、下载你生成的视频,出站流量都算数;隧道方式同样走流量,只是通常量级小。
更要紧的是别把"关掉隧道"当成"停机"。终端里 Ctrl+C 掐断隧道,实例还在跑,算力照算;实例停机后算力停了,存储费仍然在收;只有销毁实例才全部停止计费。所以调试完一轮,明确一下是"待会儿还要接着用"(停机,留数据,付存储)还是"这件事做完了"(把结果拉回本地,销毁)。计费口径和可租节点在 NexGPU 价格页能查到,单价在下单时锁定到销毁为止。
往本地拉文件不用另外开端口,scp 和 rsync 复用同一条 SSH 通道,记得同样带上 -P(scp 用大写 P)指定那个高位端口:
scp -P 20022 -i ~/.ssh/id_ed25519 [email protected]:/workspace/output/result.mp4 ./实例销毁前,把模型权重之外的产出、改过的配置和脚本都归到一个目录里一次性拉走,比事后找回省事得多。
NexGPU-算力租赁,GPU服务器,GPU云算力,AI服务器租用-新闻博客
评论(0)