树莓派放家里宽带上运行,希望能在外随时随地控制,但宽带又没有公网 IP,怎么从外网访问内网的树莓派呢?如果手边有个公网 VPS 的话,那这个问题就可以使用反向 SSH 隧道解决了。
在树莓派终端运行下面的命令,可以建立一个简单的 SSH 反向隧道。
$ ssh -R *:2222:localhost:22 vps
vps是我的一条 ssh 连接项目。-R表示建立反向隧道,*:2222:localhost:22表示将远程2222端口上的数据转发到本地22端口,其中*表示监听远程机器上的所有 interface(默认只监听远端的 localhost,这里的星号也可写作0.0.0.0),最后启动本地 sshd 服务端。
像下面这样就能 SSH 连接到内网的树莓派了。x.x.x.x是 VPS 的 IP,-p通过端口2222连接。
$ ssh -p 2222 alarm@x.x.x.x
然后把它完善下,做成一个服务。我希望达成的目标是这样的:开机自动启动 SSH 反向隧道,SSH 连接丢失或超时则自动重连,如果断网的话就关机。
树莓派系统为 Archlinuxarm(systemd 系统都可)的话,在目录/etc/systemd/system/中新建ssh-reverse.timer
[Unit]
Description=Reverse SSH Tunnel on VPS
Wants=network-online.target
After=network-online.target network.target
[Timer]
OnActiveSec=10
[Install]
WantedBy=multi-user.target
再在这个目录中新建ssh-reverse.service
[Unit]
Description=Reverse SSH Tunnel on VPS
Wants=network-online.target
After=network-online.target network.target
OnFailure=check-internet.timer
[Service]
User=alarm
ExecStart=/usr/bin/ssh -NTC -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -o ConnectTimeout=2 -R *:2222:localhost:22 vps
RestartSec=3
Restart=always
[Install]
WantedBy=multi-user.target
然后设置断网后自动关机的逻辑。还是在此目录中新建check-internet.timer
[Unit]
Description=Check Internet Connectivity
Wants=network-online.target
After=network-online.target network.target
[Timer]
OnActiveSec=20
RemainAfterElapse=false
[Install]
WantedBy=multi-user.target
再新建check-internet.service
[Unit]
Description=Check Internet Connectivity
Wants=network-online.target
After=network-online.target network.target
StartLimitIntervalSec=20
StartLimitBurst=3
StartLimitAction=poweroff
[Service]
ExecStart=/bin/sh -c 'timeout 2 ping -c1 www.baidu.com >/dev/null'
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
最后运行# systemctl enable ssh-reverse.timer开机启动ssh-reverse.timer。另外,不要忘了安装timeout和ping这两个 shell 程序。
最后的效果:联网时,树莓派自动建立反向隧道,网络短时波动则自动重连;断网时,最长一分钟后自动关机。