OpenSSH: ювелирное конфигурирование и изысканные методы использования
За последние несколько лет OpenSSH из простого набора программ для защищенной системы регистрации, выполнения команд на удаленном хосте и передачи файлов с одной машины на другую превратился в швейцарский армейский нож, потрясающий своими возможностями. Бьюсь об заклад, ты не используешь и полвину из них.
С места в карьер
OpenSSH включен практически во все варианты *nix-систем, поэтому не будем останавливаться на инсталляции и сразу перейдем к настройкам, секретным трюкам и советам.
Чтобы просмотреть настройки, убрав пустые строки и комментарии, используем команду:
Кроме того, есть еще ряд параметров, устанавливаемых по умолчанию. Традиционно для SSH-соединений используется TCP-порт 22. За это отвечает директива Port.
Практика показывает, что стоит появиться новому серверу, как через некоторое время к нему подтягиваются программы-брутфорсеры. В большинстве случаев работают они по простому алгоритму: сначала проверяется диапазон IP-адресов на наличие открытого 22 порта, и если таковые будут найдены, запускается программа перебора пароля.
Самым простым способом защиты является изменение порта по умолчанию. Выставляем:
Port 8022
При подключении к системе следует указать порт при помощи ключа '–p':
$ ssh -p8022 user@127.0.0.1
Естественно, такой подход не сможет защитить от опытного хакера, но большинство примитивных скриптов «не найдут» спрятанный сервер SSH. Плюс, повесив на 22 порт ловушку honeypot, можно отлавливать и блокировать подобные попытки.
Параметр AddressFamily позволяет определить адресное пространство, с которым придется иметь дело серверу и подключающимся клиентам. Его отсутствие в файле конфигурации означает установку значения «any» – то есть сервер готов работать с протоколами IPv4 и IPv6. Я использую только первый из них:
AddressFamily inet
Актуальна версия OpenSSH 5.0/5.0p1, которая полностью совместима с SSH 1.3, 1.5 и 2.0. Защищенность протокола SSH 1 по нынешним меркам считается недостаточной и по умолчанию используется SSH 2, устойчивый к атакам типа man-in-the-middle, TCP-hijacking и DNS-spoofing. Все современные клиенты (SecureCRT, Putty, TeraTerm Pro) умеют работать с SSH 2, поэтому нет смысла активировать SSH 1:
Protocol 2
Сжатие потока можно регулировать при помощи опций:
Compression yes
CompressionLevel 6 # Допустимые значения от 1 до 9
Высшую степень компрессии стоит применять только при дорогостоящем трафике или медленных каналах.
Настройки доступа
По умолчанию sshd принимает подключения на всех интерфейсах, что нужно далеко не всегда. Если не требуется заходить на сервер «извне», то ограничь его работу определенным адресом с помощью параметра ListenAddress:
# ListenAddress 0.0.0.0
ListenAddress 192.168.1.2
Кстати, дополнительно через двоеточие можно указать и номер порта, в этом случае значение Port игнорируется.
В большинстве дистрибутивов в целях безопасности доступ суперпользователю по SSH закрыт (PermitRootLogin no), и при попытке зарегистрироваться под root мы получаем сообщение об ошибке. Для выполнения задач, требующих привилегий администратора, приходится заходить под обычным пользователем и использовать su или sudo. Красиво выйти из ситуации поможет директива Match. В качестве аргумента ей передается критерий отбора (User, Group, Host, Address), его значение и параметр, который нужно применить. Для примера разрешим подключение под root только с localhost и из доверенной подсети 192.168.5.0/24:
PermitRootLogin no
Match Host 192.168.5.*,127.0.0.1
PermitRootLogin yes
По дефолту доступ к серверу разрешен для всех групп и пользователей. С помощью параметров AllowUsers/AllowGroups, DenyUsers/DenyGroups можно указать, кому разрешены, а кому запрещены входящие SSH-подключения. В качестве примера создадим отдельную группу, членам которой и будет разрешен доступ:
В Debian и Ubuntu для аутентификации по умолчанию используется GSSAPI (Generic Security Services Application Programming Interface), что обычно требует времени. Есть смысл использовать этот механизм только совместно с Kerberos 5, иначе его можно отключить, уменьшив задержку. Одновременно запретим использование одноразовых паролей на базе системы S/Key:
GSSAPIAuthentication no
ChallengeResponseAuthentication no
Несколько параметров в sshd_config позволяют контролировать время работы и бездействия клиента, но они не всегда так уж полезны. Например, по умолчанию TCPKeepAlive установлен в «yes»; это означает, что сервер будет периодически проверять, находится ли клиент «на линии» – если он не отвечает, соединение автоматически разрывается. И хотя с ним системные ресурсы не расходуются зря, в целях безопасности его лучше отключить:
TCPKeepAlive no
Хакер, анализируя такие пакеты, может провести ряд сетевых атак, поэтому вместо TCPKeepAlive лучше использовать директивы:
ClientAliveInterval 15
ClientAliveCountMax 3
Следующие два параметра позволяют контролировать неудачные подключения к серверу:
LoginGraceTime 60
MaxStartups 2:50:10
Параметр LoginGraceTime определяет, по истечению какого времени простаивающее подключение будет разорвано (в секундах). Значение по умолчанию (120) явно завышено. Количество параллельных неаутентифицированных подключений к серверу контролируется при помощи MaxStartups. Запись параметра имеет форму «start:rate:full». В нашем случае она означает отключение с вероятностью 50% при наличии двух неаутентифицированных связей с линейным ростом вероятности до 100% при достижении 10.
Установки в файлах /etc/ssh/sshrc или ~/.ssh/rc позволяют выполнить действия при регистрации пользователя. Здесь можно использовать любые команды оболочки. Например, отправляем на почту уведомление, что в систему по ssh зашел пользователь:
Таким образом, можно полностью контролировать подключения пользователей.
Золотые ключики
Аутентификация при помощи пароля не всегда безопасна, поэтому некоторые security-специалисты советуют ее отключить и воспользоваться авторизацией по ключам:
PasswordAuthentication no
PubkeyAuthentication yes
Чтобы подстраховаться, стоит ограничить доступ беспарольным клиентам. Нужные параметры можно указывать прямо в ~/.ssh/authorized_keys:
$ vim .ssh/authorized_keys
from="192.168.0.*,212.34.XX.YY" ssh-rsa AAAA[...]
Здесь же допускается задавать команды, которые будут вызваны при подключении:
Каталог /work, находящийся на сервере remotehost, будет сохранен в архив ~/backup/work-11052008.tar.bz2.
Защищаем сетевые соединения
Используя SSH, можно защитить информацию, которая передается программами, не имеющими встроенных механизмов шифрования соединения. Например, сделаем бэкап с помощью dump(8) на удаленный сервер:
$ sudo dump -0au -f - /dev/rwd1a | gzip -9 | \
ssh remotehost 'dd of=cvs_backup.dump.gz'
Хотя если немного постараться, dump можно и без применения каналов подружить с ssh:
Примечание редактора: при трансфере двоичных данных всегда проверяй размер исходных и целевых файлов – баги могут подстерегать в самых неожиданных местах:
reading message user@localhost.domain.ru:1 of 1 (8062 octets)....... flushed
Организовав защищенный туннель, можно перенаправить в него любой трафик. Например, смонтируем удаленный ресурс Samba по каналу, организованному через SSH:
$ ssh -L 8139:domain.ru:139 user@domain.ru
SSH-форвардинг в зависимости от того, где перенаправляются пакеты, можно организовать двумя способами: локально (ключ '-L') или удаленно ('-R'). Во многих системах открывать соединения с портами ниже 1024 имеет право только root, поэтому выбираем 8139. Теперь монтируем удаленный ресурс:
Другой вариант настройки форвардинга – использование файла ~/.ssh/config. Например, настроим 192.168.1.1 на перенаправление входящей и исходящей почты по шифрованному каналу для клиентов из 192.168.1.0/24 на mail.domain.ru:
$ vim .ssh/config
Host mail
Hostname mail.domain.ru
LocalForward 192.168.1.1:8025 mail.domain.ru:25
LocalForward 192.168.1.1:8110 mail.domain.ru:110
LocalForward 192.168.1.1:8143 mail.domain.ru:143
GatewayPorts yes
Кстати, прописав в ~/.ssh/config параметры всех используемых серверов, можно с легкостью управлять сразу всей стаей.
Если часто приходится работать с несколькими удаленными хостами, советую присмотреться к проекту ClusterSSH (clusterssh.sf.net). Он позволяет открыть несколько соединений по SSH и одновременно выполнять на них команды. Нужные пакеты уже есть в репозитарии Debian/Ubuntu:
$ sudo aptitude install clusterssh
И запускаем:
$ cssh one two three
Параметр ProxyCommand позволяет выполнить произвольную команду. Для примера подключимся через шлюз к файловому серверу, который находится за NAT:
$ vim .ssh/config
Host gateway
HostName ns.domain.ru
Host filesrv
HostName 192.168.5.201
ProxyCommand ssh gateway nc -w 180 %h %p
Подключаемся:
$ ssh filesrv
Использование параметра ControlMaster позволяет ускорить доступ к удаленному серверу за счет того, что в специальном файле сохраняются все параметры предыдущего сеанса, которые и используются при повторном подключении. Для примера создадим две Host-секции:
$ vim .ssh/config
Host srv1
HostName 213.167.XX.YY
ControlMaster yes
# Здесь %r - имя, %h – хост и %p - порт
ControlPath ~/.ssh/ctl-%r-%h-%p
Host srv1fast
HostName 213.167.XX.YY
ControlMaster no
ControlPath ~/.ssh/ctl-%r-%h-%p
Теперь на сервере srv1 выполняем утилиту uptime. Логинимся на нем (чтобы создать локальный сокет для второго подключения), переходим на другую консоль и снова запрашиваем статистические счетчики:
Как видишь, при мультиплексировании соединений время выполнения команды uptime на удаленном сервере уменьшилось в 25 раз – настоящее турбореактивное ускорение!
Секурные носки
Но это еще не все чудеса. OpenSSH можно использовать как специальный SOCKS-сервер, который поддерживает более гибкое проксирование, чем простое перенаправление портов. Например, команда:
$ ssh –D1080 user@domain.ru
создает локальный SOCKS5-сервер, который ждет подключения на localhost:1080. Альтернативный вариант – прописать директиву DynamicForward в .ssh/config:
$ vim .ssh/config
Host proxy
HostName ns.domain.ru
DynamicForward 1080
Подключаемся, введя «ssh proxy». Протестировать работу SOCKS5-сервера можно такой командой:
В OpenSSH 4.9 появилась долгожданная поддержка chroot(2) для sshd, контролируемая с помощью опции ChrootDirectory. К примеру, заставим подключающегося по sftp пользователя warez переходить в измененный корневой каталог 0day:
$ sudo vim /etc/ssh/sshd_config
#Subsystem sftp /usr/libexec/sftp-server
Subsystem sftp internal-sftp
Match User warez
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
ChrootDirectory /0day
Вместо заключения
Автодополнение хостов можно выполнить за счет использования встроенных средств командной оболочки:
Параноидально настроенные администраторы, возможно, захотят, наоборот, зашифровать все IP и доменные адреса из файла .ssh/known_hosts. Делается это так: