关于 expose-localhost
expose-localhost 是一项指导通过 ngrok 将本地服务公开到互联网的技能,面向需要分享开发服务或 TCP 服务的用户。它涵盖访问控制、流量策略及可复用配置。
主要功能
- 01通过 ngrok 建立 HTTP 或 TCP 隧道
- 02配置 OAuth、基本认证和 IP 限制
- 03为开放访问设置速率限制
- 04检测本地服务端口并验证配置
- 05保存隧道策略和启动脚本
适用场景
- 01向评审者分享受保护的开发预览
- 02临时开放 SSH 或数据库连接
- 03为本地服务配置可复用的隧道启动流程
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ngrok/ skills --skill expose-localhost安装后在 Claude Code 中输入/expose-localhost确认已加载。
附带文件references/TROUBLESHOOTING.md
详细介绍
暴露本地主机
使用 ngrok 将本地服务暴露到公共互联网。还可以通过 Traffic Policy 添加 OAuth、OWASP 防护或速率限制。
前置条件
- 已安装 ngrok CLI(可使用
ngrok命令) - 已配置身份验证令牌(
ngrok config add-authtoken <TOKEN>)
工作流
步骤 1:预检与配置
在不提示用户的情况下,验证 ngrok 是否已就绪:
ngrok config check
如果缺少身份验证令牌,请告知用户运行:ngrok config add-authtoken <TOKEN>(可在 https://dashboard.ngrok.com/get-started/your-authtoken 获取令牌)
然后,先一次性询问所有问题,再进行任何操作:
Before I expose your service, I need a few details:
1. **Port**: I see your app runs on port 3000. Is that correct?
2. **Domain**: Use your dev domain, or do you have a custom domain?
3. **Access control**: Open access, or require login (Google/GitHub/etc.)?
4. **Save config?**: One-time setup, or save for reuse?
不要提及云端点、保留域名或内部端点——这些都是用户无需考虑的高级概念。
检测端口:检查 package.json 脚本中的 --port、.env 中的 PORT=,以及 docker-compose.yml 中的端口映射。
它是 HTTP 服务吗? 如果用户提到 SSH、RDP、数据库,或指定了 22、3389、5432 或 3306 等端口,则这是原始 TCP 服务——请跳转到非 HTTP 服务(TCP)。上面关于域名和访问控制的问题不适用于此类服务。
域名:大多数 ngrok 账户都有一个免费的静态开发域名(例如 something.ngrok-free.dev)。运行 ngrok http PORT 会自动使用该域名。用户也可以提供在 ngrok 控制面板中配置的自定义域名。有些账户(尤其是新账户)可能还没有开发域名——如果 ngrok 因 ERR_NGROK_15013 而失败,请告知用户:“您还没有开发域名。请前往 https://dashboard.ngrok.com/domains 领取免费域名,然后我们可以再试一次。”
如果用户请求 OAuth,还要询问:“是否只允许特定人员访问?我可以按电子邮件地址或电子邮件域名限制访问。”
收集完答案后,请进行确认,并在继续操作前征得用户同意(Y/n)。
步骤 2:启动隧道
不启用安全防护(最简单)
ngrok http {PORT} &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1
使用特定域名时,添加 --url https://{DOMAIN}。
启用安全防护(Traffic Policy)
先创建流量策略文件,然后使用该文件启动 ngrok。
仅 OAuth(用户请求身份验证时的默认设置):
on_http_request:
- actions:
- type: oauth
config:
provider: google
将 google 替换为所选提供商(google、github、microsoft、gitlab、linkedin、twitch)。
如果用户请求 OAuth,默认仅使用 OAuth。除非用户明确要求,否则不要添加 OWASP 防护或速率限制——OAuth 已经可以阻止未经身份验证的访问。
限制 OAuth 访问的电子邮件地址——使用单独的规则和 CEL 表达式拒绝不匹配的电子邮件地址。不要在 OAuth 操作中添加 allow 字段。
单个电子邮件地址:
on_http_request:
- actions:
- type: oauth
config:
provider: google
- expressions:
- "actions.ngrok.oauth.identity.email != '[email protected]'"
actions:
- type: deny
config:
status_code: 403
电子邮件域名:
on_http_request:
- actions:
- type: oauth
config:
provider: google
- expressions:
- "!actions.ngrok.oauth.identity.email.endsWith('@your-company.com')"
actions:
- type: deny
config:
status_code: 403
多个电子邮件地址——在 in 左侧明确指定身份:
- expressions:
- "!(actions.ngrok.oauth.identity.email in ['[email protected]', '[email protected]'])"
actions:
- type: deny
config:
status_code: 403
共享密钥(适用于不会使用身份提供商(IdP)登录的人员——例如外部客户端,或没有公司账户的审核者):
on_http_request:
- actions:
- type: basic-auth
config:
credentials:
- "reviewer:{PASSWORD}"
通过你已经信任的渠道,将 URL 和密码发给对方。如果对方的 IP 地址稳定,restrict-ips 也是一种无需共享信息的替代方案。
开放访问加固(不启用身份验证,但需要防护):
on_http_request:
- actions:
- type: rate-limit
config:
name: default-rate-limit
algorithm: sliding_window
capacity: 200
rate: "60s"
bucket_key:
- conn.client_ip
- type: owasp-crs-request
config:
on_error: halt
on_http_response:
- actions:
- type: owasp-crs-response
config:
on_error: halt
写入策略文件后,启动 ngrok:
ngrok http {PORT} --traffic-policy-file .ngrok/traffic-policy.yml &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1
使用特定域名时,添加 --url https://{DOMAIN}。
要分享开发服务器吗? Vite、Next 和 webpack 会拒绝 Host 标头不是 localhost 的请求,而且它们的热重载 WebSocket 也需要允许 ngrok 域名。在分享 URL 前完成设置——请参阅 references/TROUBLESHOOTING.md。
步骤 3:处理错误
如果流量策略操作因套餐限制而失败:
- 告知用户需要升级才能使用的具体操作
- 提议从策略中移除该操作并重试
- 不要建议改用云端点作为变通方案
步骤 4:持久化配置(如果用户需要)
将以下文件保存到项目中:
.ngrok/traffic-policy.yml——策略(如果配置了安全防护).ngrok/expose.sh:
#!/bin/bash
set -e
echo "Your service will be at: https://{DOMAIN}"
ngrok http {PORT} --url https://{DOMAIN} --traffic-policy-file .ngrok/traffic-policy.yml
如果没有策略,请省略 --traffic-policy-file。如果没有特定域名,请省略 --url。
还可以选择在 package.json 中添加:
{ "scripts": { "tunnel": "bash .ngrok/expose.sh" } }
拆除
pkill ngrok
非 HTTP 服务(TCP)
对于 SSH、RDP 或数据库,请使用 ngrok tcp,而不是 ngrok http。
ngrok tcp {PORT} &
sleep 3
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*"' | head -1
ngrok 会返回类似 tcp://1.tcp.ngrok.io:12345 的地址。客户端需要分别使用主机名和端口:
# local sshd on port 22, reached through the address above
ssh -p 12345 {USER}@1.tcp.ngrok.io
常见端口:SSH 22、RDP 3389、PostgreSQL 5432、MySQL 3306。
每次重启后,地址都会变化。 如需使用固定地址,请先预留。ngrok 会分配主机名和端口——与域名不同,你无法自行选择:
ngrok api reserved-addrs create --description "SSH for {NAME}" --region us
ngrok tcp {PORT} --url tcp://{ADDR}
预留 TCP 地址需要付费套餐,且在删除前会持续计费。
这里的访问控制方式有所不同。 OAuth 和 OWASP 仅适用于 HTTP,在此处无法使用。TCP 策略在 on_tcp_connect 阶段运行,通常使用 restrict-ips 进行控制:
on_tcp_connect:
- actions:
- type: restrict-ips
config:
enforce: true
allow:
- 203.0.113.0/24
以相同方式附加策略:ngrok tcp {PORT} --traffic-policy-file .ngrok/traffic-policy.yml
云端端点(高级)
仅当用户明确需要在 Agent 停止后仍然有效的 URL 时才使用(例如,用于 Webhook 或长期集成)。
需要 API 密钥:ngrok config add-api-key <KEY>(从 https://dashboard.ngrok.com/api-keys 获取)
- 预留域名:
ngrok api reserved-domains create --domain "{DOMAIN}" - 创建云端端点,并使用包含
forward-internal作为最后一项操作的流量策略:
ngrok api endpoints create --url "https://{DOMAIN}" --bindings public --traffic-policy "$(cat .ngrok/traffic-policy.yml)"
流量策略必须以以下内容结尾:
- type: forward-internal
config:
url: https://{NAME}.internal
- 启动内部 Agent:
ngrok http {PORT} --url https://{NAME}.internal - 拆除:
ngrok api endpoints delete {ENDPOINT_ID}
相关技能
此技能用于为服务提供公共 URL。相邻任务各有专门技能——请移交处理,而不是在此处重新实现:
- 一般情况下的身份验证、速率限制、IP 规则或维护页面 —
secure-endpoint。(在此处的步骤 2 中处理与指定人员共享预览。) - 需要接收 Webhook —
receive-webhooks可在边缘验证提供商签名,并使接收端无需暴露在公共互联网中。 - 这是一个 MCP 服务 —
run-mcp-gateway负责处理各提供商的凭据。 - 由 controlplane 为每个沙箱、租户或设备创建一个端点 —
provision-sandbox-access。 - 出现故障(
ERR_NGROK_*,通过 URL 访问时返回 400,但在 localhost 上正常)—troubleshoot-ngrok。 - 设置或身份验证问题 —
ngrok-setup。
有关底层模型——端点类型、HTTP 与 TCP 的区别,以及完整的 Traffic Policy 操作集——请参阅 ngrok-engine。有关如何在 CLI 以外的平台(SDK、REST API、Terraform、Kubernetes)上应用配置,请参阅 ngrok-surfaces。