SSH-ключи: подключение без пароля — полный гайд для Linux, Windows и macOS

SSH-ключи: подключение без пароля — полный гайд
# 1. Генерируй ключ (один раз на своей машине)
ssh-keygen -t ed25519 -C "my-laptop-2026"

# 2. Скопируй на сервер (последний раз введёшь пароль)
ssh-copy-id user@IP_СЕРВЕРА

# 3. Проверь
ssh user@IP_СЕРВЕРА

Вошёл без пароля — готово. Не вошёл — читай раздел «Troubleshooting» ниже.

Время: 15 минут на полную настройку. Что нужно: терминал на клиенте (встроен в Linux/macOS/Windows 10+), один раз доступ к серверу по паролю или через консоль хостинга.

1. Диагноз: пароль уже 47-й раз за день

Снова открываешь терминал, набираешь ssh root@45.67.89.10 — и сервер снова просит пароль. Который уже сменили три раза после того, как «кто-то» поставил qwerty123.

Или пишешь скрипт деплоя — и он встаёт колом, потому что ждёт ввода с клавиатуры. А клавиатуры нет, это же автоматизация.

Или классика: новый коллега, новый проект — все обмениваются паролями в мессенджере. В открытую.

Почему SSH по паролю — это дыра

Боты сканируют 22-й порт круглосуточно. Это не преувеличение — посмотри логи любого нового сервера через час после создания:

sudo journalctl -u sshd | grep "Failed password" | wc -l
# На свежем VPS через 24 часа: сотни или тысячи попыток

Три причины, почему пароли ломаются:

  • Брутфорс — боты перебирают словари 24/7. Слабый пароль — вопрос часов
  • Утечки — пароль от сервера повторяется где-то ещё. Там база утекла — здесь взломали
  • Передача — пароль отправили в Telegram, Slack, почту. Он уже не только у тебя

Типичный сценарий потери сервера: слабый пароль, открытый 22-й порт, root доступен напрямую. Бот нашёл за 6 часов. Сервер майнит крипту или рассылает спам.

SSH-ключ украсть в 1000 раз сложнее, чем пароль. Нужно получить доступ к твоей машине и забрать приватный файл. Пароль — достаточно одной утечки базы данных где угодно.

Что получишь из этой статьи:

  • Генерация ключей: Linux, macOS, Windows (PowerShell + PuTTY)
  • Копирование на сервер — автоматически и вручную
  • SSH config — ssh prod вместо семи флагов и IP наизусть
  • SSH agent — passphrase вводишь один раз за сессию
  • Отключение пароля на сервере — с защитой от самоблокировки
  • SSH для CI/CD и автоматизации
  • Troubleshooting: 10 ошибок с решениями
  • Безопасность: fail2ban, ротация ключей, аудит

2. Как работает аутентификация по SSH-ключу

Два файла. Одна математика.

  • Приватный ключ (~/.ssh/id_ed25519) — только у тебя. Никому не давать, никуда не копировать, не отправлять. Это твоя личная подпись
  • Публичный ключ (~/.ssh/id_ed25519.pub) — кладём на серверы в ~/.ssh/authorized_keys. Утечёт — не страшно. Без приватного ключа бесполезен

Процесс аутентификации:

  1. Ты подключаешься: ssh user@server
  2. Сервер смотрит в ~/.ssh/authorized_keys — есть ли твой публичный ключ
  3. Сервер генерирует случайную строку, шифрует её твоим публичным ключом и отправляет тебе
  4. Твой SSH-клиент расшифровывает строку приватным ключом и отправляет ответ обратно
  5. Сервер проверяет — правильно ли расшифровано. Если да — пускает. Пароль не нужен
Почему это безопасно: приватный ключ никогда не покидает твою машину. По сети передаётся только результат криптографической операции — расшифрованная строка. Перехватить бесполезно.

Ed25519 vs RSA: что генерировать

Алгоритм Размер ключа Скорость Безопасность Когда использовать
Ed25519 256 бит Быстро Современный стандарт По умолчанию — всегда
RSA 4096 4096 бит Медленнее Надёжно Legacy-системы, старые SSH-серверы
RSA 2048 2048 бит Быстрее RSA Минимально приемлемо Только если нельзя иначе
ECDSA 256/384 бит Быстро Спорно (NIST-кривые) Не рекомендуется
DSA 1024 бит Устарел Никогда

Вывод: генерируй Ed25519. Если сервер не принимает (OpenSSH < 6.5, редкость) — RSA 4096.

3. Генерация SSH-ключа

Linux и macOS

# Ed25519 — современный стандарт, используй его
ssh-keygen -t ed25519 -C "work-laptop-2026"

# RSA — если сервер старый и не поддерживает Ed25519
ssh-keygen -t rsa -b 4096 -C "work-laptop-2026"

Три вопроса при генерации:

  1. Куда сохранить — нажми Enter, оставь по умолчанию (~/.ssh/id_ed25519)
  2. Passphrase — парольная фраза для дополнительной защиты приватного ключа. Можно оставить пустой (Enter). С фразой — безопаснее, но нужен ssh-agent (об этом ниже)
  3. Повтор фразы — та же или Enter
# Проверяем результат:
ls -la ~/.ssh/
# id_ed25519      ← приватный (600, никому не давать)
# id_ed25519.pub  ← публичный (644, кладём на серверы)

Windows — PowerShell / Windows Terminal

С Windows 10 1809+ OpenSSH встроен. Открывай PowerShell:

ssh-keygen -t ed25519 -C "work-windows-2026"
# Ключи сохранятся в C:\Users\ИМЯ\.ssh\
# Посмотреть публичный ключ:
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub

# Список файлов:
dir $env:USERPROFILE\.ssh\

Windows — PuTTY (если используешь PuTTY)

PuTTY использует формат .ppk. Генерация через PuTTYgen:

  1. Запусти PuTTYgen (входит в комплект putty.org)
  2. Parameters → выбери EdDSA или RSA 4096
  3. Нажми Generate, поводи мышкой — это энтропия
  4. Добавь Key comment (имя машины или твоё имя)
  5. Нажми Save private key → сохраняется .ppk
  6. Скопируй текст из поля «Public key for pasting into OpenSSH authorized_keys» — именно это поле, не кнопка «Save public key»
Нужен стандартный формат? PuTTYgen → Conversions → Export OpenSSH key. Получишь обычный приватный ключ, совместимый с ssh, git, скриптами.

4. Копирование публичного ключа на сервер

Способ 1: ssh-copy-id (рекомендуется, Linux/macOS)

# Стандартный порт:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@IP_СЕРВЕРА

# Нестандартный порт:
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 user@IP_СЕРВЕРА

Введёшь пароль последний раз. Скрипт сам добавит ключ в ~/.ssh/authorized_keys и выставит правильные права.

Способ 2: вручную (работает везде, включая Windows)

# Смотрим публичный ключ:
cat ~/.ssh/id_ed25519.pub
# Копируем — одна длинная строка, начинается с "ssh-ed25519"
# Подключаемся по паролю, на сервере выполняем:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "СЮДА_ВСТАВЬ_ПУБЛИЧНЫЙ_КЛЮЧ" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Одной командой через pipe (быстро)

cat ~/.ssh/id_ed25519.pub | ssh user@IP_СЕРВЕРА \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
   cat >> ~/.ssh/authorized_keys && \
   chmod 600 ~/.ssh/authorized_keys"

Способ 3: через панель хостинга

Hetzner, DigitalOcean, Timeweb, Selectel — все позволяют добавить SSH-ключ при создании сервера. Вставь содержимое .pub-файла в поле «SSH Key». Ключ окажется в authorized_keys автоматически на новом сервере.

Права — это не опция, это требование SSH. Если chmod 700 на ~/.ssh и chmod 600 на authorized_keys не выставлены — SSH откажет в авторизации. Молча. Без объяснений. Это причина №1 почему «ключ не работает».

Полная таблица правильных прав:

Путь Права Команда
~/.ssh/ 700 (drwx——) chmod 700 ~/.ssh
~/.ssh/authorized_keys 600 (-rw——-) chmod 600 ~/.ssh/authorized_keys
~/.ssh/id_ed25519 600 (-rw——-) chmod 600 ~/.ssh/id_ed25519
~/.ssh/id_ed25519.pub 644 (-rw-r—r—) chmod 644 ~/.ssh/id_ed25519.pub
~/.ssh/config 600 (-rw——-) chmod 600 ~/.ssh/config
~ (домашняя) 755 или 700 chmod 755 ~

5. Проверка подключения без пароля

# Подключаемся — пароль не должен спросить:
ssh user@IP_СЕРВЕРА

# Явно указать ключ (если несколько):
ssh -i ~/.ssh/id_ed25519 user@IP_СЕРВЕРА

# Подробный вывод — степень -v по уровню отчаяния:
ssh -v user@IP_СЕРВЕРА    # базовый
ssh -vv user@IP_СЕРВЕРА   # подробный
ssh -vvv user@IP_СЕРВЕРА  # полный дамп

Что должно быть: приглашение командной строки сервера без запроса пароля. В выводе -v ищи строку Authenticated to ... using "publickey" — это победа.

6. SSH config — подключение одним словом вместо IP и флагов

Вместо:

ssh -i ~/.ssh/id_ed25519 -p 2222 deploy@45.67.89.10

Пишешь просто:

ssh prod

Создай файл ~/.ssh/config:

nano ~/.ssh/config
# ============================================================
# Глобальные настройки для всех хостов
# ============================================================
Host *
    # Порядок алгоритмов (Ed25519 первым)
    HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
    # Держать соединение живым
    ServerAliveInterval 60
    ServerAliveCountMax 3
    # Добавлять <a href="https://it-apteka.com/avtomaticheskaja-ustanovka-wordpress-na-vps-za-5-minut-skript-pod-kljuch/" title="Автоматическая установка WordPress на VPS за 5 минут (Скрипт под ключ)" target="_blank" rel="noopener"  data-wpil-monitor-id="1366">ключи в агент автоматически</a>
    AddKeysToAgent yes

# ============================================================
# Продакшн-сервер
# ============================================================
Host prod
    HostName 45.67.89.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    ForwardAgent no          # на продакшн агент не пробрасываем

# ============================================================
# Staging
# ============================================================
Host staging
    HostName 45.67.89.11
    User deploy
    Port 22
    IdentityFile ~/.ssh/id_ed25519

# ============================================================
# Сервер с нестандартным ключом
# ============================================================
Host office
    HostName 192.168.1.100
    User admin
    IdentityFile ~/.ssh/id_rsa_office
    IdentitiesOnly yes      # только этот ключ, не перебирать все

# ============================================================
# Jump-хост: подключение через бастион
# ============================================================
Host internal-db
    HostName 10.0.0.50
    User dbadmin
    ProxyJump prod           # сначала на prod, потом на 10.0.0.50
    IdentityFile ~/.ssh/id_ed25519

# ============================================================
# GitHub / GitLab
# ============================================================
Host github.com
    HostName github.com
    User <a class="wpil_keyword_link" href="https://it-apteka.com/tag/git/" target="_blank"  rel="noopener" title="Git" data-wpil-keyword-link="linked"  data-wpil-monitor-id="1356">git</a>
    IdentityFile ~/.ssh/id_ed25519_github
    IdentitiesOnly yes

Host gitlab.com
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work
    IdentitiesOnly yes
# Выставляем права:
chmod 600 ~/.ssh/config

Теперь: ssh prod, ssh staging, ssh internal-db — без IP, без флагов, без боли.

IdentitiesOnly yes — важная опция. Без неё SSH перебирает все ключи из агента. Если их много — сервер может заблокировать после N попыток с ошибкой Too many authentication failures. С этой опцией — только указанный ключ.

7. SSH-agent: passphrase один раз за сессию

Если поставил passphrase на ключ — агент запомнит её на сессию. Вводишь один раз при логине, дальше всё автоматически.

Linux

# Агент обычно уже запущен в desktop-окружениях
# Проверить:
echo $SSH_AUTH_SOCK
# Если пусто — запустить:
eval "$(ssh-agent -s)"

# Добавить ключ (спросит passphrase один раз):
ssh-add ~/.ssh/id_ed25519

# Посмотреть загруженные ключи:
ssh-add -l

# Удалить все ключи из агента (выход из сессии):
ssh-add -D

Для автозапуска агента добавь в ~/.bashrc или ~/.zshrc:

# Запускать агент если не запущен:
if [ -z "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -s)"
    ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi

macOS — постоянное хранение в Keychain

# Добавить ключ с сохранением в Keychain (не надо вводить при каждом ребуте):
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

# В ~/.ssh/config добавить для постоянства:
Host *
    AddKeysToAgent yes
    UseKeychain yes          # только macOS

Windows — ssh-agent как служба

# Запустить один раз от администратора:
Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent

# Добавить ключ:
ssh-add $env:USERPROFILE\.ssh\id_ed25519

# Проверить:
ssh-add -l

8. Отключение входа по паролю на сервере

Делай это ТОЛЬКО после того, как убедился: вход по ключу работает. Открой два терминала. В одном — активная сессия на сервере. Во втором — проверь подключение по ключу. Только после этого меняй sshd_config. Иначе заблокируешь себя.
sudo nano /etc/ssh/sshd_config
# Запрет входа по паролю:
PasswordAuthentication no

# Запрет прямого входа root (root только по ключу если нужен):
PermitRootLogin prohibit-password

# Разрешить только ключи:
PubkeyAuthentication yes

# Запрет пустых паролей:
PermitEmptyPasswords no

# Отключить challenge-response:
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no

# Только SSHv2:
Protocol 2
# Проверяем конфиг ПЕРЕД перезапуском (спасает от опечаток):
sudo sshd -t
# Пустой вывод = конфиг валидный

# Перезапускаем:
sudo systemctl restart sshd

Проверь подключение в новом терминале. Всё работает — можно закрывать старую сессию.

Дополнительно: ограничение по пользователям и IP

# Разрешить SSH только конкретным пользователям:
AllowUsers deploy admin

# Или запретить конкретных:
DenyUsers guest test

# Изменить порт (небольшая защита от ботов):
Port 2222

# Разрешить только с конкретного IP (если у тебя статический):
# В /etc/hosts.allow:
# sshd: 203.0.113.10

# Или через AllowUsers с маской:
AllowUsers deploy@203.0.113.10
# После любых изменений — проверяй:
sudo sshd -t && sudo systemctl restart sshd

9. Несколько SSH-ключей для разных проектов

Один ключ на все серверы — неправильно. Скомпрометирован один сервер — скомпрометированы все.

# Ключ для GitHub:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github -C "github-personal-2026"

# Ключ для клиентского проекта:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_client -C "client-project-2026"

# Ключ для рабочего GitLab:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "work-gitlab-2026"

Прописываем в ~/.ssh/config через IdentityFile и IdentitiesOnly yes — как показано в разделе выше.

# Проверить подключение к GitHub:
ssh -T git@github.com
# Ожидаемый ответ: Hi username! You've successfully authenticated...

# Посмотреть все ключи и их fingerprint:
for f in ~/.ssh/*.pub; do
  echo "=== $f ==="
  ssh-keygen -lf "$f"
done

10. SSH-ключи для CI/CD и автоматизации

GitHub Actions, GitLab CI, Jenkins, Ansible — всё это ходит на серверы по SSH. Правила для деплой-ключей:

# Генерируем деплой-ключ (без passphrase):
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_deploy -C "ci-deploy-2026" -N ""
# -N "" означает пустая passphrase

# Приватный ключ → в секреты CI/CD (GitHub: Settings → Secrets → SSH_PRIVATE_KEY)
# Публичный ключ → на сервер в authorized_keys пользователя deploy
# В authorized_keys можно ограничить ключ — разрешить только конкретные команды:
# command="/usr/bin/rsync --server ...",no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA...

# Или ограничить по IP (CI-сервер имеет статический IP):
from="203.0.113.50",no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA...
# Пример использования в GitHub Actions:
# - name: Deploy via SSH
#   uses: appleboy/ssh-action@v1
#   with:
#     host: ${{ secrets.SERVER_HOST }}
#     username: deploy
#     key: ${{ secrets.SSH_PRIVATE_KEY }}
#     script: |
#       cd /var/www/app
#       git pull
#       systemctl restart app

Скрипт массовой выдачи доступа новому коллеге

#!/bin/bash
# add_ssh_key.sh — добавляет публичный ключ на список серверов
# Использование: ./add_ssh_key.sh "ssh-ed25519 AAAA... vasya-laptop"

NEW_KEY="$1"
SERVERS=(
    "deploy@45.67.89.10"
    "deploy@45.67.89.11"
    "admin@192.168.1.100"
)

[ -z "$NEW_KEY" ] && { echo "Использование: $0 'ssh-ed25519 AAAA... комментарий'"; exit 1; }

for SERVER in "${SERVERS[@]}"; do
    echo -n "→ $SERVER ... "
    ssh "$SERVER" \
      "echo '$NEW_KEY' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" \
      && echo "✓" || echo "✗ ошибка"
done
chmod +x add_ssh_key.sh
./add_ssh_key.sh "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... vasya-laptop-2026"
Proxmox Backup Server: установка и настройка NetDiag: диагностика сети без установки Настройка OSPF MikroTik RouterOS 7 Мониторинг сервисов: Uptime Kuma

 

11. Troubleshooting SSH-ключей: чеклист и таблица ошибок

Быстрый чеклист — запускай по порядку

# 1. Расширенный вывод — читай внимательно каждую строку
ssh -vvv user@IP_СЕРВЕРА 2>&1 | head -60

# 2. Права на клиентской машине
stat ~/.ssh
stat ~/.ssh/id_ed25519
stat ~/.ssh/config 2>/dev/null

# Быстрое исправление всех прав одной командой:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 ~/.ssh/id_ed25519_* ~/.ssh/config 2>/dev/null
chmod 644 ~/.ssh/*.pub 2>/dev/null
chmod 600 ~/.ssh/authorized_keys 2>/dev/null

# 3. Что загружено в агенте:
ssh-add -l
# "The agent has no identities" → нужно ssh-add

# 4. Authorized_keys на сервере:
ssh -o PasswordAuthentication=yes user@IP "cat ~/.ssh/authorized_keys && ls -la ~/.ssh/"

# 5. Лог sshd на сервере (там вся правда):
sudo journalctl -u sshd -n 50 --no-pager
# или:
sudo tail -50 /var/log/auth.log

# 6. Что реально принимает sshd:
sudo sshd -T | grep -E "pubkeyauth|passwordauth|authorizedkeys|permitroot"

Таблица типичных ошибок

Симптом Причина Решение
Permission denied (publickey) Ключ не совпадает, неправильный пользователь, права на файлы Проверь: правильный ли ключ в authorized_keys, правильный ли user@, права 700/600. ssh -vvv покажет какой ключ пробует
Bad owner or permissions on ~/.ssh/config Права на config не 600, или владелец не ты chmod 600 ~/.ssh/config
SSH всё равно просит пароль PasswordAuthentication yes в sshd_config, или SELinux/AppArmor блокирует authorized_keys Проверь sshd -T | grep passwordauth. На CentOS/RHEL: restorecon -Rv ~/.ssh/
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED Сменился ключ сервера (переустановка ОС, новый сервер на том же IP) ssh-keygen -R IP_СЕРВЕРА — удаляет старую запись из known_hosts
Could not open a connection to your authentication agent ssh-agent не запущен eval "$(ssh-agent -s)" затем ssh-add ~/.ssh/id_ed25519
Too many authentication failures SSH перебирает все ключи из агента, сервер блокирует после N попыток Добавь IdentitiesOnly yes в блок Host в ~/.ssh/config
PuTTY: Server refused our key Скопировали не то поле — нажали «Save public key» вместо копирования из текстового поля PuTTYgen → открой приватный ключ → скопируй текст из поля «Public key for pasting into OpenSSH authorized_keys»
sign_and_send_pubkey: signing failed Агент запущен, но ключ не добавлен ssh-add -l — проверь. ssh-add ~/.ssh/id_ed25519 — добавь
RSA-ключ не работает на Ubuntu 22.04+ OpenSSH 8.8+ отключил rsa-sha по умолчанию В ~/.ssh/config для хоста добавь: HostKeyAlgorithms +ssh-rsa и PubkeyAcceptedKeyTypes +ssh-rsa. Или перейди на Ed25519
Ключ есть, права правильные, всё равно не пускает (CentOS/RHEL) SELinux-контекст файлов не соответствует ожидаемому restorecon -Rv ~/.ssh/. Проверь: ls -Z ~/.ssh/

SELinux — скрытый убийца на CentOS/RHEL

# Симптом: права правильные, ключ правильный, не пускает
# Проверяем контекст безопасности:
ls -Z ~/.ssh/

# Восстанавливаем правильный контекст:
restorecon -Rv ~/.ssh/

# Диагностика: временно отключить для теста (не на продакшне!)
sudo setenforce 0
ssh user@localhost
sudo setenforce 1
# Если после setenforce 0 заработало — дело точно в SELinux

12. Безопасность SSH в production

Fail2ban: автоматическая блокировка брутфорса

# Устанавливаем:
sudo apt install fail2ban -y    # Debian/Ubuntu
sudo yum install fail2ban -y    # CentOS/RHEL

# Создаём локальный конфиг (не редактируем jail.conf напрямую):
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
# Минимальная конфигурация для SSH в jail.local:
[DEFAULT]
bantime  = 1h          # блокировать на 1 час
findtime = 10m         # окно поиска попыток
maxretry = 5           # максимум попыток

[sshd]
enabled  = true
port     = ssh         # или 2222 если порт нестандартный
logpath  = %(sshd_log)s
backend  = %(sshd_backend)s
maxretry = 3           # 3 неудачных попытки → бан
bantime  = 24h         # бан на сутки
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

# Статус банов:
sudo fail2ban-client status sshd

# Разблокировать IP вручную:
sudo fail2ban-client set sshd unbanip 1.2.3.4

Firewall: ограничь доступ к SSH

# UFW (Ubuntu/Debian):
sudo ufw allow from 203.0.113.0/24 to any port 22    # только с твоей подсети
sudo ufw deny 22                                       # всем остальным закрыть
sudo ufw enable

# nftables (современный Linux):
sudo nft add rule inet filter input tcp dport 22 ip saddr 203.0.113.0/24 accept
sudo nft add rule inet filter input tcp dport 22 drop

# iptables:
sudo iptables -A INPUT -p tcp --dport 22 -s 203.0.113.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP
Не закрывай SSH для всех до того, как убедишься что твой IP в белом списке. Заблокируешь себя — придётся идти в консоль хостинга или VNC.

Ротация ключей — раз в год и при увольнении

# 1. Генерируем новый ключ (пока старый ещё работает):
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "work-laptop-2026-new"

# 2. Добавляем новый на серверы:
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@IP_СЕРВЕРА

# 3. Проверяем вход по новому ключу:
ssh -i ~/.ssh/id_ed25519_new user@IP_СЕРВЕРА

# 4. Удаляем старый ключ из authorized_keys на сервере:
# Находим строку со старым комментарием:
ssh user@IP_СЕРВЕРА "grep -n 'work-laptop-2025' ~/.ssh/authorized_keys"
# Удаляем строку (например, строка 2):
ssh user@IP_СЕРВЕРА "sed -i '2d' ~/.ssh/authorized_keys"

# 5. Обновляем ~/.ssh/config на клиенте

Бэкап ключей

# Шифруем архив с ключами через GPG (симметричное шифрование):
tar czf - ~/.ssh/ | gpg --symmetric --cipher-algo AES256 \
  -o ssh-keys-backup-$(date +%Y%m%d).tar.gz.gpg

# Восстановить:
gpg -d ssh-keys-backup-20260101.tar.gz.gpg | tar xzf - -C ~/
Зашифрованный архив — в облако. Незашифрованные приватные ключи в облако — никогда. Это не параноя, это гигиена безопасности.

Аудит: кто имеет доступ к серверу

#!/bin/bash
# audit_ssh_keys.sh — список всех авторизованных ключей

AUTH_FILE=~/.ssh/authorized_keys
[ ! -f "$AUTH_FILE" ] && { echo "authorized_keys не найден"; exit 0; }

echo "=== SSH ключи пользователя $(whoami) на $(hostname) ==="
echo ""

COUNT=0
while IFS= read -r line; do
    [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue
    COUNT=$((COUNT+1))
    TYPE=$(echo "$line" | awk '{print $1}')
    COMMENT=$(echo "$line" | awk '{print $3}')
    FP=$(echo "$line" | ssh-keygen -lf /dev/stdin 2>/dev/null | awk '{print $2}')
    echo "[$COUNT] $TYPE"
    echo "    Комментарий: ${COMMENT:-без комментария}"
    echo "    Fingerprint: ${FP:-н/д}"
    echo ""
done < "$AUTH_FILE"

echo "Всего: $COUNT ключей"
chmod +x audit_ssh_keys.sh && ./audit_ssh_keys.sh

13. Управление ключами: посмотреть, удалить, проверить

# Посмотреть публичный ключ:
cat ~/.ssh/id_ed25519.pub

# Fingerprint ключа (для сравнения):
ssh-keygen -lf ~/.ssh/id_ed25519.pub

# Все ключи в директории:
for f in ~/.ssh/*.pub; do echo "=== $f ==="; ssh-keygen -lf "$f"; done

# Удалить уволившегося сотрудника по комментарию:
ssh user@IP "grep -v 'vasya-laptop' ~/.ssh/authorized_keys > /tmp/ak && mv /tmp/ak ~/.ssh/authorized_keys"

# Удалить устаревшую запись из known_hosts:
ssh-keygen -R IP_СЕРВЕРА
ssh-keygen -R hostname.domain.com

14. FAQ по SSH-ключам

В чём разница между Ed25519 и RSA?

Ed25519 — современный алгоритм на основе эллиптических кривых. Короткий ключ (256 бит) даёт такую же безопасность, как RSA 3072+. Быстрее генерируется, быстрее работает, меньше места занимает. RSA — классика, нужен только для legacy-систем с OpenSSH < 6.5. Для всего нового используй Ed25519.

Нужна ли passphrase на ключе?

Зависит от угрозы. Без passphrase: если украли машину или вытащили ключ из файловой системы — сразу имеют доступ ко всем серверам. С passphrase: даже с файлом ключа нужна ещё фраза. Для CI/CD — без passphrase (не может ввести интерактивно). Для личного ключа — ставь фразу и настрой ssh-agent.

Можно ли использовать один ключ для всех серверов?

Технически да. Правильно — нет. Компрометация одного сервера → злоумышленник видит твой публичный ключ → может проверить его на других серверах. Минимум: отдельный ключ для personal/work/ci-cd. Правильно: отдельный ключ для каждого клиента или проекта.

SSH не работает после переустановки сервера — WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED

После переустановки ОС меняется host key сервера. SSH предупреждает что это может быть MITM-атака. Если ты сам переустановил сервер — это ложная тревога. Удали старую запись: ssh-keygen -R IP_СЕРВЕРА. Следующее подключение спросит подтвердить новый fingerprint.

Как настроить SSH-ключи для GitHub?

# Генерируй отдельный ключ:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github -C "github-2026"

# Добавь публичный ключ в GitHub:
# Settings → SSH and GPG keys → New SSH key
cat ~/.ssh/id_ed25519_github.pub

# В ~/.ssh/config:
# Host github.com
#     IdentityFile ~/.ssh/id_ed25519_github
#     IdentitiesOnly yes

# Проверь:
ssh -T git@github.com

SSH-ключ есть, но CI/CD не может подключиться к серверу

Пять причин: (1) в CI добавлен публичный ключ вместо приватного — нужен именно приватный; (2) приватный ключ скопирован с лишними пробелами или переносами — проверь формат; (3) ключ с passphrase — в CI нужен без passphrase; (4) пользователь deploy не существует на сервере; (5) права на authorized_keys не 600.

Как подключиться по SSH через бастион (jump host)?

# Одноразово:
ssh -J user@bastion user@internal-server

# Через ~/.ssh/config (постоянно):
# Host internal-server
#     HostName 10.0.0.50
#     ProxyJump bastion
#     User admin

Что делать если потерял приватный ключ?

Если есть доступ к серверу через другой способ (другой ключ, консоль хостинга, VNC) — зайди и удали старый публичный ключ из authorized_keys. Сгенерируй новый ключ, добавь новый публичный. Если доступа нет вообще — только консоль хостинга или физический доступ к машине. Именно поэтому нужен бэкап ключей.

Итог: что теперь работает

Сгенерированы Ed25519-ключи, публичный скопирован на серверы, ~/.ssh/config настроен — теперь ssh prod вместо семи флагов. SSH-agent запомнит passphrase до перезагрузки. Вход по паролю на сервере отключён, fail2ban блокирует брутфорс.

Боты ломятся на 22-й порт — и разбиваются об ключевую аутентификацию. Деплой-скрипты ходят на сервер без остановок. Новый коллега получает доступ скриптом за две минуты, а не через «пароль в каком чатике».

💬 Сломалось или не работает?

Пиши в комментарии. Укажи: ОС клиента и сервера, вывод ssh -vvv user@host 2>&1 | head -40, вывод sudo tail -20 /var/log/auth.log на сервере. Разберёмся.

Андрей Анатольевич
Author: Андрей Анатольевич

Руководитель ИТ / Кризис-менеджер 25 лет в IT: от инженера в МегаФоне до руководителя отдела. Знаю, как выглядит бардак: нестабильные сети, устаревшая инфраструктура, конфликты в команде, раздутые сроки. Помогаю бизнесу выходить из кризиса: навожу порядок в легаси, стабилизирую то, что разваливается, выстраиваю прогнозируемые процессы. Не раз возвращал к жизни ИТ-структуры — знаю цену хаосу. 📍 Ищу проект для полной реорганизации / стабилизации. 📬 Telegram: @over_dude ✉️ mail@it-apteka.com

Оставайтесь на связи

Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.

Подписаться на IT-Аптеку →

Мы ВКонтакте

IT-Аптека — советы, новости и помощь рядом.

Вступить в группу ВКонтакте →
Поделитесь:

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх