#!/bin/bash set -euo pipefail ZARYA_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" source "${ZARYA_DIR}/lib/common.sh" TARGET_IP="" ALIAS="" PORT="${SRV_DEFAULT_PORT:-1488}" USER_NAME="${SRV_DEFAULT_USER:-atlas}" TCP_PORTS="${SRV_DEFAULT_TCP_PORTS:-1488 80 443}" UDP_PORTS="${SRV_DEFAULT_UDP_PORTS:-51820}" UFW_IN="${SRV_UFW_INCOMING:-deny}" UFW_OUT="${SRV_UFW_OUTGOING:-allow}" UFW_FWD="${SRV_UFW_FORWARD:-deny}" UFW_APP="${SRV_UFW_APPLICATION:-skip}" ENABLE_BBR="${SRV_ENABLE_BBR:-true}" DISABLE_IPV6="${SRV_DISABLE_IPV6:-true}" DISABLE_ICMP="${SRV_DISABLE_ICMP:-false}" VERIFY_GATE="false" PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGY8TEByHoDFNsy18VG6BJALc8HUYeoKZz2PeKMyKMND atlas@core" while [[ $# -gt 0 ]]; do case "$1" in --verify|--test|-v) VERIFY_GATE="true" shift ;; --port) PORT="$2" shift 2 ;; --user) USER_NAME="$2" shift 2 ;; --tcp) TCP_PORTS="$2" shift 2 ;; --udp) UDP_PORTS="$2" shift 2 ;; --disable-icmp) DISABLE_ICMP="true" shift ;; --enable-icmp) DISABLE_ICMP="false" shift ;; --disable-ipv6) DISABLE_IPV6="true" shift ;; --enable-ipv6) DISABLE_IPV6="false" shift ;; --no-bbr) ENABLE_BBR="false" shift ;; --help|-h) echo "Использование: z srv-init [ALIAS] [--verify] [--port N] [--user NAME] [--tcp 'PORTS'] [--udp 'PORTS'] [--disable-icmp] [--disable-ipv6] [--no-bbr]" exit 0 ;; *) if [[ -z "${TARGET_IP}" ]]; then TARGET_IP="$1" elif [[ -z "${ALIAS}" ]]; then ALIAS="$1" fi shift ;; esac done if [[ -z "${TARGET_IP}" ]]; then log_err "IP-адрес целевого сервера обязателен. Введите 'z srv-init --help'." exit 1 fi if [[ -z "${ALIAS}" ]]; then LAST_OCTET="${TARGET_IP##*.}" ALIAS="n${LAST_OCTET}.srv" fi log_info "Инициализация ноды ${ALIAS} (${TARGET_IP}:${PORT})..." ssh -o StrictHostKeyChecking=accept-new -p 22 "root@${TARGET_IP}" "bash -s" << REMOTE_EOF set -euo pipefail id -u "${USER_NAME}" &>/dev/null || useradd -m -s /bin/bash -G sudo "${USER_NAME}" mkdir -p "/home/${USER_NAME}/.ssh" echo "${PUBKEY}" > "/home/${USER_NAME}/.ssh/authorized_keys" chmod 700 "/home/${USER_NAME}/.ssh" chmod 600 "/home/${USER_NAME}/.ssh/authorized_keys" chown -R "${USER_NAME}:${USER_NAME}" "/home/${USER_NAME}/.ssh" echo "${USER_NAME} ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/${USER_NAME}" chmod 440 "/etc/sudoers.d/${USER_NAME}" if systemctl is-active --quiet ssh.socket 2>/dev/null; then systemctl disable --now ssh.socket fi rm -rf /etc/ssh/sshd_config.d/*.conf cat << SSHEOF > /etc/ssh/sshd_config Port ${PORT} PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-password PubkeyAuthentication yes X11Forwarding no AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server SSHEOF systemctl enable --now ssh.service systemctl restart ssh.service which ufw >/dev/null 2>&1 || (DEBIAN_FRONTEND=noninteractive apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y ufw) ufw --force reset ufw default ${UFW_IN} incoming ufw default ${UFW_OUT} outgoing ufw default ${UFW_FWD} forward sed -i -E 's/^DEFAULT_APPLICATION_POLICY=.*/DEFAULT_APPLICATION_POLICY="'${UFW_APP}'"/' /etc/default/ufw || true if [[ "${DISABLE_IPV6}" == "true" ]]; then sed -i -E 's/^IPV6=.*/IPV6=no/' /etc/default/ufw || true fi for p in ${TCP_PORTS}; do ufw allow "\${p}/tcp" done for p in ${UDP_PORTS}; do ufw allow "\${p}/udp" done ufw --force enable rm -f /etc/sysctl.d/99-atlas.conf touch /etc/sysctl.d/99-atlas.conf if [[ "${ENABLE_BBR}" == "true" ]]; then printf "net.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\n" >> /etc/sysctl.d/99-atlas.conf fi if [[ "${DISABLE_IPV6}" == "true" ]]; then printf "net.ipv6.conf.all.disable_ipv6 = 1\nnet.ipv6.conf.default.disable_ipv6 = 1\nnet.ipv6.conf.lo.disable_ipv6 = 1\n" >> /etc/sysctl.d/99-atlas.conf fi if [[ "${DISABLE_ICMP}" == "true" ]]; then printf "net.ipv4.icmp_echo_ignore_all = 1\n" >> /etc/sysctl.d/99-atlas.conf fi sysctl --system >/dev/null 2>&1 || true REMOTE_EOF SSH_CONFIG="${HOME}/.ssh/config" if ! grep -q "Host.*${ALIAS}" "${SSH_CONFIG}" 2>/dev/null; then printf "\nHost %s\n Hostname %s\n" "${ALIAS}" "${TARGET_IP}" >> "${SSH_CONFIG}" fi if [[ "${VERIFY_GATE}" == "true" ]]; then log_warn "Включен режим ручного подтверждения." echo "Откройте соседний терминал и выполните: ssh ${ALIAS}" read -r -p "Подключение успешно? [y/N]: " CONFIRM if [[ "${CONFIRM}" != "y" && "${CONFIRM}" != "Y" ]]; then log_err "Подтверждение отклонено оператором. Откат конфигурации..." ssh -o ConnectTimeout=10 -p "${PORT}" -i "${RAM_KEY}" "${USER_NAME}@${TARGET_IP}" "sudo ufw disable && sudo sed -i -E 's/^Port .*/Port 22/' /etc/ssh/sshd_config && sudo systemctl restart ssh.service" || true log_warn "Откат завершен: порт 22 возвращен, UFW выключен." exit 1 fi fi log_info "Автоматическая валидация ноды ${ALIAS}..." ssh -o ConnectTimeout=5 "${ALIAS}" "hostname" log_ok "Сервер ${ALIAS} успешно инициализирован и верифицирован."