OpenSSH (Русский)

From ArchWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Состояние перевода: На этой странице представлен перевод статьи OpenSSH. Дата последней синхронизации: 11 июля 2021. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

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
Важно: Перед заданием этой настройки следует убедиться, что аутентификация по открытому ключу включена для всех аккаунтов, которым может потребоваться SSH-доступ. Для этого используются файлы 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 не различает успешными и неудачными попытками входа.

Ограничение входа от имени суперпользователя

Tango-view-refresh-red.pngThis article or section is out of date.Tango-view-refresh-red.png

Reason: В текущей версии OpenSSH вход от root отключён по умолчанию. Некоторые части этого раздела могут быть избыточны. (Discuss in Talk:OpenSSH (Русский))

Предоставление возможности входа через 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].

Важно: Использование проброса X11 имеет важные последствия для безопасности. Изучите соответствующие разделы страниц справочных руководств ssh(1), sshd_config(5) и ssh_config(5), а также вопрос на StackExchange

Настройка

На удалённой системе:

На клиенте:

Совет: Если графический интерфейс отображается плохо или вы получаете сообщения об ошибках, включите опцию ForwardX11Trusted (в командной строке это флаг -Y). Это предотвратит управление пробросом Х11 со стороны расширения безопасности X11. Если вы будете использовать эту опцию, обязательно прочитайте предупреждение в начале этого раздела

Использование

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Команда xhost обычно не нужна (Discuss in Talk:OpenSSH (Русский))

Выполните удалённый вход как обычно, добавив флаг -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 пользователя, вошедшего в систему.

Совет: Полезные ссылки при решении проблем с пробросом X11: [4], [5], [6].

Проброс других портов

В дополнение к встроенной поддержке 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 через промежуточный узел

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: SSH-туннелирование давно известно, поэтому неплохо было бы добавить несколько ссылок с подробным описанием. Например, [7], где рассмотрены и некоторые другие варианты. (Discuss in Talk:OpenSSH (Русский))

Идея заключается в том, чтобы подключиться к серверу через промежуточный узел, причём сервер соединяется с этим узлом через обратный SSH-туннель. Например, это может быть полезно, когда сервер находится за NAT, а промежуточный узел представляет собой публичный SSH-сервер, используемый в качестве прокси. При этом:

  • у клиента должны быть ключи для авторизации и на промежуточном узле, и на целевом сервере;
  • у сервера должны быть ключи дла авторизации на промежуточном узле.

Ниже приведён пример настройки соединения через промежуточный узел. Предполагается, что пользователь1 — аккаунт на клиентской машине, пользователь2 — на промежуточном узле и пользователь3 — на сервере. Сначала необходимо создать обратный туннель:

ssh -R 2222:localhost:22 -N пользователь2@промежуточный-узел

Это действие можно автоматизировать с помощью скрипта, службы systemd или autossh.

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: Объяснить, почему недостаточно команды ssh user3@relay -p 2222. (Discuss in Talk:OpenSSH (Русский))

Соединение со стороны клиента устанавливается командой:

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
Совет: Можно создать несколько процессов autossh, если нужно поддерживать несколько туннелей. Просто создайте нужное количество файлов служб с разными именами.

Альтернатива на случай невозможности запустить демон 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-адреса могут совпадать. Нужен какой-то способ их различать.

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: "Лучшее решение" не должно представлять собой совет воспользоваться чем-то другим. (Discuss in Talk:OpenSSH (Русский))

Лучшим решением будет воспользоваться рекомендациями из раздела #Настройка для работы в конкретной сети и использовать разные параметры 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

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: В файл known_hosts записывается IP-адрес даже в том случае, если вы используете имя хоста для доступа на сервер. (Discuss in Talk:OpenSSH (Русский))
Важно: В рабочих сетях используйте только имя хоста для удалённого доступа к нему и/или используйте отдельный файл 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.

Теперь после подключения к удалённому серверу вы сможете работать с другими службами с помощью локальных ключей.

Решение проблем

Проверка

Проверьте следующие моменты, прежде чем искать решение проблем.

  1. Каталог с настройками ~/.ssh и его содержимое должно быть доступно только пользователю (проверьте и клиент, и сервер), а также права на запись в домашнем каталоге должны быть только у пользователя:
    $ chmod go-w ~
    $ chmod 700 ~/.ssh
    $ chmod 600 ~/.ssh/*
    $ chown -R $USER ~/.ssh
    
  2. Убедитесь, что открытый ключ клиента (например, id_rsa.pub) указан в файле ~/.ssh/authorized_keys на сервере;
  3. Убедитесь, что вы не ограничили доступ через SSH параметрами AllowUsers и AllowGroups в настройках сервера;
  4. Проверьте, установил ли пользователь пароль. Иногда новые пользователи не устанавливают пароль до первого входа в систему;
  5. Добавьте параметр LogLevel DEBUG в файл /etc/ssh/sshd_config;
  6. Изучите вывод команды journalctl -xe (запускается с правами root) на предмет сообщений об ошибках;
  7. Перезапустите демон 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 и т.д.).

Ваш провайдер или кто-то еще блокирует нужный порт?

Примечание: Пробуйте этот шаг в том случае, если вы знаете, что у вас не запущено никаких фаерволлов, и что вы настроили роутер на DMZ или проброс портов на компьютер. Здесь вы найдете рекомендации по диагностике и возможные решения.

В некоторых случаях провайдер может блокировать порт по умолчанию (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 и используйте новый.

Смотрите также