OpenSSH (Русский)
OpenSSH (OpenBSD Secure Shell) — набор программ, предоставляющих шифрование сеансов связи в компьютерных сетях по протоколу SSH (Secure Shell). OpenSSH разработан в рамках возглавляемого Тео де Раадтом (Theo de Raadt) проекта OpenBSD как открытая альтернатива проприетарному Secure Shell компании SSH Communications Security.
OpenSSH иногда путают с OpenSSL; они разрабатываются разными командами и имеют различное назначение. Определённая схожесть в названиях возникла из-за приверженности обоих проектов принципам открытого программного обеспечения (open software).
Установка
Установите пакет openssh.
Клиент
Чтобы установить соединение с сервером, выполните:
$ ssh -p порт пользователь@адрес-сервера
Если на сервере разрешена аутентификация только по открытому ключу, см. Ключи SSH.
Настройка
Настройки клиента делятся на две категории: общие для всех исходящих соединений и относящиеся к соединениям только с определёнными хостами. Например:
~/.ssh/config
# глобальные настройки User пользователь # настройки отдельного хоста Host мой-сервер HostName адрес-сервера Port порт
С такими настройками следующие команды будут иметь одинаковый эффект:
$ ssh -p порт пользователь@адрес-сервера $ ssh мой-сервер
Подробнее см. руководство ssh_config(5).
Некоторые настройки не имеют флагов-аналогов для командной строки, но можно указать необходимые опции с помощью флага -o
. Например, -oKexAlgorithms=+diffie-hellman-group1-sha1
.
Сервер
sshd
— демон сервера OpenSSH, который управляется службой sshd.service
в соответствии с настройками в файле /etc/ssh/sshd_config
. Если вы собираетесь изменить настройки, то стоит сначала запустить sshd
в тестовом режиме, чтобы убедиться, что демон запустится без проблем. Отсутствие вывода означает рабочую конфигурацию.
# sshd -t
Настройка
Чтобы изменить настройки, нужно отредактировать/добавить нужные строки в файле настроек, например:
Предоставить доступ отдельным пользователям:
AllowUsers пользователь1 пользователь2
Предоставить доступ группам пользователей:
AllowGroups группа1 группа2
Параметр Banner
позволяет настроить приветственное сообщение (например, сохранённое в файле /etc/issue
):
Banner /etc/issue
Пары открытых и закрытых ключей генерируются службой sshdgenkeys и сохраняются в файле /etc/ssh
. Если какие-то ключи отсустствуют, то они создаются заново, даже если опция HostKeyAlgorithms
в файле sshd_config
разрешает не все алгоритмы шифрования. Всего создаётся четыре пары ключей на основе алгоритмов dsa, rsa, ecdsa и ed25519. Чтобы sshd мог использовать конкретный ключ, укажите следующую опцию:
HostKey /etc/ssh/ssh_host_rsa_key
Если сервер находится в глобальной (WAN) сети, рекомендуется также сменить порт со стандартного 22 на случайное значение, например:
Port 39901
- Альтернативный порт лучше выбирать из числа не занятых другими службами. Инфомацию о портах можно найти в файле
/etc/services
, а также в статье Список портов TCP и UDP. Смена порта снизит количество попыток входа, выполняемых автоматизированными сканерами и скриптами, которые обычно ожидают SSH-соединение на порте 22. Чтобы полностью исключить такие попытки, можно настроить port knocking. - В целях безопасности рекомендуется полностью отключить вход по паролю. Другие полезные способы повышения защищённости SSH-соединения описаны в разделе #Безопасность.
- OpenSSH может прослушивать несколько портов одновременно. Для этого укажите несколько параметров
Port номер-порта
в файле настроек. - Можно сгенерировать новые пары ключей в дополнение (или взамен) к тем, которые были созданы изначально. Удалите ненужные пары ключей из файлов в каталоге
/etc/ssh
, после чего выполните командуssh-keygen -A
с правами root.
Управление демоном
Запустите/включите службу sshd.service
. Демон SSH будет работать в фоновом режиме и выполнять форк (fork) для каждого входящего соединения [1].
sshd.socket
был удалён из openssh в версии 8.0p1-3. Он использовал активацию сокета systemd, вследствие чего оказался уязвим к DoS-атакам (см. FS#62248). Если sshd.socket
будет включён во время обновления до openssh 8.0p1-3, то юниты sshd.socket
и sshd@.service
будут скопированы в каталог /etc/systed/system
и включены заново. Это сделано с единственной целью — не поломать существующие конфигурации, в остальном же рекомендуется перейти на использование sshd.service
.
sshd.socket
, обратите внимание на следующие моменты:
- Юнит
sshd.socket
может внезапно прекратить работу (например, из-за исчерпания свободной памяти), а опциюRestart=always
для юнитов сокетов задать нельзя [2]. - Использовании активации сокета может привести к отказу в обслуживании (denial of service), если слишком большое количество соединений приведёт к невозможности новых запусков службы (см. FS#62248).
sshd.socket
нельзя задать параметр ListenAddress
, поэтому будут разрешены соединения с любых адресов. Для создания аналогичной ListenAddress
настройки отредактируйте файл sshd.socket
, указав порт и IP-адрес в параметре ListenStream
(например, ListenStream=192.168.1.100:22
). Также нужно добавить параметр FreeBind=true
в раздел [Socket]
, иначе проявится та же проблема, что и при задании ListenAddress
: если сеть не успела вовремя включиться, сокет не запустится.
sshd@.service
(каждый со своим названием). Следовательно, ни sshd.socket
, ни обычный sshd.service
не будут логировать попытки установления соединения. Логи экземпляров сокетов можно просматривать командами journalctl -u "sshd@*"
и journalctl /usr/bin/sshd
с правами root.
Безопасность
Удалённый вход в систему через SSH удобен для осуществления административных задач, но представляет определённую проблему с точки зрения безопаности. SSH часто подвергается атакам полным перебором и нуждается в соответствующей конфигурации, чтобы не дать посторонним войти в систему.
ssh-audit предлагает автоматизированный анализ серверных и клиентских настроек. Следующие статьи и инструменты могут также быть полезными:
Вход только по открытому ключу
Если клиент не может выполнить вход по открытому ключу, SSH-сервер по умолчанию предоставляет возможность аутентификации по паролю. Это позволяет злоумышленнику получить доступ с помощью полного перебора паролей. Самый надёжный способ защиты от такой атаки — полностью отключить вход по паролю и оставить только аутентификацию с помощью ключей SSH. Для этого нужно отключить следующую опцию в файле настроек демона:
/etc/ssh/sshd_config
PasswordAuthentication no
authorized_keys
. Подробнее см. SSH keys#Copying the public key to the remote server.Двухфакторная аутентификация и открытые ключи
С помощью опции AuthenticationMethods
можно настроить использование различных способов аутентификации, например, применение открытых ключей совместно с двухфакторной аутентификацией.
Программы аутентификации
В статье Google Authenticator описана настройка Google Authenticator.
Для Duo установите duo_unixAUR, в котором есть полная поддержка модуля pam_duo.so
. Подробнее о настройке параметров доступа (Integration Key, Secret Key, API Hostname) см. документацию Duo Unix.
Настройка PAM
Для использования PAM с OpenSSH, отредактируйте следующий файл:
/etc/ssh/sshd_config
ChallengeResponseAuthentication yes AuthenticationMethods publickey keyboard-interactive:pam
После этого можно будет выполнять вход в систему или по открытому ключу, или в соответствии настройками аутентификации PAM.
Наоборот, если вы хотите настроить вход по открытому ключу и через PAM, используйте в качестве разделителя AuthenticationMethods запятую, а не пробел:
/etc/ssh/sshd_config
ChallengeResponseAuthentication yes AuthenticationMethods publickey,keyboard-interactive:pam
При входе по ключу и PAM аутентификацию по паролю можно отключить:
/etc/pam.d/sshd
#отключение удалённного root auth required pam_securetty.so #требуется google authenticator auth required pam_google_authenticator.so #но пароль не нужен #auth include system-remote-login account include system-remote-login password include system-remote-login session include system-remote-login
Защита от атак полным перебором
Принцип атаки полным перебором прост: атакующий многократно пытается выполнить вход на страницу или веб-сервер, используя большое количество случайных комбинаций имён пользователей и паролей.
Подробнее см. ufw#Rate limiting with ufw и Настройка межсетевого экрана#Атака полным перебором в случае экрана iptables
Кроме того, программы вроде fail2ban или sshguard помогают защититься от атак перебором, блокируя попытки подбора паролей.
- Разрешайте входящие SSH-соединения только для доверенных адресов
- Используйте fail2ban или sshguard для автоматической блокировки IP-адресов, которые провалили попытку аутентификации слишком много раз.
- Используйте pam_shield для блокировки IP-адресов, которые выполняют слишком большое количество попыток входа за определённый период времени. В отличие от fail2ban и sshguard, pam_shield не различает успешными и неудачными попытками входа.
Ограничение входа от имени суперпользователя
Предоставление возможности входа через SSH от имени суперпользователя без какой-либо защиты считается плохой практикой. Существует два способа ограничения этой возможности для повышения безопасности.
Отключение
Утилита sudo выборочно предоставляет права суперпользователя для действий, которым они необходимы, без входа в учётную запись root. Благодаря этому можно заблокировать аккаунт root, чтобы отключить возможность входа в него через SSH. Это потенциально является средством защиты от атак перебором, поскольку атакующему придётся подбирать ещё и имя учётной записи в дополнение к паролю.
Чтобы отключить вход от имени суперпользователя через SSH, получите его права и отредактируйте секцию "Authentication" файла /etc/ssh/sshd_config
. Просто измените значение #PermitRootLogin yes
на no
и раскомментируйте строку:
/etc/ssh/sshd_config
PermitRootLogin no ...
Перезапустите демон SSH.
Теперь вы не сможете войти в систему через SSH от имени суперпользователя, но по-прежнему будете иметь возможность входить от имени обычного пользователя и использовать команды su и sudo для администрирования.
Ограничение
Некоторые автоматические задачи, вроде удалённого резервного копирования системы, требуют полного root-доступа. Чтобы иметь возможность безопасно его использовать, вместо отключения укажите конкретные команды. Для этого отредактируйте файл ~root/.ssh/authorized_keys
, создав префиксы для соответствующих ключей, например:
command="/usr/lib/rsync/rrsync -ro /" ssh-rsa …
Теперь при входе с использованием соответствующего ключа пользователь получит права root, но сможет выполнять только те команды, которые перечислены между кавычками.
При этом остаётся возможность входа в систему с использованием имени суперпользователя. Это можно исправить, добавив следующую строку в файл sshd_config
:
PermitRootLogin forced-commands-only
Это не только ограничит список команд, которые могут выполняться через SSH от имени суперпользователя, но и отключит использование паролей, оставляя возможность входа в root-аккаунт только по ключу.
Есть альтернатива, вводящая меньше ограничений, которая позволит выполнять любые команды от имени суперпользователя, но сделает невозможной атаку перебором благодаря отключению входа по паролю. Для этого пропишите:
PermitRootLogin prohibit-password
Защита файла authorized_keys
Для дополнительной защиты можно запретить пользователям добавлять новые открытые ключи, по которым можно будет выполнить соединение.
Задайте файлу authorized_keys
права только на чтение для владельца и отключите остальные:
$ chmod 400 ~/.ssh/authorized_keys
Чтобы не позволить пользователям вернуть разрешения, установите бит неизменяемости на файл authorized_keys
. После этого пользователь может попытаться перемеименовать каталог ~/.ssh
и создать новый каталог с таким же именем и файлом authorized_keys
. Чтобы не дать ему это сделать, установите бит неизменяемости и на каталог ~/.ssh
.
authorized_keys
и дать ему права на запись. В конце нужно будет вернуть настройки обратно.
Советы и рекомендации
Шифрованный туннель SOCKS
Эта возможность будет полезна для обладателей ноутбуков, которые часто подключаются к небезопасным беспроводным сетям в общественных местах. Для создания туннеля необходимо предварительно запустить сервер SSH в каком-нибудь безопасном месте, например, дома или на работе. Также будет весьма кстати какая-нибудь служба динамического DNS вроде DynDNS, которая избавит вас от необходимости запоминать IP-адрес.
Шаг 1: установить соединение
Для установления соединения необходимо лишь выполнить команду:
$ ssh -TND 4711 пользователь@хост
где пользователь
— ваше имя пользователя на сервере SSH, работающием на машине хост
. Сервер запросит пароль, после чего будет установлено соединение. Флаг N
отключает интерактивное приглашение командной строки, а флаг D
позволяет пользователю выбрать локальный порт для прослушивания. Флаг T
означает, что сервер не станет выделять псевдо-терминал для данного соединения.
Также стоит указать флаг -v
, который сделает вывод команды более многословным. В частности, по выводу можно будет понять, что соединение действительно было установлено.
Шаг 2 (вариант А): настроить браузер (или другие программы)
Чтобы установленное соединение (см. выше) было хоть как-то полезно, нужно настроить браузер и другие программы на использование туннеля SOCKS. В настоящее время SSH поддерживает как SOCKSv4, так и SOCKSv5, вы можете выбрать любой из них.
- Для Firefox: Preferences > General > Settings.... В открывшемся окне выберите пункт Manual proxy configuration, введите
localhost
в поле SOCKS host и номер порта в поле Port (4711
для примера выше).
- DNS-запросы Firefox автоматически посылаться через туннель не будут, что представляет собой некоторую уязвимость с точки зрения приватности. Чтобы это исправить, также выберите пункт Proxy DNS when using SOCKS v5. Очевидно, что это будет работать, только если вы выбрали пятую версию протокола SOCKS, а не четвёртую.
- Перезапустите Firefox, чтобы настройки заработали.
- Для Chromium: SOCKS можно настроить через переменные окружения или опции командной строки. Например, выберите одну из следующих функций и добавьте её в файл
.bashrc
:
function secure_chromium { port=4711 export SOCKS_SERVER=localhost:$port export SOCKS_VERSION=5 chromium & exit }
или
function secure_chromium { port=4711 chromium --proxy-server="socks://localhost:$port" & exit }
Теперь откройте терминал, выполните
$ secure_chromium
и наслаждайтесь защищённым туннелем!
Шаг 2 (вариант Б): настроить TUN-интерфейс
Этот вариант выглядит несколько более запутанным по сравнению с предыдущим, но зато вам не придётся настраивать работу через SOCKS-прокси для каждого приложения по отдельности. Данное решение подразумевает настройку локального TUN-интерфейса и перенаправление всего трафика на него.
Подробнее см. VPN over SSH#Set up badvpn and tunnel interface.
Проброс X11
Проброс Х11 — механизм, который позволяет графическим интерфейсам программ удаленной машины-сервера отображаться на локальной машине-клиенте. При этом нет необходимости устанавливать на удаленном узле всю систему Х11, но надо установить хотя бы xauth. xauth — утилита, которая поддерживает конфигурации Xauthority
, используемые сервером и клиентом для аутентификации сессии X11 [3].
Настройка
На удалённой системе:
- Установите пакеты xorg-xauth и xorg-xhost;
- В файле
/etc/ssh/sshd_config
:- Задайте для опции
X11Forwarding
значениеyes
; - Убедитесь, что заданы значения
AllowTcpForwarding yes
,X11UseLocalhost yes
иX11DisplayOffset 10
(значения по умолчанию, если ничего не менялось, см. sshd_config(5));
- Задайте для опции
- Перезапустите службу sshd.
На клиенте:
- Установите пакет xorg-xauth;
- включите опцию
ForwardX11
либо добавив флаг-X
в командной строке, либо задав в файле настроек клиента параметрForwardX11 yes
.
ForwardX11Trusted
(в командной строке это флаг -Y
). Это предотвратит управление пробросом Х11 со стороны расширения безопасности X11. Если вы будете использовать эту опцию, обязательно прочитайте предупреждение в начале этого разделаИспользование
Выполните удалённый вход как обычно, добавив флаг -X
, если опция ForwardX11 не включена в конфигурационном файле клиента:
$ ssh -X пользователь@хост
Если вы получаете ошибки при запуске графических приложений, попробуйте опцию ForwardX11Trusted:
$ ssh -Y пользователь@хост
Теперь вы можете запустить любую программу с графическим интерфейсом пользователя на удаленном сервере, и ее вывод будет перенаправлен в вашу локальную сессию:
$ xclock
Если вы получите ошибки "Cannot open display", попробуйте выполнить следующую команду от имени обычного пользователя:
$ xhost +
эта команда позволит выполнять проброс приложений X11 любому пользователю. Чтобы ограничить проброс конкретным хостом:
$ xhost +имя-хоста
где имя-хоста - это имя конкретного хоста. Подробнее см. xhost(1).
Будьте осторожны с некоторыми приложениями, так как они могут проверять локальную машину на предмет уже работающего приложения. Один из примеров - Firefox: либо закройте работающий Firefox, либо используйте следующий параметр запуска:
$ firefox --no-remote
Если вы получите ошибку X11 forwarding request failed on channel 0
при подключении (и лог-файл сервера /var/log/errors.log
будет содержать строку Failed to allocate internet-domain X11 display socket
), удостоверьтесь, что пакет xorg-xauth установлен. Если его установка не поможет, попробуйте сделать одно из двух:
- Включить опцию
AddressFamily any
в файлеsshd_config
на сервере; - Задать опции
AddressFamily
вsshd_config
на сервере значение inet. Присвоение значения inet может исправить проблемы с клиентами Ubuntu при использовании IPv4.
Для запуска приложений X от имени других пользователей на сервере SSH вам необходимо добавить (команда xauth add
) строку аутентификации, взятую из вывода команды xauth list
пользователя, вошедшего в систему.
Проброс других портов
В дополнение к встроенной поддержке SSH X11 также можно установить безопасный туннель для любого соединения TCP с использованием локального или удаленного проброса.
Локальный проброс открывает на локальной машине порт, подключения к которому будут перенаправлены на удаленный хост, а оттуда - по заданному направлению. Очень часто этим направлением будет сам удаленный хост, предоставляющий secure shell и, например, безопасное соединение VNC для этой же машины. Локальный проброс осуществляется при помощи ключа -L
и задания спецификации проброса в следующей форме: <порт туннеля>:<адрес назначения>:<порт назначения>
.
Например:
$ ssh -L 1000:mail.google.com:25 192.168.0.100
будет использовать SSH для входа в систему и открытия шелла на 192.168.0.100
, а также создаст туннель от порта 1000 локальной машины на порт 25 mail.google.com. В результате подключения к localhost:1000
будут перенаправлены на порт Gmail SMTP. Для Google всё будет выглядеть так, будто соединение (но вовсе не обязательно — передаваемые по нему данные) исходит от 192.168.0.100
; данные будут в безопасности между локальной машиной и 192.168.0.100
, но не между 192.168.0.100
и Google, если не предпринять дополнительных мер.
Также:
$ ssh -L 2000:192.168.0.100:6001 192.168.0.100
будет принимать подключения к localhost:2000
, которые будут перенаправлены на порт 6001 удаленного хоста. Этот пример хорош для VNC-соединений с помощью утилиты vncserver. Утилита входит в пакет TigerVNC, и, несмотря на очевидную полезность, имеет некоторые проблемы с безопасностью.
Удаленный проброс позволяет удаленному хосту подключаться к произвольному хосту через туннель SSH и локальную машину, предоставляя функционал, обратный локальному пробросу. Это полезно в ситуациях, когда, например, удаленный хост ограничен фаерволлом. Он включается ключом -R
и заданием спецификаций проброса в следующей форме: <порт туннеля>:<адрес назначения>:<порт назначения>
.
Например:
$ ssh -R 3000:irc.freenode.net:6667 192.168.0.200
поднимет шелл на 192.168.0.200
, и соединения из 192.168.0.200
к своему же порту 3000 (т.е. localhost:3000
удалённого хоста) будут посланы через туннель на локальную машину, а затем на irc.freenode.net, порт 6667, что в данном примере позволит использовать программы IRC на удаленном хосте, даже если обычно порт 6667 будет для них заблокирован.
Оба вида проброса могут быть использованы для предоставления безопасного "шлюза", позволяющего другим компьютерам получить преимущества туннеля SSH без непосредственно работающего SSH или демона SSH, при использовании bind-адреса в начале туннеля как части спецификации проброса, например, <адрес туннеля>:<порт туннеля>:<адрес назначения>:<порт назначения>
. <адрес туннеля>
может быть любым адресом на машине, localhost
, *
(или blank), который, соответственно, пропускает соединения через заданный адрес, интерфейс loopback или любой интерфейс. По умолчанию проброс ограничен соединениями от машины в начале туннеля, <адрес туннеля>
установлен в localhost
. Локальный проброс не требует дополнительной настройки, в то время как удаленный проброс ограничен конфигурацией демона SSH удаленного сервера. Смотрите описание опции GatewayPorts
на справочной странице sshd_config(5)
и опции -L address
в руководстве ssh(1) для получения дополнительной информации.
Jump-хост
Может случиться так, что у вас не будет возможности установить связь с удалённой машиной напрямую. В этом случае используется jump-сервер или узел-бастион. Следовательно, необходимо соединить два или более SSH-туннеля в цепочку. Разумеется, ваши ключи должны позволять выполнить авторизацию на каждом из серверов в цепи. Для этого SSH запускается с опциями пересылки аутентификационных данных (-A
) и выделения псевдотерминала (-t
):
$ ssh -A -t -l пользователь1 бастион1 \ ssh -A -t -l пользователь2 промежуточный-узел2 \ ssh -A -t -l пользователь3 целевой-узел
Несколько проще то же самое можно сделать с флагом -J
:
$ ssh -J пользователь1@бастион1,пользователь2@промежуточный-узел2 пользователь3@целевой-узел
Промежуточные хосты в директиве -J
разделяются запятыми и располагаются в порядке установления соединения. Часть пользователь...@
необязательна. При работе с опцией -J
используется стандартный файл настроек SSH, поэтому при необходимости в нём можно указать настройки соединения для каждого хоста в отдельности.
Опция ProxyJump
в файле настроек эквивалентyна флагу командной строки -J
, см. ssh_config(5).
Обратный SSH через промежуточный узел
Идея заключается в том, чтобы подключиться к серверу через промежуточный узел, причём сервер соединяется с этим узлом через обратный SSH-туннель. Например, это может быть полезно, когда сервер находится за NAT, а промежуточный узел представляет собой публичный SSH-сервер, используемый в качестве прокси. При этом:
- у клиента должны быть ключи для авторизации и на промежуточном узле, и на целевом сервере;
- у сервера должны быть ключи дла авторизации на промежуточном узле.
Ниже приведён пример настройки соединения через промежуточный узел. Предполагается, что пользователь1 — аккаунт на клиентской машине, пользователь2 — на промежуточном узле и пользователь3 — на сервере. Сначала необходимо создать обратный туннель:
ssh -R 2222:localhost:22 -N пользователь2@промежуточный-узел
Это действие можно автоматизировать с помощью скрипта, службы systemd или autossh.
Соединение со стороны клиента устанавливается командой:
ssh -t пользователь1@промежуточный-узел ssh пользователь3@localhost -p 2222
Удалённую команду для создания соединения с обратным туннелем можно добавить в файл ~/.ssh/authorized_keys
на промежуточном узле. Для этого воспользуйтесь полем command
:
command="ssh пользователь3@localhost -p 2222" ssh-rsa KEY2 пользователь1@клиент
Тогда установить соединение можно командой:
ssh пользователь2@промежуточный-узел
Обратите внимание, что функция автодополнения SCP в терминале клиента работать не будет, а на некоторых конфигурациях не будет работать и сама передача данных по протоколу SCP.
Мультиплексирование
Демон SSH обычно прослушивает порт 22. Однако трафик, который адресован не на стандартные порты HTTP/S (80 и 443 соответственно), на публичных серверах часто блокируется. Следовательно, в таком случае SSH-соединение невозможно. В качестве возможного решения можно указать демону sshd
прослушивать один из портов в белом списке:
/etc/ssh/sshd_config
Port 22 Port 443
Поскольку порт 443 уже прослушивается веб-сервером в ожидании HTTPS-пакетов, в данном случае имеет смысл воспользоваться мультиплексором вроде sslh. Он будет прослушивать мультиплексированный порт и переадресовывать пакеты разным сервисам в зависимости от их назначения.
Увеличение скорости SSH
Среди настроек клиента есть некоторые, которые позволяют увеличить скорость соединения либо глобально, либо для отдельных хостов. Полное описание этих опций можно найти в руководстве ssh_config(5).
-
Используйте быстрый алгоритм шифрования: в современных процессорах с инструкциями AESNI алгоритмы
aes128-gcm@openssh.com
иaes256-gcm@openssh.com
гораздо более производительны, чем стандартный алгоритм OpenSSH,chacha20-poly1305@openssh.com
. Выбрать алгоритм можно флагом-c
. Чтобы сделать изменения постоянными, добавьте пунктCiphers
в файл~/.ssh/config
, перечислив алгоритмы в порядке уменьшения предпочтительности, например:Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
-
Включите или выключите сжатие: сжатие может увеличить скорость для медленных соединений, оно включается параметром
Compression yes
или флагом-C
. Однако в качестве алгоритма сжатия используется относительно медленный gzip(1), который в быстрых сетях становится узким местом. Поэтому в локальных и быстрых сетях лучше отключить сжатие параметромCompression no
.
-
Объединение соединений: в случае нескольких одновременных сессий к одному хосту можно объединить их в одно соединение:
ControlMaster auto ControlPersist yes ControlPath ~/.ssh/sockets/socket-%r@%h:%p
- где вместо
~/.ssh/sockets
можно использовать любой каталог без прав на запись для остальных пользователей.
- Параметр
ControlPersist
позволяет задать время ожидания после момента разрыва исходного соединения. Возможны следующие значения:-
no
— соединение разрывается сразу же после отключения предыдущего клиента; - время ожидания в секундах;
-
yes
— бесконечное ожидание, соединение автоматически разрываться не будет.
-
- Время входа можно сократить, если пропустить поиск заголовков IPv6. Для этого используйте опции
AddressFamily inet
или флаг-4
.
- Наконец, если вы собираетесь использовать SSH для SFTP или SCP, High Performance SSH/SCP поможет значительно увеличить пропускную способность с помощью динамического изменения размера буфера SSH. Установите пакет openssh-hpn-gitAUR, чтобы использовать OpenSSH с этим расширением.
Монтирование удалённых файловых систем при помощи SSHFS
В статье SSHFS описано, как использовать SSH для монтирования удалённых файловых систем в локальный каталог, чтобы иметь возможность выполнять любые операции над смонтированными файлами (копирование, переименование, редактирование в vim и т.д.). Предпочтительнее использовать sshfs, а не shfs, поскольку последний не обновлялся с 2004 года.
Поддержание подключения
По умолчанию сеанс связи SSH автоматически разрывается, если соединение не использовалось в течение какого-то времени. Чтобы сохранить сеанс, клиент может посылать сигналы серверу, если не было получено никаких данных за последнее время, или наоборот, сервер может посылать сообщения через определённые временные интервалы, если он не получал данных от клиента.
- На сервере параметр
ClientAliveInterval
задаёт время ожидания в секундах, по истечении которого при отсутствии данных от клиента sshd пошлёт последнему запрос. Значение по умолчанию — 0, "не посылать сообщений". Например, чтобы запрашивать ответ от клиента каждые 60 секунд, задайте параметрClientAliveInterval 60
в настройках сервера. Также обратите внимание на параметрыClientAliveCountMax
иTCPKeepAlive
. - На клиенте параметр
ServerAliveInterval
задаёт временной промежуток между запросами на сервер. Например, чтобы посылать запросы каждые 120 секунд, задайте параметрServerAliveInterval 120
в настройках клиента. Также обратите внимание на параметрыServerAliveCountMax
иTCPKeepAlive
.
ServerAliveInterval
на клиентах, которым нужно сохранять сеансы, а настройки серверов и остальных клиентов оставить без изменений.
Автоматический перезапуск туннелей SSH с помощью systemd
systemd может автоматически создавать SSH-соединения при загрузке/входе в систему, а также перезапускать их при внезапном разрыве соединения.
Ниже представлен пример службы, которая будет создавать SSH-туннель в соответствии с настройками SSH. Если соединение было по какой-то причине разорвано, служба подождёт 10 секунд и перезапустит его:
~/.config/systemd/user/tunnel.service
[Unit] Description=SSH tunnel to myserver [Service] Type=simple Restart=always RestartSec=10 ExecStart=/usr/bin/ssh -F %h/.ssh/config -N myserver
запустите/включите пользовательскую службу systemd. В разделе #Поддержание подключения описано, как предотвратить разрыв соединения из-за превышения времени ожидания. Если вы захотите запускать туннель при загрузке системы, то придётся переписать юнит, чтобы сделать его системным.
Autossh - автоматический перезапуск сессий и туннелей SSH
Если сессия или туннель не может поддерживаться в активном состоянии, например, из-за плохого подключения к сети и связанных с ним отключений, используйте autossh для автоматического перезапуска.
Примеры использования:
$ autossh -M 0 -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" имя_пользователя@example.com
Совместно с SSHFS:
$ sshfs -o reconnect,compression=yes,transform_symlinks,ServerAliveInterval=45,ServerAliveCountMax=2,ssh_command='autossh -M 0' имя_пользователя@example.com: /mnt/example
Подключение через SOCKS-прокси, сконфигурированный при помощи настроек proxy:
$ autossh -M 0 -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" -NCD 8080 имя_пользователя@example.com
При помощи опции -f
autossh может быть запущен в качестве фонового процесса. Однако, в этом случае вы не сможете вводить пароль в интерактивном режиме.
Сессия будет завершена, как только вы введете команду exit
, иначе процесс autossh получит сигнал SIGTERM, SIGINT или SIGKILL.
Автозапуск Autossh при загрузке системы при помощи systemd
Если вы хотите, чтобы autossh запускался автоматически, вы можете использовать systemd. Например, вы можете создать файл юнита, подобный этому:
/etc/systemd/system/autossh.service
[Unit] Description=AutoSSH service for port 2222 After=network.target [Service] Environment="AUTOSSH_GATETIME=0" ExecStart=/usr/bin/autossh -M 0 -NL 2222:localhost:2222 -o TCPKeepAlive=yes foo@bar.com [Install] WantedBy=multi-user.target
Здесь AUTOSSH_GATETIME=0
— это переменная окружения, указывающая, как долго ssh должен быть поднят, прежде чем autossh утвердит успешное подключение. Установка значения 0 укажет autossh игнорировать неудачное подключение ssh. Это может быть полезно при добавлении autossh в автозагрузку. Другие переменные окружения доступны на справочной странице autossh(1). Конечно, вы можете сделать этот юнит более комплексным, если вам это необходимо (для получения дополнительных подробностей смотрите документацию systemd); очевидно, вы можете использовать ваши собственные опции для autossh, но учтите, что флаг -f
, подразумевающий AUTOSSH_GATETIME=0
, не работает с systemd.
Не забудьте запустить и/или включить службу.
Мы также можете отключить ControlMaster, например:
ExecStart=/usr/bin/autossh -M 0 -o ControlMaster=no -NL 2222:localhost:2222 -o TCPKeepAlive=yes foo@bar.com
Альтернатива на случай невозможности запустить демон SSH
Для удалённых или headless-серверов, которые полагаются исключительно на SSH, сбой запуска демона SSH (например, после обновления системы) может означать невозможность осуществлять администрирование. Systemd в этом случае может помочь, если воспользоваться опцией OnFailure
.
Предположим, что на сервере работает sshd
, а качестве запасного варианта выбран telnet. Создайте файл, который показан ниже. Включать telnet.socket
не надо!
/etc/systemd/system/sshd.service.d/override.conf
[Unit] OnFailure=telnet.socket
Это всё. Telnet не будет работать, если запущен sshd
. Если же sshd
не запустится, то можно будет создать сеанс telnet для устранения неисправностей.
Настройка цвета фона терминала для удалённого хоста
Чтобы проще было понять, на каком хосте вы сейчас работаете, можно задать фон терминала для каждой машины.
К сожалению, это работает не для всех терминалов (только для Zsh).
Настройка для работы в конкретной сети
С помощью параметра Match exec
можно создавать настройки хостов для работы в конктретных сетях.
Например, если используется nmcli и соединение настроено (вручную или с помощью DHCP) на использование search-domain:
Match exec "nmcli | grep domains: | grep example.com" CanonicalDomains example.com # Should you use a different username on this network #User username # Use a different known_hosts file (for private network or synchronisation) #UserKnownHostsFile <network>_known_hosts
Проверка ключей хостов в локальных сетях
У серверов, находящихся в разных приватных сетях, IP-адреса могут совпадать. Нужен какой-то способ их различать.
Лучшим решением будет воспользоваться рекомендациями из раздела #Настройка для работы в конкретной сети и использовать разные параметры UserKnownHostsFile
для разных сетей. Второй способ лучше использовать, если вы работаете в новых или экспериментальных сетях — просто игнорируйте ключи хостов (hostkeys) для приватных сетей:
Host 10.* 192.168.*.* 172.31.* 172.30.* 172.2?.* 172.1?.* # Disable HostKey verification # Trust HostKey automatically StrictHostKeyChecking no # Do not save the HostKey UserKnownHostsFile=/dev/null # Do not display: "Warning: Permanently Added ..." LogLevel Error
known_hosts
для каждой сети.
Выполнение команд во время входа
Если вы работаете в интерактивном сеансе, существует несколько способов выполнить команду при входе в систему:
- отредактируйте файл
authorized_keys
на удалённом хосте (см. sshd(8) § AUTHORIZED_KEYS FILE FORMAT); - отредактируйте файл
~/.ssh/rc
на удалённом хосте, если сервер работает с включённой опциейPermitUserRC
; - отредактируйте файл настроек командной оболочки, например,
.bashrc
.
Проброс SSH-агента
Проброс SSH-агента позволяет использовать ваши локальные ключи при подключении к серверу. Рекомендуется включать проброс агента только для отдельных хостов.
~/.ssh/config
Host мойсервер.com ForwardAgent yes
После этого настройте агент SSH и добавьте ваши локальные ключи утилитой ssh-add.
Теперь после подключения к удалённому серверу вы сможете работать с другими службами с помощью локальных ключей.
Решение проблем
Проверка
Проверьте следующие моменты, прежде чем искать решение проблем.
- Каталог с настройками
~/.ssh
и его содержимое должно быть доступно только пользователю (проверьте и клиент, и сервер), а также права на запись в домашнем каталоге должны быть только у пользователя:$ chmod go-w ~ $ chmod 700 ~/.ssh $ chmod 600 ~/.ssh/* $ chown -R $USER ~/.ssh
- Убедитесь, что открытый ключ клиента (например,
id_rsa.pub
) указан в файле~/.ssh/authorized_keys
на сервере; - Убедитесь, что вы не ограничили доступ через SSH параметрами
AllowUsers
иAllowGroups
в настройках сервера; - Проверьте, установил ли пользователь пароль. Иногда новые пользователи не устанавливают пароль до первого входа в систему;
- Добавьте параметр
LogLevel DEBUG
в файл/etc/ssh/sshd_config
; - Изучите вывод команды
journalctl -xe
(запускается с правами root) на предмет сообщений об ошибках; -
Перезапустите демон
sshd
и выполните выход/вход на клиенте и сервере.
Подключение отклонено или проблема тайм-аута
Проброс портов
Если ваша машина находится за NAT или маршрутизатором (скорее всего так и есть, если речь не идёт о VPS или хосте с публичным IP-адресом), убедитесь, что маршрутизатор пробрасывает входящие SSH-соединения на неё. Узнайте внутренний IP-адрес сервера командой ip addr
и настройте маршрутизатор пробрасывать TCP на SSH-порт этого адреса. Подробности смотри на portforward.com.
SSH запущен и прослушивает?
Утилита ss покажет все процессы, прослушивающие TCP-порты:
$ ss --tcp --listening
Если в выводе окажется, что система не прослушивает порт ssh
, то SSH не запущен: проверьте журнал на предмет сообщений об ошибках.
Имеются ли правила фаервола, блокирующие соединения?
Iptables может блокировать подключения к порту 22
. Проверьте это следующей командой:
# iptables -nvL
Просмотрите вывод на предмет правил, которые могут блокировать нужные вам пакеты (цепочка INPUT
). Затем, если необходимо, разблокируйте порт командой вида:
# iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
Информацию по настройке межсетевых экранов можно найти в разделе Файрвол.
Трафик доходит до вашего компьютера?
Запустите дамп трафика на компьютере, с которым возникли проблемы:
# tcpdump -lnn -i any port ssh and tcp-syn
Будет показана некоторая базовая информация. Подождите совпадения. После этого попробуйте подключиться вновь. Если вы не видите никакого вывода команды, когда вы пытаетесь подключиться, это значит, что что-то вне вашего компьютера блокирует трафик (это может быть аппаратный фаерволл, роутер NAT и т.д.).
Ваш провайдер или кто-то еще блокирует нужный порт?
В некоторых случаях провайдер может блокировать порт по умолчанию (SSH порт 22). Чтобы это проверить, создайте сервер на всех интерфейсах (0.0.0.0) и подключитесь удаленно.
Если вы получите сообщение об ошибке вроде этого:
ssh: connect to host www.inet.hr port 22: Connection refused
это означает, что порт не был заблокирован провайдером: просто на сервере не запущен SSH для этого порта (смотрите статью Безопасность через неясность).
Однако, если вы получите сообщение об ошибке вроде этого:
ssh: connect to host 111.222.333.444 port 22: Operation timed out
это означает, что что-то отклоняет ваш трафик TCP, предназначенный для порта 22. Как правило, этот порт скрыт либо вашим фаерволлом, либо третьей стороной (например, провайдером, блокирующим и/или отклоняющим входящий трафик на порт 22). Если вы знаете, что фаерволл на вашем компьютере не запущен и Гремлины не размножаются на ваших роутерах и свитчах, это означает, что провайдер блокирует трафик.
Чтобы убедиться в этом, вы можете запустить Wireshark на сервере и "прослушать" трафик, предназначенный для порта 22. Поскольку Wireshark является утилитой анализа трафика на уровне 2 , а TCP/UDP используют уровень 3 и выше (смотрите статью TCP/IP), если вы ничего не получаете при создании удаленного подключения, вероятнее всего, что третья сторона блокирует трафик для этого порта на вашем сервере.
Диагностика
Установите либо tcpdump, либо Wireshark из пакета wireshark-cli.
Для tcpdump:
# tcpdump -ni интерфейс "port 22"
Для Wireshark:
$ tshark -f "tcp port 22" -i интерфейс
где интерфейс — сетевой интерфейс для соединения WAN (для проверки выполните ip a
). Если вы не получаете никаких пакетов при попытке удаленного подключения, можете быть уверены, что ваш провайдер блокирует входящий на порт 22 трафик.
Возможное решение
Вы можете просто использовать другой порт, который провайдером не блокируется. Откройте файл /etc/ssh/sshd_config
и укажите другой порт. Например, добавьте:
Port 22 Port 1234
Также удостоверьтесь, что другие строки "Port" закомментированы. Если просто закомментировать строку "Port 22" и прописать "Port 1234", проблема не будет решена, поскольку sshd будет прослушивать лишь порт 1234. Используйте обе строки для запуска сервера SSH на обоих портах.
Перезапустите сервер sshd.service
. Готово! Теперь вам необходимо настроить ваш(и) клиент(ы) на использование другого порта.
Read from socket failed: connection reset by peer
Последние версии openssh иногда выдают подобное сообщение при попытке подключения к старым SSH-серверам. Это можно обойти с помощью различных параметров клиента (подробнее см. ssh_config(5)).
Причиной проблемы может быть алгоритм эллиптических кривых ecdsa-sha2-nistp*-cert-v01@openssh
. Его можно отключить, удалив название алгоритма из списка HostKeyAlgorithms
.
Если это не помогло, возможно, список алгоритмов слишком длинен. Укажите в параметре Ciphers
менее длинный список (короче 80 символов). Аналогично можно попробовать сократить список MACs
.
Также стоит изучить обсуждение[устаревшая ссылка 2021-05-17] на форуме openssh.
"[ваша командная оболочка]: No such file or directory" / ssh_exchange_identification problem
Одна из возможных причин - необходимость найти абсолютный путь (который возвращает команда whereis -b [ваша командная оболочка]
, например) в $SHELL
, даже если бинарный пакет вашего интерпретатора находится в одной из записей $PATH
.
Ошибки "Terminal unknown" и "Error opening terminal"
Если вы получаете одну из таких ошибок во время входа, это значит, что сервер не может распознать ваш терминал. Приложения ncurses вроде nano могут не запуститься, выдав сообщение "Error opening terminal".
Правильным решением будет установить файл terminfo клиентского терминала на сервер. Тогда консольные программы на сервере будут знать, как правильно взаимодействовать с вашим терминалом. Информацию о текущем terminfo можно получить с помощью команды infocmp
, после чего нужно выяснить, какому пакету он принадлежит.
Если установить файл нормально не удаётся, скопируйте его в домашний каталог на сервере:
$ ssh myserver mkdir -p ~/.terminfo/${TERM:0:1} $ scp /usr/share/terminfo/${TERM:0:1}/$TERM myserver:~/.terminfo/${TERM:0:1}/
После выхода и отключения от сервера проблема должна решиться.
Хак $TERM
Можно задать переменную окружения сервера TERM=xterm
(например, в файле .bash_profile
). Это заглушит сообщения об ошибках и позволит запуститься приложениям ncurses, но результатом может стать странное поведение и графические баги — кроме случая, если контрольные последовательности вашего терминала совпадают с таковыми у xterm.
Ошибка Connection closed by x.x.x.x [preauth]
Если вы получили такое сообщение об ошибке, убедитесь, что настроен верный HostKey:
HostKey /etc/ssh/ssh_host_rsa_key
id_dsa не используется в OpenSSH 7.0
OpenSSH 7.0 прекратил использование открытых ключей DSA из соображений безопасности. Если вам очень нужно именно эти ключи, воспольуйтесь опцией PubkeyAcceptedKeyTypes +ssh-dss
(на странице https://www.openssh.com/legacy.html она не упомянута).
Не удаётся подобрать способ обмена ключами в OpenSSH 7.0
OpenSSH 7.0 прекратил использование алгоритма diffie-hellman-group1-sha1, поскольку он ненадёжный и теоретически может быть взломан т.н. атакой Logjam (см. https://www.openssh.com/legacy.html). Если этот алгоритм будет нужен какому-то хосту, ssh выдаст соощение об ошибке следующего содержания:
Unable to negotiate with 127.0.0.1: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
Лучшим решением будет обновить сервер и отключить использование устаревших алгоритмов. Если это сделать невозможно, вы можете заставить клиент включить алгоритм параметром KexAlgorithms +diffie-hellman-group1-sha1
.
Сеанс tmux/screen прерывается при разрыве соединения SSH
Если ваши процессы прерываются при завершении сеанса SSH, возможно, что вы используете активацию сокета и systemd принудительно её убивает. В этом случае есть два решения. Первый — не использовать активацию сокета и заменить ssh.socket
на ssh.service
. Второй — задать параметр KillMode=process
в разделе Service
файла ssh@.service
.
Параметр KillMode=process
может также быть полезен при работе с классическим ssh.service
, т.к. он не позволяет убить процесс сессии SSH или процессы screen и tmux при остановке или перезагрузке сервера.
Сеанс SSH не отвечает
SSH реагирует на команды управления XON
и XOFF
. Он остановится, если вы случайно нажали Ctrl+s
. Нажмите Ctrl+q
, чтобы продолжить сеанс.
Broken pipe
Если вы пытаетесь установить соединение и получаете ответ Broken pipe
на packet_write_wait
, попробуйте подключиться в режиме отладки. Посмотрите, если ли в выводе сообщений об ошибках:
debug3: send packet: type 1 packet_write_wait: Connection to A.B.C.D port 22: Broken pipe
Строчка send packet
указывает на то, что ответный пакет получен не был. Следовательно, проблема заключается в QoS. Чтобы уменьшить потерю пакетов, задайте значение параметра IPQoS
:
/etc/ssh/ssh_config
Host * IPQoS reliability
Значение reliability
(0x04
) должно решить проблему. Также можно задать значения 0x00
и throughput
(0x08
).
Демон медленно запускается после перезагрузки
Если демон запускается необычно долго после перезагрузки (несколько минут), особенно для headless- и виртуализированных серверов, это может быть связано с нехваткой энтропии [8]. Для решения этой проблемы установите Rng-tools или Haveged. Однако обратите внимание на вопросы безопасности, которые обсуждаются в посвящённых этим утилитам статьях.
Завершение неотвечающего SSH-соединения
Если клиентский сеанс больше не отвечает и не завершается командами вызвавшей программы (например, командной оболочки), то завершить его можно последовательным нажатием клавиш Enter
, ~
и .
.
~
является управляющей последовательностью псевдотерминала (см. ssh(1) § ESCAPE CHARACTERS), которую можно нажимать несколько раз в зависимости от того, какой сеанс необходимо завершить. Например, если вы установили соединение от А к Б, а затем от Б к В, и сеанс Б-В больше не отзывается, завершить его можно нажав Enter
и введя ~~.
. После этого останется только рабочий сеанс с Б.
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
Если клиент выдаёт предупреждение, что ключ ssh-сервера изменился, убедитесь, что новый ключ действительно принадлежит оператору сервера. Если всё в порядке, удалите старый ключ из файла known_hosts
командой ssh-keygen -R $SSH_HOST
и используйте новый.
Смотрите также
- Защита от атак перебором
- Управление ключами OpenSSH: Часть 1 на IBM developerWorks, Часть 2 и Часть 3 на funtoo.org
- Secure Secure Shell