#!/bin/bash
# Funnel公网链路健康自检 + 自动恢复
# 背景: Mac本地网络变更(网关/IP变化)后, tailscale本地状态看似正常,
# 但公网中继上的Funnel注册会失效, TLS握手被掐断, 外部无法访问看板。
# 本脚本定期通过公网中继真实路径探测(强制走公网IP, 不走本机tailscale捷径),
# 全部失败时自动 tailscale down/up 重建Funnel注册。
# 由 launchd (com.hftrading.funnel-health) 每10分钟调用一次。

DOMAIN="mac-mini.taild0463a.ts.net"
TS="/Applications/Tailscale.app/Contents/MacOS/Tailscale"
LOGDIR="/Users/jugelizi/Library/Logs/hftrading"
LOG="$LOGDIR/funnel-health.log"
STAMP=$(date '+%Y-%m-%d %H:%M:%S')

mkdir -p "$LOGDIR"
log(){ echo "[$STAMP] $1" >> "$LOG"; }

# 1. 公网DNS解析真实中继IP(绕过本机tailscaled的本地解析)
IPS=$( { dig +short "$DOMAIN" @223.5.5.5 2>/dev/null || dig +short "$DOMAIN" @8.8.8.8 2>/dev/null; } \
  | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | sort -u )
if [ -z "$IPS" ]; then
  # 公网DNS都失败=本机断网, 此时恢复无意义
  log "公网DNS解析失败, 跳过检查(本机可能断网)"
  exit 0
fi

# 2. 探测: 逐个公网中继测TLS+HTTP(任意一个通=健康; 健康时不写日志防膨胀)
check_all(){
  local ip code
  for ip in $IPS; do
    code=$(curl -s -o /dev/null -w '%{http_code}' -m 15 \
      --resolve "$DOMAIN:443:$ip" "https://$DOMAIN/" 2>/dev/null)
    [ "$code" = "200" ] && return 0
  done
  return 1
}

if check_all; then
  exit 0
fi

log "公网链路异常(中继 $(echo $IPS | tr '\n' ' ') 全部探测失败), 执行恢复: tailscale down/up"

# 3. 恢复: 重建连接触发Funnel重新注册
"$TS" down >> "$LOG" 2>&1
sleep 5
"$TS" up >> "$LOG" 2>&1
sleep 12

# 4. 复测确认
if check_all; then
  log "恢复成功, 公网Funnel链路已恢复"
else
  log "恢复后仍失败, 需人工介入(可查 $LOG 与 tailscale status)"
fi
exit 0
