diff --git a/Node/join.sh b/Node/join.sh index 004a7e24..26796936 100755 --- a/Node/join.sh +++ b/Node/join.sh @@ -1,15 +1,18 @@ #!/bin/bash # Montana Node — авто-присоединение к сети. -# Одна команда: -# ALIAS=amsterdam LABEL=Amsterdam COUNTRY=NL HOSTING=DigitalOcean \ -# COORDS="52.37,4.89" TOKEN= bash join.sh # -# Скрипт: -# 1. Ставит xray + ufw + montana-node -# 2. Генерирует Reality keypair + UUID + shortId -# 3. Поднимает montana-node :8444 (p2p сети Montana) и xray :443 (VLESS+Reality) -# 4. Регистрирует узел в Moscow orchestrator → авто-добавление на сайт, -# в карту, peer-health всех узлов, Helsinki cascade balancer. +# Два режима: +# +# 1. Permissionless P2P-only (любой может) — узел в сети Montana, на карте /net/, +# НО НЕ в cascade VPN balancer: +# ALIAS=cologne LABEL=Köln COUNTRY=DE HOSTING=Hetzner \ +# COORDS="50.94,6.96" bash join.sh +# +# 2. Permissioned VPN-backend (нужен TOKEN от admin) — узел дополнительно +# попадает в Helsinki cascade VPN balancer: +# ROLE=vpn-backend TOKEN= \ +# ALIAS=cologne LABEL=Köln COUNTRY=DE HOSTING=Hetzner \ +# COORDS="50.94,6.96" bash join.sh set -euo pipefail : "${ALIAS:?нужен ALIAS, например: amsterdam}" @@ -17,83 +20,47 @@ set -euo pipefail : "${COUNTRY:?нужен COUNTRY 2-буквы, например: NL}" : "${HOSTING:?нужен HOSTING, например: DigitalOcean}" : "${COORDS:?нужны COORDS \"lat,lon\", например: 52.37,4.89}" -: "${TOKEN:?нужен orchestrator TOKEN (запроси у admin)}" -ROLE="${ROLE:-vpn-backend}" +ROLE="${ROLE:-node-only}" # node-only | vpn-backend ORCH="${ORCH:-https://montana.quest/vpn/node}" +HUB="${HUB:-https://hub.montana.quest/efir369999/montana/raw/branch/main}" BOOTSTRAP_FROM="${BOOTSTRAP_FROM:-cdn.montana.quest}" +if [ "$ROLE" = "vpn-backend" ]; then + : "${TOKEN:?для vpn-backend нужен TOKEN от admin}" +fi + PUBLIC_IP="$(curl -s https://api.ipify.org)" -echo "==> Montana Node join: $ALIAS ($LABEL, $COUNTRY/$HOSTING) @ $PUBLIC_IP" +echo "==> Montana Node join: $ALIAS ($LABEL, $COUNTRY/$HOSTING) role=$ROLE ip=$PUBLIC_IP" # 1. Зависимости export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq curl ca-certificates openssl unzip jq -# 2. xray + Reality keypair -curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh | bash -s -- install --without-geodata 2>&1 | tail -3 -mkdir -p /usr/local/etc/xray -UUID="$(xray uuid)" -KEYS="$(xray x25519)" -PRIV="$(echo "$KEYS" | awk '/PrivateKey/ {print $NF}')" -PUB="$(echo "$KEYS" | awk '/Password/ {print $NF}')" -SID="$(openssl rand -hex 8)" - -cat > /usr/local/etc/xray/config.json </dev/null -systemctl enable --now xray - -# 3. ufw +# 2. ufw ufw default deny incoming >/dev/null 2>&1 || true ufw default allow outgoing >/dev/null 2>&1 || true ufw allow 22/tcp >/dev/null -ufw allow 443/tcp >/dev/null -ufw allow 8444/tcp >/dev/null +ufw allow 8444/tcp >/dev/null # p2p Montana — всегда открыт +[ "$ROLE" = "vpn-backend" ] && ufw allow 443/tcp >/dev/null echo "y" | ufw enable >/dev/null -# 4. montana-node -id montana &>/dev/null || useradd -r -m -d /var/lib/montana -s /usr/sbin/nologin montana -mkdir -p /var/lib/montana /etc/montana -chown -R montana:montana /var/lib/montana && chmod 700 /var/lib/montana - +# 3. montana-node — скачать бинарь с хаба, manifest с хаба +mkdir -p /etc/montana if [ ! -x /usr/local/bin/montana-node ]; then - echo "!! /usr/local/bin/montana-node отсутствует. Скопируй с любого узла:" - echo " scp :/usr/local/bin/montana-node $PUBLIC_IP:/usr/local/bin/" - exit 2 + echo "==> Скачиваю montana-node бинарь с $HUB/Node/bin/montana-node" + curl -sL "$HUB/Node/bin/montana-node" -o /usr/local/bin/montana-node + chmod +x /usr/local/bin/montana-node fi if [ ! -f /etc/montana/genesis-manifest.json ]; then - echo "!! /etc/montana/genesis-manifest.json отсутствует. Скопируй:" - echo " scp :/etc/montana/genesis-manifest.json $PUBLIC_IP:/etc/montana/" - exit 2 + curl -sL "$HUB/Node/genesis-manifest.json" -o /etc/montana/genesis-manifest.json fi -if [ ! -f /var/lib/montana/identity.bin ]; then - sudo -u montana /usr/local/bin/montana-node init --data-dir /var/lib/montana -fi +id montana &>/dev/null || useradd -r -m -d /var/lib/montana -s /usr/sbin/nologin montana +mkdir -p /var/lib/montana +chown -R montana:montana /var/lib/montana && chmod 700 /var/lib/montana + +[ -f /var/lib/montana/identity.bin ] || sudo -u montana /usr/local/bin/montana-node init --data-dir /var/lib/montana cat > /etc/systemd/system/montana-node.service <&1 | tail -3 + mkdir -p /usr/local/etc/xray + UUID="$(xray uuid)" + KEYS="$(xray x25519)" + PRIV="$(echo "$KEYS" | awk '/PrivateKey/ {print $NF}')" + PBK="$(echo "$KEYS" | awk '/Password/ {print $NF}')" + SID="$(openssl rand -hex 8)" + cat > /usr/local/etc/xray/config.json </dev/null + systemctl enable --now xray +fi + # 5. Регистрация в orchestrator LAT="$(echo "$COORDS" | cut -d, -f1)" LON="$(echo "$COORDS" | cut -d, -f2)" -PAYLOAD=$(jq -nc \ - --arg alias "$ALIAS" \ - --arg ip "$PUBLIC_IP" \ - --arg country "$COUNTRY" \ - --arg hosting "$HOSTING" \ - --arg label "$LABEL" \ - --argjson lat "$LAT" \ - --argjson lon "$LON" \ - --arg pbk "$PUB" \ - --arg uuid "$UUID" \ - --arg sid "$SID" \ - --arg role "$ROLE" \ - --arg secret "$TOKEN" \ - '{alias:$alias,ip:$ip,country:$country,hosting:$hosting,label:$label,coords:[$lat,$lon],reality_pbk:$pbk,reality_uuid:$uuid,reality_sid:$sid,role:$role,secret:$secret}') -RESP=$(curl -sk -X POST "$ORCH/register" -H 'Content-Type: application/json' -d "$PAYLOAD") -echo "orchestrator: $RESP" +if [ "$ROLE" = "vpn-backend" ]; then + ENDPOINT="$ORCH/register" + PAYLOAD=$(jq -nc \ + --arg alias "$ALIAS" --arg ip "$PUBLIC_IP" --arg country "$COUNTRY" \ + --arg hosting "$HOSTING" --arg label "$LABEL" --argjson lat "$LAT" --argjson lon "$LON" \ + --arg pbk "$PBK" --arg uuid "$UUID" --arg sid "$SID" --arg role "$ROLE" --arg secret "$TOKEN" \ + '{alias:$alias,ip:$ip,country:$country,hosting:$hosting,label:$label,coords:[$lat,$lon],reality_pbk:$pbk,reality_uuid:$uuid,reality_sid:$sid,role:$role,secret:$secret}') +else + ENDPOINT="$ORCH/announce" + PAYLOAD=$(jq -nc \ + --arg alias "$ALIAS" --arg ip "$PUBLIC_IP" --arg country "$COUNTRY" \ + --arg hosting "$HOSTING" --arg label "$LABEL" --argjson lat "$LAT" --argjson lon "$LON" \ + '{alias:$alias,ip:$ip,country:$country,hosting:$hosting,label:$label,coords:[$lat,$lon]}') +fi + +RESP=$(curl -sk -X POST "$ENDPOINT" -H 'Content-Type: application/json' -d "$PAYLOAD") +echo "orchestrator ($ROLE → $ENDPOINT): $RESP" cat <