FRP反向隧道实现异地SSH家用Linux

没有公网 IP,怎么从外面 SSH 登进家里那台机器

家里有台 Linux 机器,平时挂着跑点东西。人在外面想登进去看一眼、改个配置,结果它在路由器后面,没有公网 IP,SSH 直接连不上。

我这里用 frp 做反向隧道。云服务器跑 frps,家里机器跑 frpc,外面的 Mac 或 Windows 再跑一个 frpc visitor。以后在外面连自己电脑的 127.0.0.1:6000,流量会被转到家里机器的 22 端口。

这篇主线只用 stcp visitor,云服务器只需要放行 7000。这样不用把家里 SSH 映射成公网端口,少挨一些扫描。

开始前准备

先把东西备齐:

  • 一台带公网 IP 的云服务器,本文用 203.0.113.42 代替,系统示例用 Ubuntu。
  • 家里那台 Linux 机器,SSH 服务已经在 22 端口跑着。
  • 外面要连接的电脑,macOS 或 Windows 都行。
  • 云服务器安全组放行 TCP 7000
  • 一段 auth.token,云服务器、家里机器、外部电脑三边都要一致。
  • 一段 secretKey,家里机器和外部电脑的 visitor 要一致,别和 auth.token 混用。

先在云服务器和家里机器上确认 SSH 服务正常:

bash 复制代码
sudo systemctl status ssh

看到 active (running) 就行。Ubuntu 服务名是 ssh,CentOS / RHEL / Rocky 系列是 sshd,本文后面所有 ssh 服务名都相应换成 sshd

再生成两段密钥。找一台可信机器执行:

bash 复制代码
openssl rand -hex 32
openssl rand -hex 32

第一段后面填到 auth.token,第二段填到 secretKey

步骤 1 · 云服务器和家里机器安装 frp

frpsfrpc 在同一个发布包里。云服务器和家里机器都要装。

先看机器架构:

bash 复制代码
uname -m
# x86_64  -> 用 amd64
# aarch64 -> 用 arm64

下面示例用 0.61.1,安装时可以去 frp 的 GitHub release 页把版本号换成新的。云服务器和家里机器都执行:

bash 复制代码
cd /tmp
wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz
tar -xzf frp_0.61.1_linux_amd64.tar.gz
cd frp_0.61.1_linux_amd64
sudo cp frps frpc /usr/local/bin/
sudo mkdir -p /etc/frp

检查一下:

bash 复制代码
frps -v
frpc -v

能看到 0.61.1,这步就过了。

步骤 2 · 云服务器配置 frps

云服务器上写 /etc/frp/frps.toml

toml 复制代码
bindAddr = "0.0.0.0"
bindPort = 7000

auth.method = "token"
auth.token = "your-frps-token-here"

transport.tls.force = true

log.to = "/var/log/frps/frps.log"
log.level = "info"
log.maxDays = 7

your-frps-token-here 换成刚才生成的第一段密钥。

建日志目录,再用 systemd 拉起:

bash 复制代码
sudo mkdir -p /var/log/frps

sudo tee /etc/systemd/system/frps.service > /dev/null <<'EOF'
[Unit]
Description=frp server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo systemctl status frps

预期是 active (running)。日志里能看到服务启动成功:

bash 复制代码
sudo tail -n 50 /var/log/frps/frps.log

步骤 3 · 云服务器放行 7000

云厂商控制台的安全组,入站放行 TCP 7000。这一步别只改系统防火墙,云厂商安全组不放,外面一样连不进来。

如果服务器本机开了 ufw,再放一次:

bash 复制代码
sudo ufw allow 7000/tcp
sudo ufw status

预期能看到 7000/tcp ALLOW

到这里,云服务器只负责接收 frp 控制连接,不直接暴露家里 SSH。

步骤 4 · 家里机器配置 frpc

家里 Linux 上写 /etc/frp/frpc.toml

toml 复制代码
serverAddr = "203.0.113.42"
serverPort = 7000
auth.token = "your-frps-token-here"

transport.tls.enable = true
transport.poolCount = 3

[[proxies]]
name = "home-ssh-stcp"
type = "stcp"
secretKey = "your-stcp-secret-here"
localIP = "127.0.0.1"
localPort = 22

这里有三个值要换:

  • serverAddr 换成你的云服务器公网 IP。
  • auth.token 和云服务器 frps.toml 保持一字不差。
  • secretKey 换成刚才生成的第二段密钥。

transport.poolCount = 3 是为了多预建几条 TCP 连接。家用宽带 NAT 有时会清理空闲长连接,多几条能缓一下。

然后拉起家里机器上的 frpc

bash 复制代码
sudo tee /etc/systemd/system/frpc.service > /dev/null <<'EOF'
[Unit]
Description=frp client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo systemctl status frpc

看日志:

bash 复制代码
journalctl -u frpc -n 50

看到 start proxy success,并且带着 home-ssh-stcp,说明家里机器已经把 SSH 注册到云服务器。

顺手把 SSH 安全项改掉。这个建议别跳过:

bash 复制代码
sudo nano /etc/ssh/sshd_config

确认这两行是这样:

text 复制代码
PasswordAuthentication no
PermitRootLogin no

改之前要先确认你的公钥已经在家里机器的 ~/.ssh/authorized_keys 里。否则重启 SSH 后,自己可能进不去。

确认没问题再重启:

bash 复制代码
sudo systemctl restart ssh

步骤 5 · macOS 配置 visitor

Mac 这边不用开公网端口,只需要跑一个本地 frpc,把本机 127.0.0.1:6000 接到家里机器。

Intel Mac 下载 darwin_amd64

bash 复制代码
cd ~/Downloads
curl -LO https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_darwin_amd64.tar.gz
tar -xzf frp_0.61.1_darwin_amd64.tar.gz
mkdir -p ~/.frp
cp frp_0.61.1_darwin_amd64/frpc ~/.frp/frpc
chmod +x ~/.frp/frpc

Apple 芯片 Mac 把包名里的 darwin_amd64 换成 darwin_arm64

写配置文件 ~/.frp/frpc-home-ssh.toml

toml 复制代码
serverAddr = "203.0.113.42"
serverPort = 7000
auth.token = "your-frps-token-here"

transport.tls.enable = true

[[visitors]]
name = "home-ssh-mac"
type = "stcp"
serverName = "home-ssh-stcp"
secretKey = "your-stcp-secret-here"
bindAddr = "127.0.0.1"
bindPort = 6000

启动 visitor:

bash 复制代码
~/.frp/frpc -c ~/.frp/frpc-home-ssh.toml

终端会停在前台,先别关。另开一个终端连家里机器:

bash 复制代码
ssh -p 6000 youruser@127.0.0.1

youruser 是家里 Linux 的用户名,不是云服务器用户名,也不是 Mac 用户名。登进去后执行:

bash 复制代码
hostname

显示家里那台机器的主机名,就通了。

步骤 6 · Windows 配置 visitor

Windows 下载 frp_0.61.1_windows_amd64.zip,解压到 C:\frp。ARM64 Windows 下载 windows_arm64 包。

C:\frp\frpc-home-ssh.toml 写入:

toml 复制代码
serverAddr = "203.0.113.42"
serverPort = 7000
auth.token = "your-frps-token-here"

transport.tls.enable = true

[[visitors]]
name = "home-ssh-windows"
type = "stcp"
serverName = "home-ssh-stcp"
secretKey = "your-stcp-secret-here"
bindAddr = "127.0.0.1"
bindPort = 6000

PowerShell 启动 visitor:

powershell 复制代码
cd C:\frp
.\frpc.exe -c .\frpc-home-ssh.toml

同样让这个窗口开着。另开一个 PowerShell:

powershell 复制代码
ssh -p 6000 youruser@127.0.0.1

这里的 youruser 还是家里 Linux 的用户名。Windows 只是在本机开了 127.0.0.1:6000,真正认证发生在家里那台 Linux 上。

踩坑提醒

frpc 日志报 auth failed auth.token 不一致。云服务器、家里机器、Mac/Windows 三边都要填同一段,复制粘贴,别手敲。

日志里有 tls handshake 云服务器开了 transport.tls.force = true,客户端就得走 TLS。frp 从 v0.50.0 起客户端默认已开 TLS,transport.tls.enable = true 写不写都会走,配置里显式写出来是图个清楚。家里机器和 Mac/Windows 三边确认都开着就行。

家里机器日志没有 start proxy success 先看 serverAddrserverPort,再看云服务器安全组是否放行 7000。这一步没通,后面的 Mac/Windows 都不用看。

Mac/Windows visitor 连上了,但 SSH 到 127.0.0.1:6000 失败。 看 visitor 配置里的 serverName,必须等于家里机器 [[proxies]] 里的 name。这篇里两边都是 home-ssh-stcp。再看 secretKey,也必须一字不差。

连一会儿就断,偶发 connection reset 家用宽带 NAT 会清理空闲连接。transport.poolCount = 3 能缓解,真要稳再加 SSH keepalive:

bash 复制代码
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -p 6000 youruser@127.0.0.1

改完 SSH 配置后把自己锁外面。 这是最烦的坑。关密码登录前,先用密钥从另一台机器成功登录一次,再重启 ssh。没有确认公钥可用,不要急着改 PasswordAuthentication no

验证

云服务器验证 frps

bash 复制代码
sudo systemctl status frps
sudo tail -n 50 /var/log/frps/frps.log

家里机器验证 frpc

bash 复制代码
sudo systemctl status frpc
journalctl -u frpc -n 50

Mac 或 Windows 验证本地端口:

bash 复制代码
nc -zv 127.0.0.1 6000
ssh -p 6000 youruser@127.0.0.1

Windows 没有 nc 的话,用 PowerShell:

powershell 复制代码
Test-NetConnection 127.0.0.1 -Port 6000
ssh -p 6000 youruser@127.0.0.1

登进去后 hostname 是家里那台机器,整条链路就通了。

可选:不跑本地 frpc 的直连方式

如果你不想在 Mac/Windows 上跑 visitor,也可以用普通 tcp 映射,把家里机器的 22 映射到云服务器的 6022

toml 复制代码
[[proxies]]
name = "home-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6022

云服务器 frps.toml 里建议限制允许的远端端口:

toml 复制代码
allowPorts = [
  { single = 6022 },
]

然后云厂商安全组和 ufw 都放行 6022,外面直接连:

bash 复制代码
ssh -p 6022 youruser@203.0.113.42

这个方案少一个本地 visitor,连起来更省事。但代价也明显:家里 SSH 等于挂到了公网 6022,扫描器迟早会扫到。我自己更倾向于上面那套 stcp visitor,多跑一个客户端,换来云服务器不暴露业务端口。

到这里,外面用 Mac 或 Windows 都能 SSH 进家里那台 Linux。临时调试、用完即走,Cloudflare Tunnel 或 ngrok 更省事;长期挂着,又刚好有台云服务器,frp 这套更划算。

相关推荐
小比特_蓝光1 小时前
匿名管道+进程池
linux
BS_Li2 小时前
【Linux网络编程】NAT、代理服务、内网穿透
linux·网络·智能路由器
龙萱坤诺2 小时前
Claude Fable 5 重新开放:最强模型回归
大数据·运维·人工智能
tjl521314_212 小时前
Git SSH Host Key Verification Failed 问题排查与解决
运维·git·ssh
杨云龙UP3 小时前
Windows SQL Server 备份无法传输至异地共享目录排查处理
运维·服务器·数据库·windows·共享·smb·异地备份传输
Thomas.Chan3 小时前
数据中心动环监控系统架构详解
运维·网络·计算机网络·其他·系统架构·数据中心
想你依然心痛3 小时前
AtomCode 在 DevOps 场景中的实战:CI/CD 流水线脚本自动生成
运维·ci/cd·docker·devops·自动化部署·github actions
spider_xcxc3 小时前
Redis 深度实践:安全管控、性能压测与持久化分析(二)
运维·前端·redis·云计算·bootstrap·运维开发
用户029266661334 小时前
Linux 用户管理知识与应用实践(三:用户组及修改用户密码)
linux