用 frps + frpc 通过 SSH 远程连接家中 Mac:内网穿透与开机启动配置
家里的电脑没有公网 IP,也不想在路由器上折腾端口转发,怎样在外面通过 SSH 连回来?可以让家里的 frpc 主动连接公网服务器上的 frps,再通过 SSH 跳板访问家里的 SSH 服务。
本文以 Linux 公网服务器 + macOS 家用电脑 为例,使用 frp 0.66.0 的 TOML 配置。其他版本请核对对应文档。所有地址、用户名和认证信息均为示例,不包含实际部署信息。
一、连接结构
外出使用的电脑
│ SSH 连接公网服务器,使用 ProxyJump
▼
公网服务器 SSH → 127.0.0.1:60022(frps)
│ frp 隧道
▼
家中 Mac 的 frpc
│
▼
127.0.0.1:22(sshd)
家中 Mac 主动建立出站连接,因此通常不需要家庭公网 IP 或路由器端口映射。外出电脑只需 SSH 客户端,无须安装 frpc。
公网服务器仅开放自己的 SSH 端口和 frps 控制端口;60022 只监听服务器回环地址,通过跳板访问。
本文统一使用以下示例:
| 项目 | 示例值 |
|---|---|
| 公网服务器 IP | 203.0.113.10,文档保留地址,必须替换 |
| 公网服务器 SSH 用户 | jumpuser |
| 家中 Mac 用户 | homeuser |
| frps 控制端口 | 7000 |
| 服务器 SSH 映射端口 | 60022 |
二、配置公网服务器 frps
从 frp 官方 Releases 获取适合服务器系统、架构的版本。建议客户端和服务端先使用相同版本。
假设二进制放在 /usr/local/bin/frps,配置放在 /etc/frp/frps.toml:
bindPort = 7000
proxyBindAddr = "127.0.0.1"
auth.method = "token"
auth.token = "REPLACE_WITH_A_RANDOM_SECRET"
transport.tls.force = true
allowPorts = [{ single = 60022 }]
用密码管理器或 openssl rand -hex 32 生成随机 token,两端填写同一份。不要把真实 token 放进文章、截图或代码仓库。
proxyBindAddr 控制代理监听地址;它是服务端全局设置。已有其他代理的服务器,修改前需要检查兼容性。allowPorts 同样是全局限制,已有业务需要一并保留其端口。
先检查配置:
/usr/local/bin/frps verify -c /etc/frp/frps.toml
新建 /etc/systemd/system/frps.service:
[Unit]
Description=frp server
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
这个基础示例使用 systemd 默认的 root 身份,生产环境可进一步改为专用低权限账号;本文使用的两个 frp 端口均高于 1024。
sudo chmod 600 /etc/frp/frps.toml
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo systemctl status frps
已有服务就修改现有配置并重启,不必重复创建服务。云安全组和系统防火墙需要放行 TCP 7000 及服务器 SSH 端口;不要放行 60022。
三、开启家中 Mac 的 SSH
在「系统设置 → 通用 → 共享 → 远程登录」中开启服务,只允许需要的用户登录。
在 Mac 上检查:
nc -vz 127.0.0.1 22
外出电脑的 SSH 公钥需要分别配置到公网服务器账号、家中 Mac 账号的 ~/.ssh/authorized_keys。两次认证相互独立,可以使用不同密钥。只传公钥,不传私钥;此方案不需要开启 SSH agent 转发。
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
确认密钥登录正常后,可以再按自己的安全策略关闭密码登录。公网服务器的 SSH 服务必须允许该跳板账号转发到 127.0.0.1:60022,否则 ProxyJump 会失败。
四、安装和配置 Mac 上的 frpc
Apple Silicon 下载 darwin_arm64,Intel Mac 下载 darwin_amd64。下面以 Apple Silicon 和固定版本为例:
curl -fL -o frp.tar.gz \
https://github.com/fatedier/frp/releases/download/v0.66.0/frp_0.66.0_darwin_arm64.tar.gz
tar -xzf frp.tar.gz
sudo mkdir -p /usr/local/bin /usr/local/etc/frp /usr/local/var/log/frp
sudo install -o root -g wheel -m 755 \
frp_0.66.0_darwin_arm64/frpc /usr/local/bin/frpc
固定目录安排如下:
| 内容 | 路径 |
|---|---|
| 客户端程序 | /usr/local/bin/frpc |
| 客户端配置 | /usr/local/etc/frp/frpc.toml |
| 开机启动配置 | /Library/LaunchDaemons/com.frp.frpc.plist |
| 日志目录 | /usr/local/var/log/frp/ |
使用 sudoedit /usr/local/etc/frp/frpc.toml 写入:
serverAddr = "203.0.113.10"
serverPort = 7000
auth.method = "token"
auth.token = "REPLACE_WITH_A_RANDOM_SECRET"
transport.tls.enable = true
loginFailExit = false
[[proxies]]
name = "home-mac-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 60022
替换 IP 和 token。loginFailExit = false 让客户端在初次连接失败后继续重试。transport.tls.enable 开启 frp 传输加密;它本身不等于完成服务器证书可信校验,有证书认证要求时还应配置可信 CA 和服务器名称。SSH 自身仍需认真核验主机指纹。
sudo chmod 600 /usr/local/etc/frp/frpc.toml
sudo /usr/local/bin/frpc verify -c /usr/local/etc/frp/frpc.toml
五、使用 LaunchDaemon 实现开机启动
系统级 LaunchDaemon 可以在开机后、尚未登录桌面时启动。以下让 frpc 使用隐藏的专用账号 _frpc,避免长期以 root 运行。
下面的账号创建步骤适用于尚未创建 _frpc 用户和组的电脑。先用 dscl . -read /Users/_frpc、dscl . -read /Groups/_frpc 检查;若已有同名对象,先核实用途,不要覆盖。
将下面脚本保存为 create-frpc-user.sh,使用 sudo bash create-frpc-user.sh 执行:
#!/bin/bash
set -euo pipefail
if dscl . -read /Users/_frpc >/dev/null 2>&1 || \
dscl . -read /Groups/_frpc >/dev/null 2>&1; then
echo '_frpc 已存在,请先核实账号和组配置'
exit 1
fi
# 选择尚未使用的服务 UID/GID。
n=450
while dscl . -search /Users UniqueID "$n" | grep -q . || \
dscl . -search /Groups PrimaryGroupID "$n" | grep -q .; do
n=$((n+1))
done
dscl . -create /Groups/_frpc
dscl . -create /Groups/_frpc PrimaryGroupID "$n"
dscl . -create /Users/_frpc
dscl . -create /Users/_frpc UniqueID "$n"
dscl . -create /Users/_frpc PrimaryGroupID "$n"
dscl . -create /Users/_frpc UserShell /usr/bin/false
dscl . -create /Users/_frpc NFSHomeDirectory /var/empty
dscl . -create /Users/_frpc IsHidden 1
dscl . -create /Users/_frpc Password '*'
设置目录、配置和日志权限:
sudo chown root:_frpc /usr/local/etc/frp
sudo chmod 750 /usr/local/etc/frp
sudo chown root:_frpc /usr/local/etc/frp/frpc.toml
sudo chmod 640 /usr/local/etc/frp/frpc.toml
sudo touch /usr/local/var/log/frp/frpc.log \
/usr/local/var/log/frp/frpc.error.log
sudo chown _frpc:_frpc /usr/local/var/log/frp/frpc*.log
sudo chmod 640 /usr/local/var/log/frp/frpc*.log
注意提前创建日志并赋予服务账号写权限,否则 launchd 可能在打开日志时就报错,frpc 根本没有启动。
新建 /Library/LaunchDaemons/com.frp.frpc.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.frp.frpc</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/frpc</string>
<string>-c</string>
<string>/usr/local/etc/frp/frpc.toml</string>
</array>
<key>UserName</key><string>_frpc</string>
<key>GroupName</key><string>_frpc</string>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>ThrottleInterval</key><integer>10</integer>
<key>StandardOutPath</key><string>/usr/local/var/log/frp/frpc.log</string>
<key>StandardErrorPath</key><string>/usr/local/var/log/frp/frpc.error.log</string>
</dict>
</plist>
加载服务:
sudo chown root:wheel /Library/LaunchDaemons/com.frp.frpc.plist
sudo chmod 644 /Library/LaunchDaemons/com.frp.frpc.plist
plutil -lint /Library/LaunchDaemons/com.frp.frpc.plist
sudo launchctl enable system/com.frp.frpc
sudo launchctl bootstrap system /Library/LaunchDaemons/com.frp.frpc.plist
sudo launchctl print system/com.frp.frpc
看到 state = running 后,再检查连接和代理注册日志:
sudo tail -n 50 /usr/local/var/log/frp/frpc.log
sudo tail -n 50 /usr/local/var/log/frp/frpc.error.log
这里使用 launchd 管理重启,配置中的登录失败重试负责等待网络恢复。日志文件还应根据长期运行情况配置轮转。
六、从外网连接家中电脑
无需设置任何 SSH 别名,完整命令为:
ssh -J jumpuser@203.0.113.10:22 -p 60022 homeuser@127.0.0.1
-J 指定公网跳板,-p 60022 是服务器上的映射端口。这里的目标 127.0.0.1 由跳板服务器连接,最终通过 frp 到达家中电脑。
首次连接要分别核验公网服务器、家中电脑的 SSH 主机指纹。Mac 的 ED25519 指纹可以在本机查看:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
如果两个账号使用不同私钥,可以在外出电脑的 ~/.ssh/config 中按实际地址分别指定 IdentityFile 和 IdentitiesOnly yes;不需要为了跳板把家中电脑的私钥上传到服务器。
在 Linux 服务器检查监听:
sudo ss -lntp | grep 60022
预期为 127.0.0.1:60022,而不是 0.0.0.0:60022。
七、常见问题和维护
- 映射端口连接被拒绝:检查 frpc 是否运行、token 是否一致、代理是否注册成功,以及端口是否冲突。
administratively prohibited:检查跳板服务器 sshd 的 TCP 转发策略、账号和密钥限制。- SSH 报
Permission denied:区分是跳板账号还是家中账号认证失败,检查各自的公钥和文件权限。 - launchd 报
EX_CONFIG:既要检查 TOML,也要检查服务账号、配置目录和日志文件权限;查看系统日志获取具体原因。 - 电脑睡眠后无法连接:frp 无法替代唤醒机制。家中电脑需要保持开机、联网、系统不睡眠;显示器可以单独息屏。
- 开启 FileVault 的 Mac 重启后无法连接:可能停在启动前磁盘解锁界面,系统级 LaunchDaemon 也要等 macOS 真正启动后才能工作。
修改客户端配置后重启:
sudo /usr/local/bin/frpc verify -c /usr/local/etc/frp/frpc.toml
sudo launchctl kickstart -k system/com.frp.frpc
停止并禁用开机启动:
sudo launchctl bootout system/com.frp.frpc
sudo launchctl disable system/com.frp.frpc
重新启用时,执行前面的 enable 和 bootstrap。部署完成后建议实际重启一次,并在另一台电脑上测试;“配置已启用”和“重启后验证成功”是两项不同的检查。
