mcpField
E
expose-localhost

expose-localhost

github.com/ngrok云与 DevOps15336 次安装今天更新
代码仓库

关于 expose-localhost

expose-localhost 是一项指导通过 ngrok 将本地服务公开到互联网的技能,面向需要分享开发服务或 TCP 服务的用户。它涵盖访问控制、流量策略及可复用配置。

主要功能

  1. 01通过 ngrok 建立 HTTP 或 TCP 隧道
  2. 02配置 OAuth、基本认证和 IP 限制
  3. 03为开放访问设置速率限制
  4. 04检测本地服务端口并验证配置
  5. 05保存隧道策略和启动脚本

适用场景

  1. 01向评审者分享受保护的开发预览
  2. 02临时开放 SSH 或数据库连接
  3. 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:处理错误

如果流量策略操作因套餐限制而失败:

  1. 告知用户需要升级才能使用的具体操作
  2. 提议从策略中移除该操作并重试
  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 获取)

  1. 预留域名:ngrok api reserved-domains create --domain "{DOMAIN}"
  2. 创建云端端点,并使用包含 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
  1. 启动内部 Agent:ngrok http {PORT} --url https://{NAME}.internal
  2. 拆除: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。

评论

支持 Markdown