编写Bash脚本实现反向SSH隧道并上报端口与MAC地址
没问题,我帮你写一个完全适配这个场景的Bash脚本——既能让NAT/防火墙后的设备建立反向SSH隧道到公网服务器,还能自动把分配的隧道端口和设备MAC地址上报到指定端点,甚至支持断连后自动重试!
完整脚本代码
#!/bin/bash # 👇 这里是配置区,根据你的实际情况修改 REMOTE_USER="mypi" # 你在myserver上的用户名 REMOTE_SERVER="myserver" # 公网服务器的域名或IP REPORT_ENDPOINT="https://your-endpoint.com/report" # 接收上报的API端点 # SSH连接优化选项:避免首次连接确认、心跳保活、超时重连 SSH_OPTIONS="-o StrictHostKeyChecking=no -o ServerAliveInterval=30 -o ServerAliveCountMax=3" # 获取当前活跃网卡的MAC地址(优先取正在用的网卡) get_mac_address() { ip link show | awk '/UP.*ether/ {print $2; exit}' } # 建立反向SSH隧道,捕获分配的端口并触发上报 establish_tunnel() { # 启动反向SSH,把日志输出重定向到管道,用来提取端口 ssh -R "*:0:localhost:22" -N -T -o LogLevel=INFO $SSH_OPTIONS $REMOTE_USER@$REMOTE_SERVER 2>&1 | while read -r line; do # 匹配SSH日志里的端口分配信息(比如:Remote port forwarding from *:12345) if [[ $line =~ Remote\ port\ forwarding\ from\ \*:([0-9]+) ]]; then SSH_PORT="${BASH_REMATCH[1]}" echo "✅ 反向隧道已建立,远程端口: $SSH_PORT" # 拿到端口后立刻上报信息 report_tunnel_info fi done } # 向指定端点发送GET请求上报MAC和端口 report_tunnel_info() { MAC_ADDR=$(get_mac_address) # 检查MAC或端口是否为空,避免无效上报 if [[ -z $MAC_ADDR || -z $SSH_PORT ]]; then echo "❌ 无法获取MAC地址或隧道端口,跳过上报" return 1 fi echo "📤 上报信息:MAC=$MAC_ADDR,端口=$SSH_PORT" # 用curl发送请求,-s静默模式,-m 10秒超时,防止卡住 curl -s -m 10 "$REPORT_ENDPOINT?mac=$MAC_ADDR&port=$SSH_PORT" echo "" # 换行让日志更整洁 } # 主循环:隧道断开后自动重连,保证始终在线 main() { echo "🚀 启动反向SSH隧道服务..." while true; do establish_tunnel echo "⚠️ 隧道连接断开,5秒后尝试重连..." sleep 5 done } # 启动主程序 main
关键细节解释
- 配置区:把所有需要修改的参数都放在最开头,不用翻代码就能改,非常方便。
- MAC地址获取:通过过滤
UP状态的网卡,确保拿到的是当前正在使用的网卡MAC,而不是禁用的网卡。 - 端口提取:默认SSH不会输出端口信息,所以加了
-o LogLevel=INFO让它打印端口分配日志,再用正则匹配提取出端口号。 - SSH保活:
ServerAliveInterval和ServerAliveCountMax是为了防止连接被防火墙/NAT超时断开,每30秒发一次心跳,3次没回应就主动断开重连。 - 自动重连:外层的
while true循环会在隧道断开后等待5秒自动重试,确保设备只要在线就有可用的隧道。
使用必看事项
- 免密登录配置:必须先给设备配置到myserver的免密SSH登录,否则脚本会卡在输入密码环节。执行这条命令完成配置:
ssh-copy-id mypi@myserver - myserver SSH配置:要让反向隧道的端口能被外部访问(如果需要的话),需要修改myserver的
/etc/ssh/sshd_config,确保有这一行:
改完后重启sshd服务:GatewayPorts clientspecifiedsudo systemctl restart sshd - 更稳定的替代:autossh:如果需要极致稳定的连接,可以用
autossh代替原生ssh,它会自动检测连接状态并重连。只需要把脚本里的ssh命令换成autossh -M 0(-M 0表示不监听额外的监控端口)。 - 开机自启:可以把脚本做成systemd服务,让设备开机自动启动。创建
/etc/systemd/system/ssh-tunnel.service文件:
然后执行:[Unit] Description=Reverse SSH Tunnel Service After=network.target [Service] User=pi # 替换成运行脚本的用户 ExecStart=/path/to/your/tunnel-script.sh # 替换成脚本的实际路径 Restart=always RestartSec=5 [Install] WantedBy=multi-user.targetsudo systemctl daemon-reload && sudo systemctl enable --now ssh-tunnel.service
内容的提问来源于stack exchange,提问作者Black Glix
相关产品推荐
相关产品推荐

