Files
easyai-ai-gateway/scripts/cluster/bootstrap-wireguard.sh
T
wangbo c63709d785 fix(cluster): 经宁波中继深圳香港链路
香港与深圳公网直连出现高丢包和高时延时,固定将两地 WireGuard 数据前缀经宁波转发,同时保留直接 peer 心跳。\n\n中继规则和转发状态持久化,接入与全量 WireGuard 引导脚本保持一致;链路验收仍使用端到端丢包和 RTT 硬门禁。\n\n已通过 bash -n、ShellCheck、深圳资源预检和差异检查。
2026-08-01 09:42:59 +08:00

144 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=scripts/cluster/common.sh
source "$script_dir/common.sh"
load_cluster_env
require_commands ssh scp
hosts=("$CLUSTER_NINGBO_HOST" "$CLUSTER_HONGKONG_HOST" "$CLUSTER_LOS_ANGELES_HOST")
public_endpoints=("${CLUSTER_NINGBO_HOST#*@}" "${CLUSTER_HONGKONG_HOST#*@}" "${CLUSTER_LOS_ANGELES_HOST#*@}")
wireguard_ips=(10.77.0.1 10.77.0.2 10.77.0.3)
if [[ -n $CLUSTER_SHENZHEN_HOST ]]; then
hosts+=("$CLUSTER_SHENZHEN_HOST")
public_endpoints+=("${CLUSTER_SHENZHEN_HOST#*@}")
wireguard_ips+=(10.77.0.4)
fi
public_keys=()
for host in "${hosts[@]}"; do
echo "[wireguard] preparing $host"
public_key=$(cluster_ssh "$host" 'bash -s' <<'REMOTE' | tail -n 1
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
if ! command -v wg >/dev/null 2>&1; then
apt-get update -qq
apt-get install -y -qq wireguard-tools
fi
install -d -m 0700 /etc/wireguard
if [[ ! -s /etc/wireguard/privatekey ]]; then
umask 077
wg genkey >/etc/wireguard/privatekey
fi
chmod 0600 /etc/wireguard/privatekey
wg pubkey </etc/wireguard/privatekey >/etc/wireguard/publickey
cat /etc/wireguard/publickey
REMOTE
)
[[ $public_key =~ ^[A-Za-z0-9+/]{43}=$ ]] || {
echo "invalid WireGuard public key returned by $host" >&2
exit 1
}
public_keys+=("$public_key")
done
for local_index in "${!hosts[@]}"; do
peer_arguments=()
for candidate in "${!hosts[@]}"; do
if [[ $candidate -ne $local_index ]]; then
peer_arguments+=(
"${public_keys[$candidate]}"
"${public_endpoints[$candidate]}"
"${wireguard_ips[$candidate]}"
)
fi
done
echo "[wireguard] configuring ${hosts[$local_index]} as ${wireguard_ips[$local_index]}"
cluster_ssh "${hosts[$local_index]}" bash -s -- \
"${wireguard_ips[$local_index]}" \
"${peer_arguments[@]}" <<'REMOTE'
set -euo pipefail
local_ip=$1
shift
private_key=$(cat /etc/wireguard/privatekey)
umask 077
temporary_config=$(mktemp /etc/wireguard/wg0.conf.XXXXXX)
cat >"$temporary_config" <<EOF
[Interface]
Address = ${local_ip}/24
ListenPort = 51820
PrivateKey = ${private_key}
EOF
while (( $# >= 3 )); do
cat >>"$temporary_config" <<EOF
[Peer]
PublicKey = $1
Endpoint = $2:51820
AllowedIPs = $3/32
PersistentKeepalive = 25
EOF
shift 3
done
(( $# == 0 ))
chmod 0600 "$temporary_config"
mv "$temporary_config" /etc/wireguard/wg0.conf
systemctl enable wg-quick@wg0 >/dev/null
systemctl restart wg-quick@wg0
REMOTE
done
if (( ${#hosts[@]} == 4 )); then
cluster_ssh "$CLUSTER_HONGKONG_HOST" bash -s -- \
"${public_keys[0]}" "${public_keys[3]}" <<'REMOTE'
set -euo pipefail
wg set wg0 peer "$1" allowed-ips 10.77.0.1/32,10.77.0.4/32
wg set wg0 peer "$2" allowed-ips 0.0.0.0/32
wg-quick save wg0
REMOTE
cluster_ssh "$CLUSTER_SHENZHEN_HOST" bash -s -- \
"${public_keys[0]}" "${public_keys[1]}" <<'REMOTE'
set -euo pipefail
wg set wg0 peer "$1" allowed-ips 10.77.0.1/32,10.77.0.2/32
wg set wg0 peer "$2" allowed-ips 0.0.0.0/32
wg-quick save wg0
REMOTE
cluster_ssh "$CLUSTER_NINGBO_HOST" 'bash -s' <<'REMOTE'
set -euo pipefail
sysctl -qw net.ipv4.ip_forward=1
ensure_forward_rule() {
if ! iptables -C FORWARD "$@" 2>/dev/null; then iptables -I FORWARD 1 "$@"; fi
}
ensure_forward_rule -i wg0 -o wg0 -s 10.77.0.2/32 -d 10.77.0.4/32 \
-m comment --comment easyai-wireguard-hongkong-shenzhen -j ACCEPT
ensure_forward_rule -i wg0 -o wg0 -s 10.77.0.4/32 -d 10.77.0.2/32 \
-m comment --comment easyai-wireguard-shenzhen-hongkong -j ACCEPT
netfilter-persistent save >/dev/null
REMOTE
fi
for source_index in "${!hosts[@]}"; do
for target_index in "${!hosts[@]}"; do
[[ $source_index -eq $target_index ]] && continue
cluster_ssh "${hosts[$source_index]}" \
"ping -c 3 -W 2 ${wireguard_ips[$target_index]} >/dev/null"
done
done
for host in "${hosts[@]}"; do
latest_handshake=$(cluster_ssh "$host" \
"wg show wg0 latest-handshakes | awk '\$2 > 0 { count++ } END { print count + 0 }'")
[[ $latest_handshake == $((${#hosts[@]} - 1)) ]] || {
echo "WireGuard handshake verification failed on $host" >&2
exit 1
}
done
if (( ${#hosts[@]} == 4 )); then
echo 'wireguard_bootstrap=PASS peers=4 hongkong_shenzhen_via=ningbo'
else
echo "wireguard_bootstrap=PASS peers=${#hosts[@]}"
fi