自托管中继需先复制 .env.example 为 .env 再执行 docker compose up;--name 短域名被占用时只会输出带以太坊地址的身份绑定 URL;中继仍属信任边界,持证书私钥的恶意中继可冒充端点且自检只抽样连接

portal-tunnel
gosudaMIT活跃维护自托管的内网穿透工具,通过去信任中继把本地服务发布到 agentic web,支持端到端加密和 NAT 穿透,可作为 ngrok 替代。
Publishes localhost services to the agentic web through self-hostable, trustless relays.
curl -fsSL https://github.com/gosuda/portal-tunnel/releases/latest/download/install.sh | bash
portal expose 3000README 未说明
自托管中继隧道,把本地服务发布到公网,无需端口转发和账号
自托管的内网穿透工具,通过去信任中继把本地服务发布到 agentic web,支持端到端加密和 NAT 穿透,可作为 ngrok 替代。
核心能力
- 用一条命令启动自托管中继,支持公开与社区中继多路故障切换
- 未缓存 HTTPS 流量的 TLS 在本地隧道进程终结,中继只转发密文
- 原生自检比对 TLS 密钥材料,--ban-mitm 可封禁可疑中继
- 用本地 secp256k1 身份文件认证,无需账号和 API Key
- 支持 HTTP 路由挂载、裸 TCP 端口暴露和 IVNP 覆盖网络回程
容易踩的坑
- v2.7.4最新正式版2026-11-09 · 2026-11-09 10:53 UTC
What's Changed
- refactor: clarify package ownership and consolidate lifecycle tests by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/735
- fix(relay): issue a local certificate that Safari accepts by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/736
- feat(frontend): add mini sidebar and rename You section to Host by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/737
- refactor: consolidate relay policy and configuration ownership by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/738
- feat(portal): preserve tunnel started_at and simplify directory background by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/739
- feat(relay): accept tunnels only from listed networks by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/741
- docs(plugins): bring the agent skill references up to v2.7.3 by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/734
- feat(frontend): browser-style card header with safari compact tab and stable sorting by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/743
- revert(frontend): remove browser window header from server card by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/745
- style(frontend): display server card title and actions in single row without owner and duration by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/749
- refactor(tunnel): simplify configuration, routing, and relay status by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/747
- refactor(plugins): split portal-deploy into portal-tunnel and portal-relay by @gormes-agent[bot] in https://github.com/gosuda/portal-tunnel/pull/748
- feat(relay): default identity stream bandwidth to 1 MiB/s by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/751
- docs(plugins): add webhook/Discord and AI agent web UI guidance to portal-expose by @gormes-agent[bot] in https://github.com/gosuda/portal-tunnel/pull/752
- feat(frontend): replace landscape placeholders with identity blockies thumbnails by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/753
- feat(frontend): replace blockies with deep night sky constellation thumbnails by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/757
Full Changelog: https://github.com/gosuda/portal-tunnel/compare/v2.7.3...v2.7.4
- v2.7.32026-11-07 · 2026-11-07 20:05 UTC
查看更新说明
What's Changed
- fix(auth): hold sessions to the hosts a tunnel holds by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/731
- chore(release): bump version to v2.7.3 by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/733
Full Changelog: https://github.com/gosuda/portal-tunnel/compare/v2.7.2...v2.7.3
- v2.7.22026-11-07 · 2026-11-07 08:12 UTC
查看更新说明
What's Changed
- feat(portal): add relay stats snapshot as the first step of #665 by @dalbodeule in https://github.com/gosuda/portal-tunnel/pull/704
- chore(ci): upgrade CI tool versions and fix static error lint findings by @lemon-mint in https://github.com/gosuda/portal-tunnel/pull/710
- fix: preserve error causes and reuse identity sentinels by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/709
- chore(overlay): update gosuda.org/ivnp to v0.5.2 by @gormes-agent[bot] in https://github.com/gosuda/portal-tunnel/pull/713
- fix(relay): increase the default pre-auth source burst to 100 by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/715
- feat(auth): add a SAML 2.0 application auth provider (#701) by @DPS0340 in https://github.com/gosuda/portal-tunnel/pull/716
- feat(relay): add authenticated command-owned metrics from Server.Stats() by @dalbodeule in https://github.com/gosuda/portal-tunnel/pull/708
- refactor(config): one typed tunnel configuration for the CLI, agent, and Agent API (#717) by @DPS0340 in https://github.com/gosuda/portal-tunnel/pull/718
- feat(auth): add an email magic-link application auth provider (#666) by @DPS0340 in https://github.com/gosuda/portal-tunnel/pull/720
- feat(relay): set the initial approval mode at startup (#721) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/724
- feat(sdk): report the approval wait on RelayStatus (#722) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/725
- feat(relay): bound the leases one source can hold unapproved by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/726
- fix(auth): refuse a session cookie sent from another origin (#694) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/727
- refactor(auth): move the application auth gate to sdk/appauth (#694) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/728
- feat(auth): name and document the public appauth API (#694) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/729
- fix(auth): follow-ups to email sign-in (#720) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/730
- feat(frontend): align landing and directory UI with reference design by @lemon-mint in https://github.com/gosuda/portal-tunnel/pull/712
Full Changelog: https://github.com/gosuda/portal-tunnel/compare/v2.7.1...v2.7.2
- v2.7.12026-10-30 · 2026-10-30 17:09 UTC
查看更新说明
What's Changed
- fix(gateway): ask the provider for its account chooser on the not-allowed retry by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/706
- chore(release): bump version to v2.7.1 by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/707
Full Changelog: https://github.com/gosuda/portal-tunnel/compare/v2.7.0...v2.7.1
- v2.7.02026-10-27 · 2026-10-27 15:56 UTC
查看更新说明
What's Changed
- feat(mitm): run bounded background probes for each active lease by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/647
- fix(discovery): reject conflicting signed descriptors and catalog relay evidence by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/648
- feat(auth): support credential subject revocation and harden identity headers (#651) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/656
- docs(packaging): add remote access guide for one home service (#652) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/658
- feat(auth): add standard OIDC login provider with PKCE (#651) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/657
- fix(auth): bind OIDC sessions to the configured issuer and client (#667) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/671
- feat(acme): support RFC 9773 ARI-aware certificate renewals (#643) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/660
- fix(auth): harden OIDC discovery, key fetching and token requests (#669) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/673
- fix(cli): keep AUTH_OIDC_* from enabling application auth and document OIDC for the agent and CLI (#669) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/672
- fix(auth): keep the OIDC login state within the browser limit and give sessions a minimum lifetime (#669) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/674
- fix(auth): warn at startup when the OIDC provider is not usable (#669) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/675
- feat(gateway): shared Portal shell for the credential and wallet sign-in pages (#668) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/670
- fix(tunnel): skip the OIDC provider warning while stopping and name the tunnel (#669) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/676
- refactor(auth): resolve the application auth configuration in one place (#669) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/677
- feat(acme): support configurable ACME CA directory URL (#643) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/661
- feat(x402): add Nano payment network to paid routes by @dhyabi2 in https://github.com/gosuda/portal-tunnel/pull/688
- fix: surface short service URLs across Portal by @gosunuts in https://github.com/gosuda/portal-tunnel/pull/681
- fix(gateway): satisfy gojgp in xnoToRaw by @lidarbtc in https://github.com/gosuda/portal-tunnel/pull/690
- feat(gateway): show HTML screens when an OIDC login fails (#668) by @lidarbtc in https://github.com/gosuda/portal-tunnel/pull/689
- fix(agent): keep ban_mitm and max_active_relays when the config is saved by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/683
- refactor(agent): split the dashboard by responsibility and keep settings rows within the terminal width by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/685
- fix(acme): provision a new certificate when the stored one has expired (#643) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/680
- feat(auth): add an opt-in proof for the identity headers by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/687
- fix(portal): serve a renewed relay certificate without a restart by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/682
- feat(agent): report and edit application sign-in through the control API by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/684
- feat(agent): create static-site tunnels through the control API by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/691
- feat(sdk): add identity-bound TLS channel binding for native clients (#653) by @rabbitson87 in https://github.com/gosuda/portal-tunnel/pull/664
- feat(agent): retro dashboard with amber and green themes, double-line frames and a key bar by @rabbitson87 in https://github.com/gosuda/portal-tunn
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Portal - Self-Hostable Relay Tunnel for Localhost
Why Portal?
Portal is an open-source tunnel runtime and relay network for publishing services to the agentic web. It exposes local apps, APIs, tools, and agents through self-hosted or public relays, keeps routing and security policy in the local tunnel process, and eliminates the need for hosted vendor accounts or credit cards.
- Self-Hostable & Open Source - Run your own relay with a single command. MIT-licensed with zero telemetry, no enterprise tiers, and no call-home.
- Anonymous Relay Network - Connect to public relays or combine self-hosted and community relays into resilient multi-relay failover pools.
- End-to-End Tenant TLS - For uncached HTTPS stream exposures, TLS terminates in your local tunnel process. Forwarding relays handle ciphertext; relay-held certificate keys remain part of the trust boundary.
- IVNP-backed Overlay Networking - Bridge reverse backhauls over an independent IVNP overlay network when enhanced routing privacy is desired.
- Built-in MITM Detection - The native self-probe compares TLS keying material on a sampled connection;
--ban-mitmblocks a relay for that exposure when exporter values differ. - No Accounts, No API Keys - Authentication uses local secp256k1 cryptographic identities (
identity.json) with SIWE challenge signing. - Native x402 Payments - Route-level micropayments using gasless Sui USDC, Casper wCSPR, or Nano XNO without traditional payment processors.
📖 Explore the Complete Product Capabilities: For the complete matrix of all 20+ supported capabilities across CLI, Agent, SDK, and Relay—including interface support and trust boundaries—see the Canonical Feature Inventory.
Comparison
| Portal | ngrok | Cloudflare Tunnel | frp | |
|---|---|---|---|---|
| Public localhost URL | Yes | Yes | Yes | Yes |
| Self-hostable | Yes | Enterprise only | No | Yes |
| Open source | MIT | No | Client only | Apache 2.0 |
| Custom domain | Yes | Paid plans | Yes | Yes |
| End-to-end tenant TLS | Yes (uncached exposures) | No | No | No |
| MITM self-probe | Yes (TLS keying material export) | No | No | No |
| Multi-relay failover | Yes | Managed | Built-in | No |
| Account required | No | Yes | Yes | No |
| Native x402 payments | Yes | No | No | No |
Quick Start
1. Expose a local service
macOS / Linux:
curl -fsSL https://github.com/gosuda/portal-tunnel/releases/latest/download/install.sh | bash
portal expose 3000
Windows (PowerShell):
$ProgressPreference = 'SilentlyContinue'
irm https://github.com/gosuda/portal-tunnel/releases/latest/download/install.ps1 | iex
portal expose 3000
Portal prints an HTTPS URL when the tunnel is ready. To get a short URL without
an Ethereum address, use --name myapp when creating the identity. When that
name is available, share https://myapp.<relay-domain>/, printed as short URL
in the readiness message (alias_url in JSON logs). The identity-bound URL is
also available; it includes the Ethereum address and supports opt-in relay
caching. If the name is already taken, Portal prints only the identity-bound URL.
An existing identity keeps its saved name; use a new --identity-path to choose
a different name. Additional common usages:
# Custom name and explicit relay
portal expose 3000 --name myapp --relays https://portal.example.com --discovery=false
# Mount multiple local services behind one domain
portal expose --name myapp \
--http-route /api=http://127.0.0.1:3001 \
--http-route /=http://127.0.0.1:5173
# Dedicated raw TCP port (Minecraft, SSH, databases)
portal expose localhost:25565 --name minecraft --tcp
# Prefer an IVNP overlay backhaul path
portal expose 3000 --overlay
2. Use the local AI agent plugin
The repository includes two plugins for Codex, Claude Code, and Cursor: portal-tunnel (portal-expose and portal-connect) for publishing and reaching services, and portal-relay for running a relay:
# GitHub CLI
gh skill install gosuda/portal-tunnel portal-tunnel/portal-expose
# skills CLI
npx skills add gosuda/portal-tunnel --skill portal-expose
Ask your agent: "Expose my app on port 3000 with Portal and verify the public URL." See plugins/portal-tunnel/README.md and plugins/portal-relay/README.md for full setup instructions.
3. Manage persistent tunnels with Portal Agent
When tunnels should run continuously in the background or as a system service:
portal agent run --config config.toml
portal agent dashboard --config config.toml
See the Portal Agent Guide for configuration syntax and OS service installation.
4. Run your own relay
Deploy an open-source relay in seconds:
git clone https://github.com/gosuda/portal-tunnel
cd portal-tunnel && cp .env.example .env
docker compose up
See Deployment for DNS automation (ACME), TCP/UDP port ranges, and production policy configuration.
How End-to-End Encryption Works
The ordinary uncached forwarding path works as follows:
Browser
-> Relay SNI router (reads ClientHello/SNI, forwards tenant ciphertext)
-> Reverse session
-> Portal tunnel (completes TLS handshake locally, derives session keys)
-> Local service
- SNI Routing: The relay accepts the incoming connection and reads only the TLS ClientHello for SNI-based lease routing.
- Raw Forwarding: It forwards the raw encrypted stream over the reverse session without terminating TLS.
- Local Handshake: The Portal tunnel completes the TLS handshake locally; session keys are derived on your machine.
- Keyless Signing: For relay-hosted domains, the relay signs handshake transcripts via
/v1/sign. The relay never receives session keys. - Ciphertext Security: The relay continues forwarding ciphertext without access to tenant plaintext.
Portal minimizes relay trust; it does not yet eliminate it. A malicious relay with the certificate private key can still impersonate an endpoint, and the self-probe checks only sampled connections. See the Security Model for guarantees and exceptions, or Keyless TLS Explained for the design rationale.
Public Relay Registry
Portal includes the official public relay registry by default:
https://raw.githubusercontent.com/gosuda/portal-tunnel/main/registry.json
If you operate a public Portal relay, open a pull request to add your relay URL to registry.json.
Documentation
- Feature Inventory - Canonical inventory of all product capabilities and interfaces.
- Getting Started - Step-by-step setup and first exposure.
- Concepts - Relay and tunnel ownership, transport modes, and overlay networking.
- Security Model - Tenant TLS guarantees, relay signing authority, and cache exceptions.
- Keyless TLS Explained - Technical article on transcript signing, MITM self-probes, and delegation.
- CLI Reference - Complete command-line syntax and flag guide.
- Portal Agent - Multi-tunnel daemon and interactive dashboard.
- Self-Hosting - Running and securing your own relay instances.
- Configuration - Environment variables and configuration options.
- API Reference - Relay wire protocol and client APIs.
- Maintainer Architecture - Internal Go package ownership and data flows.
Contributing
See CONTRIBUTING.md.
License
MIT License - see LICENSE.