跳转至

PortPilot

一个轻量的 Windows 本地服务发布工具,让只在 localhost 上运行的网站和 Web 服务,可以按需要提供给手机、另一台电脑、Tailnet 或互联网访问。

GitHub:BeyondXinXin/PortPilot


1 项目定位

平时开发本地 Web 工具时,经常会遇到一个很实际的问题:

程序在自己电脑上通过 localhost 访问完全正常,但想在手机、另一台电脑上打开,或者临时发给别人看,就需要重新配置监听地址、防火墙、HTTPS、反向代理,甚至还要处理 Tailscale 或公网访问。

PortPilot 就是为了解决这类问题。

它不要求修改原来的 Web 服务,而是在外面增加一层统一的访问入口。对于已经运行的 HTTP / HTTPS 服务,只需要填写原始地址;对于一个普通静态网站目录,也可以直接由 PortPilot 启动服务。

核心目标不是做一个完整的 Web Server,而是把“本机服务如何被其他设备访问”这件事统一管理起来。


2 支持的访问方式

PortPilot 将不同网络场景整理为五种模式:

模式 适用场景
IPv6 Direct 本机有公网 IPv6,希望直接从互联网访问
Tailscale Direct 仅在自己的 Tailnet 设备之间访问
Tailscale Serve Tailnet 内需要 HTTPS
Tailscale Funnel 临时把本地服务公开到互联网
Remote Bridge 远端设备也必须通过自己的 localhost 使用服务

其中 Remote Bridge 是我后来比较喜欢的一种模式。

有些本地 Web 工具不仅要求服务本身监听 127.0.0.1,前端也可能对 HostOrigin 或浏览器安全上下文比较敏感。简单把端口暴露出去并不能完全解决问题。

Remote Bridge 的思路是:

电脑 B 浏览器
http://127.0.0.1:13081
PortPilot Bridge Client
     Tailscale
PortPilot Bridge Server
电脑 A localhost 服务

这样电脑 A 上的原服务仍然只监听本机,电脑 B 的浏览器看到的也仍然是自己的 localhost


3 核心能力

PortPilot 目前主要包括:

  • 同时管理多个本地服务
  • 支持静态网站目录和已有 HTTP / HTTPS 服务
  • 每个服务可以独立启动、停止、重启
  • 自动生成并展示访问地址
  • 支持 HTTP 与 WebSocket 转发
  • localhost 目标恢复正确的 HostOrigin
  • 集成 Tailscale CLI
  • 支持 Tailscale Direct / Serve / Funnel
  • 支持两台设备之间的 Remote Bridge
  • 托盘常驻
  • 定期检查入口状态,异常时尝试恢复
  • 配置和日志统一保存在用户目录

程序关闭主窗口后仍可在系统托盘运行,比较适合这种“启动之后长期放着不管”的小工具。


4 技术实现

项目使用 Go 1.26 开发,Windows 桌面界面使用 lxn/walk

整体可以理解成三层:

桌面管理界面
    ├── 服务配置 / 状态管理
    ├── 本地 HTTP / WebSocket 转发
    └── Tailscale / Bridge 入口管理

4.1 本地反向代理

对于已经运行的 Web 服务,PortPilot 不负责启动原程序,而是在指定入口上建立转发。

除了普通 HTTP,请求链路还需要处理 WebSocket。对于目标是 localhost 的服务,会恢复后端期望的 Host,并在存在 Origin 时同步修正,避免部分 Web UI 因来源校验导致访问失败。

4.2 Tailscale 集成

Tailscale 相关功能没有重复实现自己的虚拟网络,而是直接调用本机 Tailscale CLI。

PortPilot 负责把用户看到的“访问模式”转换为对应的 Serve、Funnel 或 Tailnet 地址管理逻辑,把比较零散的命令行操作收敛到一个桌面界面里。

4.3 Remote Bridge

Remote Bridge 由服务端和客户端两部分组成。

服务端运行在真正提供 Web 服务的电脑上,客户端在远端电脑建立一个本机 127.0.0.1 入口,两端通过 Tailnet 建立连接。

这个模式的重点不是公网穿透,而是让远端程序仍然以“访问本机 localhost”的方式工作。


5 数据与部署

PortPilot 的运行数据统一放在:

%LOCALAPPDATA%\BeyondXinXin\PortPilot\
├─ config\
│  └─ services.json
├─ logs\
│  └─ PortPilot.log
└─ resources\

项目最终发布为 Windows x64 单文件程序,不需要额外安装 Go、Node.js 或 Web Server。

使用 Tailscale 相关模式时,需要电脑已经安装并登录 Tailscale。

需要注意,IPv6 Direct 和 Tailscale Funnel 都可能把服务直接暴露到互联网。PortPilot 本身不替目标应用增加账号、鉴权或限流,因此只应该公开本身就适合公开访问的服务。


6 为什么做这个项目

PortPilot 的起点其实很简单:我有越来越多只在本机运行的小型 Web 工具。

这些工具本身并不复杂,但每次想换一台电脑、用手机访问,或者临时在外面打开时,都要重新处理网络问题。

单独解决某一次很容易:

  • 改监听地址
  • 开一个 HTTP Server
  • 写一个反向代理
  • 用 Tailscale
  • 用 Funnel
  • 手工做端口转发

真正麻烦的是这些方法分散在不同工具和配置里。

所以最后干脆把它们整理成一个自己的 Windows 小工具:本地服务是什么不重要,我只选择“这一次准备让谁访问”。

这也是 PortPilot 最核心的设计思路。


7 项目状态

PortPilot 是一个面向自己日常开发场景持续使用的小工具,目前已经覆盖局域设备、Tailnet、HTTPS、公网临时分享和远端 localhost 桥接几类常见需求。

源码与 Release:

https://github.com/BeyondXinXin/PortPilot