guanghu-ice-heart/server-tools/zhulan-remote-cell/deploy/install-tunnel-service.sh

121 lines
3.5 KiB
Shell
Executable file

#!/usr/bin/env bash
set -euo pipefail
if [[ "$(id -u)" -ne 0 ]]; then
echo "INSTALL_REQUIRES_ROOT" >&2
exit 1
fi
FRONT_HOST="${1:-}"
KNOWN_HOSTS_SOURCE="${2:-}"
if [[ ! "$FRONT_HOST" =~ ^[0-9A-Fa-f:.]+$ ]]; then
echo "FRONT_HOST_MUST_BE_LITERAL_IP" >&2
exit 1
fi
if [[ -z "$KNOWN_HOSTS_SOURCE" || ! -f "$KNOWN_HOSTS_SOURCE" ]]; then
echo "KNOWN_HOSTS_SOURCE_INVALID" >&2
exit 1
fi
EXPECTED_HOST="${ZHULAN_EXPECTED_HOST:-VM-12-12-ubuntu}"
EXPECTED_DMI="${ZHULAN_EXPECTED_DMI:-7a500f2d-9aed-4b93-b3b8-59c87c65d031}"
ACTUAL_HOST="$(hostname)"
ACTUAL_DMI="$(tr '[:upper:]' '[:lower:]' </sys/class/dmi/id/product_uuid)"
if [[ "$ACTUAL_HOST" != "$EXPECTED_HOST" || "$ACTUAL_DMI" != "$EXPECTED_DMI" ]]; then
echo "TARGET_IDENTITY_MISMATCH" >&2
exit 1
fi
CONFIG_ROOT="/etc/guanghu/zhulan-front-tunnel"
KEY_FILE="$CONFIG_ROOT/id_ed25519"
KNOWN_HOSTS="$CONFIG_ROOT/known_hosts"
SSH_CONFIG="$CONFIG_ROOT/ssh_config"
SERVICE_FILE="/etc/systemd/system/zhulan-front-tunnel.service"
if [[ ! -f "$KEY_FILE" || ! -f "$KEY_FILE.pub" ]]; then
echo "TUNNEL_IDENTITY_NOT_PREPARED" >&2
exit 1
fi
if ! getent passwd zhulan-tunnel >/dev/null; then
echo "TUNNEL_USER_NOT_PREPARED" >&2
exit 1
fi
install -o root -g zhulan-tunnel -m 0640 "$KNOWN_HOSTS_SOURCE" "$KNOWN_HOSTS"
if ! ssh-keygen -F "$FRONT_HOST" -f "$KNOWN_HOSTS" >/dev/null; then
echo "PINNED_FRONT_HOST_KEY_MISSING" >&2
exit 1
fi
EXPECTED_FRONT_HOST_KEY="${ZHULAN_EXPECTED_FRONT_HOST_KEY:-SHA256:P2EtuYFg8hptha4s0auP4yzp+Wg+H27bw4mdqzk1Cvk}"
ACTUAL_FRONT_HOST_KEY="$(ssh-keygen -F "$FRONT_HOST" -f "$KNOWN_HOSTS" | awk 'NF && $1 !~ /^#/ {print $2, $3}' | ssh-keygen -lf - 2>/dev/null | awk '{print $2}' | head -1)"
if [[ "$ACTUAL_FRONT_HOST_KEY" != "$EXPECTED_FRONT_HOST_KEY" ]]; then
echo "PINNED_FRONT_HOST_KEY_MISMATCH" >&2
exit 1
fi
cat >"$SSH_CONFIG.tmp" <<EOF
Host guanghu-zhulan-front
HostName $FRONT_HOST
User zhulan-proxy
Port 22
IdentityFile $KEY_FILE
IdentitiesOnly yes
UserKnownHostsFile $KNOWN_HOSTS
StrictHostKeyChecking yes
BatchMode yes
RequestTTY no
ExitOnForwardFailure yes
ServerAliveInterval 30
ServerAliveCountMax 3
RemoteForward 127.0.0.1:17631 127.0.0.1:17631
EOF
chown root:zhulan-tunnel "$SSH_CONFIG.tmp"
chmod 0640 "$SSH_CONFIG.tmp"
mv "$SSH_CONFIG.tmp" "$SSH_CONFIG"
cat >"$SERVICE_FILE.tmp" <<'EOF'
[Unit]
Description=Zhulan SG003 to GZ006 loopback-only reverse proxy tunnel
After=network-online.target zhulan-remote-cell.service
Wants=network-online.target
Requires=zhulan-remote-cell.service
[Service]
Type=simple
User=zhulan-tunnel
Group=zhulan-tunnel
ExecStart=/usr/bin/ssh -F /etc/guanghu/zhulan-front-tunnel/ssh_config -NT guanghu-zhulan-front
Restart=always
RestartSec=5
UMask=0077
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
ReadOnlyPaths=/etc/guanghu/zhulan-front-tunnel
StateDirectory=guanghu/zhulan-front-tunnel
[Install]
WantedBy=multi-user.target
EOF
chown root:root "$SERVICE_FILE.tmp"
chmod 0644 "$SERVICE_FILE.tmp"
mv "$SERVICE_FILE.tmp" "$SERVICE_FILE"
systemctl daemon-reload
systemctl enable --now zhulan-front-tunnel.service
for _ in $(seq 1 20); do
if systemctl is-active --quiet zhulan-front-tunnel.service; then
systemctl show zhulan-front-tunnel.service -p ActiveState -p SubState -p MainPID
exit 0
fi
sleep 1
done
systemctl status zhulan-front-tunnel.service --no-pager >&2 || true
exit 1