#!/bin/bash #set -e #set -o noglob COMMAND_NAME=${COMMAND_NAME:-"conv"} PROFILES_SERVER=${PROFILES_SERVER:-"get.conv.su"} PROFILES_DIR=${PROFILES_DIR:-"volume"} # Если задана переменная SSH_KEY, вычисляем SSH_DIR на основе пути к ключу if [[ -n "$SSH_KEY" ]]; then # Проверяем, является ли путь абсолютным if [[ "$SSH_KEY" == /* ]]; then SSH_DIR=$(dirname "$SSH_KEY") else # Если путь относительный, используем стандартную директорию .ssh SSH_DIR=${SSH_DIR:-$HOME/.ssh} SSH_KEY="$SSH_DIR/$SSH_KEY" fi else # Если SSH_KEY не задан, используем стандартную директорию .ssh SSH_DIR=${SSH_DIR:-$HOME/.ssh} fi # Адрес сервера SSH для подключения REMOTE_SERVER=${REMOTE_SERVER:-"get.conv.su"} REMOTE_SERVER_PUBKEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDwsSw5tWvu8sRRDM7hIC8miv1manTN8VFK/IWI3UuSCcgv6gFCqGhuJLlBQx/oMd+a2oqr33xZkB1PmhGgJsCSoji7FYukwwf8/3DTQbmSKoKrBx5FpqWU9A2E4+eP4aItwsSNoNI73aC4hzjHu18LNJRFJIJQTIEkmT/avbRKiDZXdknoYj/XkCuW1lTFhbiV2wtOk+3tl2c63Op4kObPTxktQv8avcHv3hw7CtBhS6fEvrgzsHUlSq822lqqdXPymO08vQLAR2bF8nu4u2VkyL+WjdRclJZ5Vjvq45wqlx8cKg8npKXzjUIKCpII2kdjAR9LlVzCytmqy2IIndbtGl44Rbr4r4k7Wo2oVwouCYWEJHUswjLQi/uMVQA8gxWuSe23JENPY7NsSU2v8JLt+De1hcx4LJSB4C4os4Cn6jRmD57ecKmN64lNsg56gtItAY/if4FGKfEKKj4+WBd8V1xGHpbfVZ+//EdxyFE13kA/nZH5YycUCI/AW++y+TnuTurlNTQrp8l/NiW/RORaHc996JxoOyps6pU5ENYG4O5qnlT4RFi4ll7pQGoj+vPbbEwPfjKeR7QadaWTBSTS1SyibDGd2R5VLggOpj0gJ8yf/BH8Mb+67Qh3fnXe9x49sop3R7Xz+Kh+NqDJ8k6b8VHSFRKK3eVQvN5DIyqyKQ==" KNOWN_HOST_TEMP_FILE=$(mktemp) SSH_CONFIG_TEMP_FILE=$(mktemp) trap "rm -f $KNOWN_HOST_TEMP_FILE $SSH_CONFIG_TEMP_FILE" EXIT echo "$REMOTE_SERVER $REMOTE_SERVER_PUBKEY" > $KNOWN_HOST_TEMP_FILE echo "Host * ControlMaster auto ControlPath $SSH_DIR/%r@%h:%p " > $SSH_CONFIG_TEMP_FILE SSH_ARGS="-p 443 -F $SSH_CONFIG_TEMP_FILE -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$KNOWN_HOST_TEMP_FILE -o ConnectTimeout=15" # Переменные для хранения информации о ключах declare -A key_info # Ассоциативный массив для хранения публичных ключей valid_keys=() # Список ключей, которые могут подключиться key_count=0 # Счетчик ключей # Функция для создания нового ключа ed25519 create_new_key() { # Запрос комментария для ключа read -rp "Введите комментарий для нового ключа (например, ваш email): " key_comment if [[ -z "$key_comment" ]]; then key_comment="auto-generated key" fi local default_key_name="id_ed25519_$(date +%Y%m%d%H%M%S)" read -rp "Введите имя файла для нового ключа (без расширения) [$default_key_name]: " key_name if [[ -z "$key_name" ]]; then key_name="$default_key_name" fi local key_path="$SSH_DIR/$key_name" echo "Создание нового ключа ed25519 с комментарием: $key_comment..." ssh-keygen -t ed25519 -f "$key_path" -N "" -C "$key_comment" if [ $? -eq 0 ]; then echo "Ключ успешно создан: $key_path" echo "Публичный ключ:" cat "${key_path}.pub" return 0 else echo "Ошибка при создании ключа." return 1 fi } remote_script_exec() { # Подключение к серверу и выполнение скрипта echo "" echo "Выполняю скрипт установки с сервера $REMOTE_SERVER используя ключ $SSH_KEY_FILE..." export SSH_KEY_FILE export REMOTE_SERVER export SSH_DIR export SSH_ARGS export KNOWN_HOST_TEMP_FILE export SSH_CONFIG_TEMP_FILE export PROFILES_DIR export PROFILES_SERVER bash <(ssh -T -i "$SSH_KEY_FILE" $SSH_ARGS $REMOTE_SERVER 2>/dev/null) exit 0 } # Если переменная окружения NEW_KEY=1, создаем новый ключ и завершаем скрипт if [[ "$NEW_KEY" == "1" ]]; then create_new_key exit $? fi # Если задана переменная SSH_KEY, используем только этот ключ if [[ -n "$SSH_KEY" ]]; then # Проверка, что файл существует и является ключом ed25519 if [ -f "$SSH_KEY" ]; then if grep -q "BEGIN OPENSSH PRIVATE KEY" "$SSH_KEY"; then if ssh-keygen -l -f "$SSH_KEY" | grep -q "ED25519"; then # Вычисление публичного ключа public_key=$(ssh-keygen -y -f "$SSH_KEY" 2>/dev/null) if [ -n "$public_key" ]; then key_info["$SSH_KEY"]="$public_key" fi fi fi else echo "Ошибка: файл ключа $SSH_KEY не найден." exit 1 fi # Проверка ключа на возможность подключения result="$(ssh -T -i "$SSH_KEY" $SSH_ARGS $REMOTE_SERVER 2>&1)" if echo "$result" | grep -q "#!/bin/bash"; then valid_keys+=("$SSH_KEY") key_count=$((key_count + 1)) else echo "Ключ $SSH_KEY не может подключиться к серверу." exit 1 fi SSH_KEY_FILE=$SSH_KEY remote_script_exec else echo "Поиск ключей ed25519 в папке: ${SSH_DIR}" # Перебор всех файлов в папке .ssh for key_file in "$SSH_DIR"/*; do # Проверка, что файл является файлом, а не папкой if [ -f "$key_file" ]; then # Проверка, что файл содержит ключ формата ed25519 if grep -q "BEGIN OPENSSH PRIVATE KEY" "$key_file"; then if ssh-keygen -l -f "$key_file" | grep -q "ED25519"; then # Вычисление публичного ключа public_key=$(ssh-keygen -y -f "$key_file" 2>/dev/null) if [ -n "$public_key" ]; then key_info["$key_file"]="$public_key" fi fi fi fi done # Проверка, есть ли ключи if [ ${#key_info[@]} -eq 0 ]; then echo "В папке ${SSH_DIR} не найдено ключей формата ed25519." if [[ $- == *i* ]]; then read -rp "Хотите создать новый ключ? (y/n): " create_key if [[ "$create_key" == "y" || "$create_key" == "Y" ]]; then create_new_key exit $? else echo "Завершение работы скрипта." exit 1 fi else echo "" echo "Чтобы создать новый ключ - выполните:" echo "NEW_KEY=1 bash <(curl -sfL https://get.conv.su)" exit 0 fi fi echo "" echo "Ключи без доступа к установке:" # Проверка ключей на возможность подключения for key_file in "${!key_info[@]}"; do result="$(ssh -T -i "$key_file" $SSH_ARGS $REMOTE_SERVER 2>&1)" if echo "$result" | grep -q "#!/bin/bash"; then valid_keys+=("$key_file") key_count=$((key_count + 1)) else echo "${key_file}" echo " ${key_info["${key_file}"]}" fi done # Проверка количества ключей, которые могут подключиться if [ "$key_count" -eq 0 ]; then echo "" echo "Нет ключей, которые могут подключиться к серверу." if [[ $- == *i* ]]; then read -rp "Хотите создать новый ключ? (y/n): " create_key if [[ "$create_key" == "y" || "$create_key" == "Y" ]]; then create_new_key exit $? else echo "Завершение работы скрипта." exit 1 fi else echo "" echo "Получите доступ у администратора - сообщите ему свой публичный ключ" echo "Чтобы создать новый ключ - выполните:" echo "NEW_KEY=1 bash <(curl -sfL https://get.conv.su)" exit 0 fi elif [ "$key_count" -eq 1 ]; then echo "" echo "Найден только один ключ с доступом к установке. Используем его для подключения." selected_key="${valid_keys[0]}" echo " 1. ${valid_keys[0]}" echo " ${key_info["${valid_keys[0]}"]}" echo "" echo "Полезные команды:" echo "Не искать, сразу использовать ключ:" echo "SSH_KEY="${valid_keys[0]}" bash <(curl -sfL https://get.conv.su)" echo "curl -sfL https://get.conv.su | SSH_KEY="${valid_keys[0]}" bash" echo "Создать новый ключ:" echo "NEW_KEY=1 bash <(curl -sfL https://get.conv.su)" SSH_KEY_FILE=$(realpath "$selected_key") remote_script_exec else echo "" echo "Найдено несколько ключей. Выберите какой использовать:" # Вывод списка ключей с их публичными ключами for i in "${!valid_keys[@]}"; do echo " $((i+1)). ${valid_keys[$i]}" echo " ${key_info["${valid_keys[$i]}"]}" done # Добавляем опцию создания нового ключа echo " $((key_count+1)). Создать новый ключ ed25519" echo " NEW_KEY=1 bash <(curl -sfL https://get.conv.su)" # Запрос выбора ключа if [[ $- == *i* ]]; then while true; do read -rp "Введите номер ключа: " key_num # Проверка, что введено число if [[ ! "$key_num" =~ ^[0-9]+$ ]]; then echo "Ошибка: введите число от 1 до $((key_count+1))." continue fi # Проверка, что число в допустимом диапазоне if ((key_num < 1 || key_num > key_count+1)); then echo "Ошибка: введите число от 1 до $((key_count+1))." continue fi break done else echo "" echo "Укажите какой ключ использовать:" for i in "${!valid_keys[@]}"; do echo "curl -sfL https://get.conv.su | SSH_KEY="${valid_keys[$i]}" bash" done exit 0 fi # Если выбран вариант создания нового ключа if ((key_num == key_count+1)); then create_new_key exit $? else # Выбор ключа по номеру selected_key="${valid_keys[$((key_num-1))]}" fi SSH_KEY_FILE=$(realpath "$selected_key") remote_script_exec fi fi