Document NSSM (fawno/nssm.cc rebuild) as an alternative to WinSW for wrapping frpc/ser2net, with a WinSW-vs-NSSM recommendation. Add gensiot as a native RFC 2217 client alongside pySerial, noting it is optional for a server-only deployment. Update references. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
360 lines
13 KiB
Markdown
360 lines
13 KiB
Markdown
[返回首页](../README.md)
|
||
|
||
# FRP 客户端部署指南
|
||
|
||
本文统一说明 Linux 与 Windows 串口服务器上的 `frpc` 部署。两种系统使用相同的 TOML 代理配置语义;差异只在安装目录、文件权限和服务管理方式。
|
||
|
||
## 一、共用概念与配置
|
||
|
||
### 1. 版本与连接参数
|
||
|
||
先确认现有 `frps` 的版本,再从 [FRP 官方发布页](https://github.com/fatedier/frp/releases) 下载版本匹配、架构正确的客户端。精确匹配服务端版本是最简单稳妥的部署策略。本文使用 TOML;FRP 从 v0.52.0 开始支持 TOML 配置。
|
||
|
||
从现有 `frpc` 配置或 `frps` 管理信息中取得以下值:
|
||
|
||
- `serverAddr`:`frps` 地址;
|
||
- `serverPort`:`frpc` 连接 `frps` 的控制/隧道端口,本部署为 `21315`;
|
||
- `auth.token`:用于认证代理注册的共享令牌。
|
||
|
||
### 2. 用 `.env` 保存真实地址与令牌
|
||
|
||
真实地址和令牌不应写死进 `frpc.toml`,也不应提交到版本库。frpc 支持在配置里用 Go 模板读取环境变量,因此本手册把真实值集中放在仓库根目录的 `.env`,配置文件只引用变量名。
|
||
|
||
`.env`(真实值,已被 `.gitignore` 忽略,仅保存在本地):
|
||
|
||
```dotenv
|
||
FRP_SERVER_ADDR=your-frps-host.example.com
|
||
FRP_SERVER_PORT=21315
|
||
FRP_AUTH_TOKEN=your-frps-token
|
||
```
|
||
|
||
仓库另附可提交的占位模板 `.env.example`;将其复制为 `.env` 后填入真实值即可。配置文件中对应写成 `{{ .Envs.FRP_SERVER_ADDR }}` 等模板,frpc 启动时用**进程环境**里的同名变量渲染。
|
||
|
||
注意:frpc 不会自动读取仓库根目录的 `.env`。该文件只是真实值的本地清单;部署时必须把这些变量注入 frpc 进程,具体见后文 Linux(systemd `EnvironmentFile`)与 Windows(WinSW `<env>`)小节。
|
||
|
||
串口服务推荐只监听回环地址,代理中相应使用 `localIP = "127.0.0.1"`,让本机串口服务不直接暴露到 LAN,由 `frpc` 主动连接本地监听端口并转发流量。
|
||
|
||
### 3. 单端口代理示例
|
||
|
||
Linux 和 Windows 均可使用同一份 TOML 结构;只需让 `localPort` 与本机 RFC 2217 服务实际监听端口一致。
|
||
|
||
```toml
|
||
serverAddr = "{{ .Envs.FRP_SERVER_ADDR }}"
|
||
serverPort = {{ .Envs.FRP_SERVER_PORT }}
|
||
auth.token = "{{ .Envs.FRP_AUTH_TOKEN }}"
|
||
|
||
[[proxies]]
|
||
name = "ser2net-rfc2217-1"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 2217
|
||
remotePort = 2217
|
||
```
|
||
|
||
如果 Windows 上的 hub4com 或其他串口服务监听本机端口 `7001`,只调整本地侧即可:
|
||
|
||
```toml
|
||
[[proxies]]
|
||
name = "windows-com3-rfc2217"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 7001
|
||
remotePort = 2217
|
||
```
|
||
|
||
### 4. 四端口代理示例
|
||
|
||
保留同一组顶层连接参数,为每个通道添加一个 `[[proxies]]` 块:
|
||
|
||
```toml
|
||
serverAddr = "{{ .Envs.FRP_SERVER_ADDR }}"
|
||
serverPort = {{ .Envs.FRP_SERVER_PORT }}
|
||
auth.token = "{{ .Envs.FRP_AUTH_TOKEN }}"
|
||
|
||
[[proxies]]
|
||
name = "ser2net-rfc2217-1"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 2217
|
||
remotePort = 2217
|
||
|
||
[[proxies]]
|
||
name = "ser2net-rfc2217-2"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 2218
|
||
remotePort = 2218
|
||
|
||
[[proxies]]
|
||
name = "ser2net-rfc2217-3"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 2219
|
||
remotePort = 2219
|
||
|
||
[[proxies]]
|
||
name = "ser2net-rfc2217-4"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 2220
|
||
remotePort = 2220
|
||
```
|
||
|
||
### 5. 三类端口不要混淆
|
||
|
||
- `serverPort = 21315`:FRP 控制/隧道端口,供 `frpc` 连接 `frps`,不是串口应用对外访问端口。
|
||
- `localPort`:串口服务器本机的 RFC 2217 监听端口;本指南中通常绑定在 `127.0.0.1`。
|
||
- `remotePort`:由 `frps` 主机对外打开、供远程 RFC 2217 客户端连接的应用端口。
|
||
|
||
例如 `localPort = 7001`、`remotePort = 2217` 表示 `frpc` 从本机回环端口 `7001` 取流量,而外部客户端连接 `frps` 主机的 `2217` 端口。
|
||
|
||
### 6. `frps` 侧要求
|
||
|
||
若 `frps` 配置了 `allowPorts`,必须允许所选 `remotePort`;四端口示例需加入 `2217-2220`。`frps` 所在主机的防火墙还应:
|
||
|
||
- 允许入站 TCP `21315`,供 `frpc` 建立控制连接;
|
||
- 允许每个已配置的入站 TCP `remotePort`;
|
||
- 尽量把公开串口端口限制为可信客户端源地址,而不是向整个互联网开放。
|
||
|
||
## 二、Linux 部署
|
||
|
||
### 1. 安装 `frpc`
|
||
|
||
从匹配 `frps` 版本和目标架构的 Linux FRP 发布包中解压 `frpc`,然后安装二进制并创建配置目录:
|
||
|
||
```bash
|
||
sudo install -m 0755 frpc /usr/local/bin/frpc
|
||
sudo install -d -m 0750 /etc/frp
|
||
```
|
||
|
||
### 2. 创建专用账户
|
||
|
||
```bash
|
||
getent group frpc >/dev/null || sudo groupadd --system frpc
|
||
id frpc >/dev/null 2>&1 || sudo useradd \
|
||
--system \
|
||
--gid frpc \
|
||
--home-dir /nonexistent \
|
||
--shell /usr/sbin/nologin \
|
||
frpc
|
||
```
|
||
|
||
如果账户已存在,用 `id frpc` 核实。后续 systemd 单元明确以 `frpc:frpc` 运行。
|
||
|
||
### 3. 写入配置与环境变量文件
|
||
|
||
将“共用概念与配置”中的单端口或四端口 TOML(使用 `{{ .Envs.* }}` 模板)写入 `/etc/frp/frpc.toml`:
|
||
|
||
```bash
|
||
sudoedit /etc/frp/frpc.toml
|
||
```
|
||
|
||
再把真实值放入服务器上的环境变量文件 `/etc/frp/frpc.env`(内容与仓库根目录 `.env` 相同):
|
||
|
||
```bash
|
||
sudoedit /etc/frp/frpc.env
|
||
```
|
||
|
||
```dotenv
|
||
FRP_SERVER_ADDR=your-frps-host.example.com
|
||
FRP_SERVER_PORT=21315
|
||
FRP_AUTH_TOKEN=your-frps-token
|
||
```
|
||
|
||
真实令牌只在 `frpc.env` 中;`frpc.toml` 只含模板,不含明文。仅允许 `root` 修改、`frpc` 组读取二者:
|
||
|
||
```bash
|
||
sudo chown root:frpc /etc/frp/frpc.toml /etc/frp/frpc.env
|
||
sudo chmod 0640 /etc/frp/frpc.toml /etc/frp/frpc.env
|
||
```
|
||
|
||
前台手动测试时,可先加载环境变量再运行:
|
||
|
||
```bash
|
||
set -a; . /etc/frp/frpc.env; set +a
|
||
/usr/local/bin/frpc -c /etc/frp/frpc.toml
|
||
```
|
||
|
||
### 4. 配置依赖 `ser2net` 的 systemd 服务
|
||
|
||
创建 `/etc/systemd/system/frpc.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=FRP client for ser2net RFC 2217
|
||
Wants=network-online.target ser2net.service
|
||
After=network-online.target ser2net.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=frpc
|
||
Group=frpc
|
||
EnvironmentFile=/etc/frp/frpc.env
|
||
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
|
||
Restart=on-failure
|
||
RestartSec=5s
|
||
NoNewPrivileges=true
|
||
PrivateTmp=true
|
||
ProtectHome=true
|
||
ProtectSystem=strict
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
加载、启用并启动服务:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable --now frpc
|
||
sudo systemctl status frpc --no-pager
|
||
```
|
||
|
||
查看日志:
|
||
|
||
```bash
|
||
sudo journalctl -u frpc -n 100 --no-pager
|
||
```
|
||
|
||
日志应显示每个代理均已成功注册并启动。
|
||
|
||
## 三、Windows 部署
|
||
|
||
### 1. 准备归档目录
|
||
|
||
从 [FRP 官方发布页](https://github.com/fatedier/frp/releases) 下载与已部署 `frps` 版本和 Windows 目标架构匹配的压缩包(通常为 `frp_*_windows_amd64.zip`),并采用以下布局:
|
||
|
||
```text
|
||
C:\frp\frpc.exe
|
||
C:\frp\frpc.toml
|
||
C:\frp\frpc-service.exe
|
||
C:\frp\frpc-service.xml
|
||
C:\frp\logs\
|
||
```
|
||
|
||
将“共用概念与配置”中的同一份 TOML(使用 `{{ .Envs.* }}` 模板)写入 `C:\frp\frpc.toml`。无需因为操作系统不同而改变代理结构;只需确保 `localPort` 与 Windows 上实际运行的 RFC 2217 服务监听端口一致。真实地址与令牌不写进 `frpc.toml`,而通过环境变量注入(手动测试见下方,服务方式见 WinSW 小节)。
|
||
|
||
### 2. 验证并交互运行
|
||
|
||
在安装服务前先在当前 PowerShell 会话注入环境变量,再检查配置并通过交互日志确认认证、远端端口和本地串口后端都能工作:
|
||
|
||
```powershell
|
||
Set-Location C:\frp
|
||
$env:FRP_SERVER_ADDR = 'your-frps-host.example.com'
|
||
$env:FRP_SERVER_PORT = '21315'
|
||
$env:FRP_AUTH_TOKEN = 'your-frps-token'
|
||
.\frpc.exe verify -c .\frpc.toml
|
||
.\frpc.exe -c .\frpc.toml
|
||
```
|
||
|
||
`verify` 只检查配置,不能证明认证成功、`remotePort` 已被允许或串口后端可用;这些必须从交互运行日志确认。
|
||
|
||
### 3. 使用 WinSW 安装服务
|
||
|
||
`frpc.exe` 是控制台程序,不应直接用 `sc.exe create` 作为服务安装方式。将稳定版本的 WinSW 可执行文件重命名为 `C:\frp\frpc-service.exe`,并创建 `C:\frp\frpc-service.xml`:
|
||
|
||
```xml
|
||
<service>
|
||
<id>frpc</id>
|
||
<name>FRP Client</name>
|
||
<description>FRP tunnel for the local RFC 2217 server</description>
|
||
<executable>%BASE%\frpc.exe</executable>
|
||
<arguments>-c "%BASE%\frpc.toml"</arguments>
|
||
<workingdirectory>%BASE%</workingdirectory>
|
||
<env name="FRP_SERVER_ADDR" value="your-frps-host.example.com" />
|
||
<env name="FRP_SERVER_PORT" value="21315" />
|
||
<env name="FRP_AUTH_TOKEN" value="your-frps-token" />
|
||
<logpath>%BASE%\logs</logpath>
|
||
<log mode="roll" />
|
||
<onfailure action="restart" delay="10 sec" />
|
||
<resetfailure>1 hour</resetfailure>
|
||
</service>
|
||
```
|
||
|
||
将上面三个 `<env>` 的值替换为真实值(与本地 `.env` 保持一致)。frpc 启动时会用这些进程环境变量渲染 `frpc.toml` 中的 `{{ .Envs.* }}` 模板。真实令牌因此保存在该 XML 中,而 `frpc.toml` 只含模板、无明文。
|
||
|
||
创建 XML 后立即收紧其 ACL(若服务以 LocalSystem 运行):
|
||
|
||
```bat
|
||
icacls C:\frp\frpc-service.xml /inheritance:r
|
||
icacls C:\frp\frpc-service.xml /grant:r "SYSTEM:(R)" "Administrators:(F)"
|
||
```
|
||
|
||
若改用专用服务账户,应相应调整 ACL,使该账户可读,同时避免普通本地用户读取令牌。
|
||
|
||
随后在提升权限的 PowerShell 中安装并启动:
|
||
|
||
```powershell
|
||
New-Item -ItemType Directory -Force C:\frp\logs
|
||
C:\frp\frpc-service.exe install
|
||
C:\frp\frpc-service.exe start
|
||
C:\frp\frpc-service.exe status
|
||
```
|
||
|
||
安装后可继续使用系统服务工具检查,并配置延迟自动启动:
|
||
|
||
```bat
|
||
sc.exe query frpc
|
||
sc.exe qc frpc
|
||
sc.exe config frpc start= delayed-auto
|
||
```
|
||
|
||
`sc.exe` 要求 `start=` 后保留空格。`frpc` 可以先于本地 RFC 2217 服务启动并稍后重连,但在本地监听器就绪前,外部连接会失败。延迟自动启动和 WinSW 的失败重启策略有助于处理开机时 USB 枚举较慢的情况。
|
||
|
||
### 4. 备选:使用 NSSM
|
||
|
||
[NSSM](https://nssm.cc/)(Non-Sucking Service Manager)是另一个把控制台程序包装成 Windows 服务的常用工具,特点是命令行/GUI 都很简单。上游 NSSM 本体停在 2014 年的 2.24;[fawno/nssm.cc](https://github.com/fawno/nssm.cc) 用 GitHub Actions 重新编译,提供较新的 32/64 位构建(如 `v2.24.1`,2024 年)。
|
||
|
||
安装服务并注入与 `.env` 相同的三个变量:
|
||
|
||
```bat
|
||
nssm install frpc "C:\frp\frpc.exe" -c "C:\frp\frpc.toml"
|
||
nssm set frpc AppDirectory "C:\frp"
|
||
nssm set frpc AppEnvironmentExtra FRP_SERVER_ADDR=your-frps-host.example.com FRP_SERVER_PORT=21315 FRP_AUTH_TOKEN=your-frps-token
|
||
nssm set frpc AppStdout "C:\frp\logs\frpc.log"
|
||
nssm set frpc AppStderr "C:\frp\logs\frpc.log"
|
||
nssm set frpc AppRestartDelay 10000
|
||
nssm set frpc Start SERVICE_DELAYED_AUTO_START
|
||
nssm start frpc
|
||
```
|
||
|
||
NSSM 默认在被管进程异常退出时自动重启;`AppRestartDelay` 以毫秒为单位设置重启前延迟。令牌此时保存在服务配置(注册表)中,仅管理员可读,因此 `frpc.toml` 依旧只含模板。修改可用 `nssm edit frpc` 打开 GUI,或用 `nssm set` 逐项调整。
|
||
|
||
**推荐取舍**:两者都远优于直接用 `sc.exe create` 包装控制台程序。
|
||
|
||
- 若希望服务定义可版本化、随仓库走、便于复制到多台机器——**优先 WinSW**:其 XML(含 `<env>`)是纯文本,正好与本手册的 `{{ .Envs.* }}` 模板衔接。本手册默认使用 WinSW。
|
||
- 若偏好交互式一条条命令或 GUI、不打算把服务定义纳入版本管理——**用 NSSM** 更快。
|
||
|
||
同样的两种方式也适用于把原生 `ser2net.exe` 或 `hub4com` 包装为服务,只需替换可执行文件与参数。
|
||
|
||
## 四、暴露面、防火墙与安全边界
|
||
|
||
### 1. 回环监听与 Windows 防火墙
|
||
|
||
当 RFC 2217 服务只绑定 `127.0.0.1`,且 `frpc.exe` 主动建立出站连接时,通常不需要添加 Windows 入站防火墙规则。Windows 主机只需能够出站访问 `FRPS_HOST:21315`。
|
||
|
||
只有在串口服务确实必须监听 LAN 接口时,才添加范围严格的入站规则,例如:
|
||
|
||
```powershell
|
||
New-NetFirewallRule `
|
||
-DisplayName 'RFC2217 from operations subnet' `
|
||
-Direction Inbound `
|
||
-Action Allow `
|
||
-Protocol TCP `
|
||
-LocalPort 2217 `
|
||
-RemoteAddress '192.0.2.0/24' `
|
||
-Profile Domain,Private
|
||
```
|
||
|
||
推荐的回环专用配置不要添加此规则。
|
||
|
||
### 2. `frps` 防火墙与访问控制
|
||
|
||
无论客户端运行在 Linux 还是 Windows,`frps` 主机都需要与前文一致的控制端口、`remotePort`、`allowPorts` 和防火墙配置。尤其应对每个公开串口端口设置可信源 IP 白名单;不能因为 `frpc` 已认证就认为远程串口访问者也已认证。
|
||
|
||
### 3. 令牌与 TLS 的范围
|
||
|
||
- `auth.token` 仅认证 `frpc` 向 `frps` 注册代理的权限;它不会认证连接公开 `remotePort` 的最终用户。
|
||
- FRP 传输 TLS 保护的是 `frpc` 到 `frps` 这一段。普通公开 TCP 代理不会因此自动加密或认证外部客户端到 `FRPS_HOST:remotePort` 的连接。
|
||
- 本部署直接暴露该 TCP 端口,并在 `frps` 侧集中处理访问控制(源 IP 白名单、防火墙,必要时叠加 VPN);frpc 侧只负责把本地回环监听转发出去。相关取舍见 [安全说明](security.md)。
|