PortRelay:把内网服务临时、可控地开放给同事

边缘网关 + Agent 的端口中继:Agent 主动连出到网关,把内网目标挂到网关端口上;
通过邀请链接按设备授权,可选审批,首次连接起计时,到期、闲置自动收回。

- portrelay-server:边缘网关(端口池、白名单与授权租约、邀请与授权网页)
- portrelay-agent:Agent(yamux 隧道、本地 API 与网页面板、流量统计)
- mac-native:SwiftUI 菜单栏 App
This commit is contained in:
DeepFal committed 2026-10-13 16:33:17 +08:00
commit 86e159b3f0
67 files changed
+13888

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
# 用法:PORTRELAY_TOKEN=$(openssl rand -hex 24) docker compose up -d
services:
portrelay:
image: ghcr.io/deepfal/portrelay-server:latest
# 或者从源码构建:
# build: ..
# host 网络保留访问者的真实 IP(白名单依赖它),也免去映射 1000 个端口
network_mode: host
environment:
PORTRELAY_TOKEN: ${PORTRELAY_TOKEN:?请设置 PORTRELAY_TOKEN}
# command: ["-listen", ":33000", "-port-min", "33000", "-port-max", "34000", "-state", "/var/lib/portrelay/leases.json", "-public-host", "gw.example.com"]
volumes:
- portrelay-state:/var/lib/portrelay
restart: unless-stopped
volumes:
portrelay-state:
+49
View File
@@ -0,0 +1,49 @@
#!/bin/sh
# 在 Linux 网关上安装 / 升级 PortRelay 服务端(systemd)。
#
# sudo ./install-server.sh ./portrelay-server
#
# 首次安装会生成随机 token 写入 /etc/portrelay-server.env;升级时保留已有配置。
set -eu
BIN="${1:-./portrelay-server}"
HERE="$(cd "$(dirname "$0")" && pwd)"
ENV_FILE=/etc/portrelay-server.env
UNIT=/etc/systemd/system/portrelay-server.service
if [ "$(id -u)" -ne 0 ]; then
echo "请用 root 运行:sudo $0 $*" >&2
exit 1
fi
if [ ! -x "$BIN" ]; then
echo "找不到可执行文件 $BIN" >&2
exit 1
fi
if [ -f /usr/local/bin/portrelay-server ]; then
cp /usr/local/bin/portrelay-server "/usr/local/bin/portrelay-server.bak-$(date +%Y%m%d-%H%M%S)"
fi
install -m 755 "$BIN" /usr/local/bin/portrelay-server
if [ ! -f "$ENV_FILE" ]; then
if command -v openssl >/dev/null 2>&1; then
TOKEN="$(openssl rand -hex 24)"
else
TOKEN="$(head -c 24 /dev/urandom | od -An -tx1 | tr -d ' \n')"
fi
umask 077
sed "s/^PORTRELAY_TOKEN=.*/PORTRELAY_TOKEN=$TOKEN/" "$HERE/portrelay-server.env.example" > "$ENV_FILE"
chmod 600 "$ENV_FILE"
echo "已生成 token 并写入 $ENV_FILE"
fi
install -m 644 "$HERE/portrelay-server.service" "$UNIT"
systemctl daemon-reload
systemctl enable portrelay-server >/dev/null
systemctl restart portrelay-server
sleep 1
systemctl --no-pager --lines=5 status portrelay-server || true
echo
echo "完成。查看 token:sudo grep PORTRELAY_TOKEN $ENV_FILE"
echo "防火墙需放通 TCP 33000-34000(控制端口 + 通道端口池)"
+10
View File
@@ -0,0 +1,10 @@
# 复制为 /etc/portrelay-server.env 并设为 0600:
# sudo install -m 600 deploy/portrelay-server.env.example /etc/portrelay-server.env
#
# Agent 与网关之间的共享密钥(必填)。生成方式:openssl rand -hex 24
PORTRELAY_TOKEN=change-me-to-a-long-random-string
# 额外的启动参数(可选),例如:
# -public-host gw.example.com 授权页上展示给访问者的地址(默认取访问者打开链接时用的地址)
# -trust-proxy 网关前面有可信反向代理时才开启
PORTRELAY_ARGS=
+30
View File
@@ -0,0 +1,30 @@
[Unit]
Description=PortRelay edge gateway
Documentation=https://github.com/DeepFal/PortRelay
After=network-online.target
Wants=network-online.target
[Service]
# PORTRELAY_TOKEN 等配置写在这里(权限 0600),参考 portrelay-server.env.example
EnvironmentFile=/etc/portrelay-server.env
ExecStart=/usr/local/bin/portrelay-server -listen :33000 -port-min 33000 -port-max 34000 -state /var/lib/portrelay/leases.json $PORTRELAY_ARGS
Restart=always
RestartSec=3
LimitNOFILE=65536
# 以临时系统用户运行,状态保存在 /var/lib/portrelay
DynamicUser=yes
StateDirectory=portrelay
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
LockPersonality=yes
[Install]
WantedBy=multi-user.target