用 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。部署完成后建议实际重启一次,并在另一台电脑上测试;“配置已启用”和“重启后验证成功”是两项不同的检查。

参考资料

浏览(26)
评论

请登录后发表观点

暂无数据