# 1. Генерируй ключ (один раз на своей машине) ssh-keygen -t ed25519 -C "my-laptop-2026" # 2. Скопируй на сервер (последний раз введёшь пароль) ssh-copy-id user@IP_СЕРВЕРА # 3. Проверь ssh user@IP_СЕРВЕРА
Вошёл без пароля — готово. Не вошёл — читай раздел «Troubleshooting» ниже.
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 часов. Сервер майнит крипту или рассылает спам.
Что получишь из этой статьи:
- Генерация ключей: 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. Утечёт — не страшно. Без приватного ключа бесполезен
Процесс аутентификации:
- Ты подключаешься:
ssh user@server - Сервер смотрит в
~/.ssh/authorized_keys— есть ли твой публичный ключ - Сервер генерирует случайную строку, шифрует её твоим публичным ключом и отправляет тебе
- Твой SSH-клиент расшифровывает строку приватным ключом и отправляет ответ обратно
- Сервер проверяет — правильно ли расшифровано. Если да — пускает. Пароль не нужен
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"
Три вопроса при генерации:
- Куда сохранить — нажми Enter, оставь по умолчанию (
~/.ssh/id_ed25519) - Passphrase — парольная фраза для дополнительной защиты приватного ключа. Можно оставить пустой (Enter). С фразой — безопаснее, но нужен ssh-agent (об этом ниже)
- Повтор фразы — та же или 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:
- Запусти PuTTYgen (входит в комплект putty.org)
- Parameters → выбери EdDSA или RSA 4096
- Нажми Generate, поводи мышкой — это энтропия
- Добавь Key comment (имя машины или твоё имя)
- Нажми Save private key → сохраняется
.ppk - Скопируй текст из поля «Public key for pasting into OpenSSH authorized_keys» — именно это поле, не кнопка «Save public 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 автоматически на новом сервере.
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. Отключение входа по паролю на сервере
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. Правила для деплой-ключей:
- Отдельный ключ — не используй личный ключ в CI/CD
- Без passphrase — CI не может ввести фразу интерактивно
- Минимальные права — отдельный пользователь
deployбез sudo - Ограничения в authorized_keys — можно разрешить только конкретные команды
# Генерируем деплой-ключ (без 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
Ротация ключей — раз в год и при увольнении
# 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 на сервере. Разберёмся.
Оставайтесь на связи
Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.
Подписаться на IT-Аптеку →



