---
date: 2026-05-14
tags: [ops, sap, ssh-tunnel, mac-bridge, production-incident]
related: docs/ops/06-sap-tunnel.md
---

# SAP 隧道挂掉时，怎么从开发机绕进内网跳板机恢复

## 背景

生产 SAP 同步报 `connect ECONNREFUSED 127.0.0.1:19443` = 内网跳板机
`10.68.100.57 (las-sdiff-01)` → 三台公网服务器的 SSH 反向隧道 `-R 19443`
全断了。文档"已知限制 1"踩中：crontab `@reboot` 不自愈，机器没重启就只能人工救。

## 不直观的点

跳板机进入通道只有公司内网。AI（在公网开发机上）平时没法触达 `10.68.100.57`，
因为唯一外部入口 `-R 19022` 反向回连也跟着挂了——同一批隧道一起死。

但**开发机和用户 Mac 之间另有一条反向 SSH 隧道**（`autossh` 维护，
`ssh -p 2222 Chentao@localhost` 落到 `Chentao-2.local`），
而 Mac 平时挂在公司 Wi-Fi/VPN 上，**Mac 能直连 `10.68.100.57:22`**。

链路：
```
Linux 开发机 (43.159.171.147)
  └─ ssh -p 2222 Chentao@localhost           # 反向隧道，autossh 自愈
       └─ ssh chentao@10.68.100.57           # Mac 的公网网络路径
            └─ 恢复 -R 19443 / -R 19022 三条隧道到三台公网服务器
```

## 前置条件（这次踩了一次坑才补上）

Mac `~/.ssh/id_ed25519.pub` 必须在跳板机 `~/.ssh/authorized_keys` 里。
本次第一次尝试时 Mac 没 key，链路网络通但 SSH 鉴权 fail；
让用户在 Mac 上 `ssh-copy-id chentao@10.68.100.57`（一次性输密码）之后才打通。

**Mac → 跳板机的 key 已经配好，下次同类故障 AI 可全自动恢复**。

## 一键恢复脚本

从开发机直接跑（链 Linux→Mac→跳板机→重建三条反代）：

```bash
ssh -p 2222 Chentao@localhost "ssh -o BatchMode=yes chentao@10.68.100.57 'bash -s'" <<'EOF'
set -e
cd ~
for tgt in "chentao@43.159.171.147:sap-tunnel-dev.log" \
           "ubuntu@43.153.69.73:sap-tunnel-uat.log" \
           "srvadmin@43.130.6.44:sap-tunnel-prod.log"; do
  user_host="${tgt%:*}"; log="${tgt##*:}"
  if pgrep -af "ssh.*-R 19443.*$user_host" >/dev/null; then
    echo "[skip] $user_host already up"
  else
    nohup ssh -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
      -o ExitOnForwardFailure=yes \
      -R 19443:localhost:19444 -R 19022:localhost:22 "$user_host" \
      >> "/home/chentao/$log" 2>&1 &
    echo "[started] $user_host (pid $!)"
  fi
done
sleep 4
pgrep -af 'ssh.*-R 19443'
EOF
```

## 验证（端到端）

- 开发机 / 生产机 `ss -tlnp | grep ':19443\|:19022'` 必须看到 listener
- 生产 `curl --max-time 5 http://localhost:19443/XISOAPAdapter/MessageServlet`
  → **HTTP 401** = 通了（401 是 SAP 要鉴权，不是隧道问题；403/200 也算通；
  连接被拒/超时 = 隧道还没起）

## 残留问题（已解决）

~~跳板机的 `@reboot` 那套不自愈是已知 tech debt~~ → **2026-05-14 同日升级完成**：
跳板机 `~/.config/systemd/user/sap-tunnel-{dev,uat,prod}.service` 用
`autossh -M 0` + systemd `Restart=always` 双层守护，老的 `@reboot` crontab
行已注释（带 `[autossh migration 2026-05-14]` 标记）。
日志改走 `journalctl --user -u sap-tunnel-prod -f`。
自愈测试：kill ssh 子进程后 ~3 秒重建。详见 `docs/ops/06-sap-tunnel.md` §3。

通用规则已沉淀至 `docs/ops/03-ops-policy.md` 「长跑后台进程的守护规则」段，
约束未来同类基础设施不允许再用 `crontab @reboot + nohup`。
