За последние несколько лет OpenSSH из простого набора программ для защищенной системы регистрации, выполнения команд на удаленном хосте и передачи файлов с одной машины на другую превратился в швейцарский армейский нож, потрясающий своими возможностями. Бьюсь об заклад, ты не используешь и полвину из них.
OpenSSH включен практически во все варианты *nix-систем, поэтому не будем останавливаться на инсталляции и сразу перейдем к настройкам, секретным трюкам и советам.
Чтобы просмотреть настройки, убрав пустые строки и комментарии, используем команду:
% egrep -v '^#' /etc/ssh/sshd_config | egrep -v '^$'
Кроме того, есть еще ряд параметров, устанавливаемых по умолчанию. Традиционно для 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:
По дефолту доступ к серверу разрешен для всех групп и пользователей. С помощью параметров AllowUsers/AllowGroups, DenyUsers/DenyGroups можно указать, кому разрешены, а кому запрещены входящие SSH-подключения. В качестве примера создадим отдельную группу, членам которой и будет разрешен доступ:
В конфиг OpenSSH прописываем:
В Debian и Ubuntu для аутентификации по умолчанию используется GSSAPI (Generic Security Services Application Programming Interface), что обычно требует времени. Есть смысл использовать этот механизм только совместно с Kerberos 5, иначе его можно отключить, уменьшив задержку. Одновременно запретим использование одноразовых паролей на базе системы S/Key:
Несколько параметров в sshd_config позволяют контролировать время работы и бездействия клиента, но они не всегда так уж полезны. Например, по умолчанию TCPKeepAlive установлен в «yes»; это означает, что сервер будет периодически проверять, находится ли клиент «на линии» – если он не отвечает, соединение автоматически разрывается. И хотя с ним системные ресурсы не расходуются зря, в целях безопасности его лучше отключить:
TCPKeepAlive no
Хакер, анализируя такие пакеты, может провести ряд сетевых атак, поэтому вместо TCPKeepAlive лучше использовать директивы:
Следующие два параметра позволяют контролировать неудачные подключения к серверу:
Параметр LoginGraceTime определяет, по истечению какого времени простаивающее подключение будет разорвано (в секундах). Значение по умолчанию (120) явно завышено. Количество параллельных неаутентифицированных подключений к серверу контролируется при помощи MaxStartups. Запись параметра имеет форму «start:rate:full». В нашем случае она означает отключение с вероятностью 50% при наличии двух неаутентифицированных связей с линейным ростом вероятности до 100% при достижении 10.
Установки в файлах /etc/ssh/sshrc или ~/.ssh/rc позволяют выполнить действия при регистрации пользователя. Здесь можно использовать любые команды оболочки. Например, отправляем на почту уведомление, что в систему по ssh зашел пользователь:
$ sudo vim /etc/ssh/sshrc
echo $(date) $SSH_CONNECTION $USER $SSH_TTY | mail -s "ssh login" admin@domain.ru
Таким образом, можно полностью контролировать подключения пользователей.
Аутентификация при помощи пароля не всегда безопасна, поэтому некоторые security-специалисты советуют ее отключить и воспользоваться авторизацией по ключам:
Чтобы подстраховаться, стоит ограничить доступ беспарольным клиентам. Нужные параметры можно указывать прямо в ~/.ssh/authorized_keys:
$ vim .ssh/authorized_keys
from="192.168.0.*,212.34.XX.YY" ssh-rsa AAAA[...]
Здесь же допускается задавать команды, которые будут вызваны при подключении:
command="ssh -t user@192.168.5.201" ssh-rsa AAAA[...]
Этот подход можно использовать для создания бэкапов. Генерируем пару ключей (секретный и публичный):
$ sudo ssh-keygen -t rsa -C 'remote backup'
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): /home/user/.ssh/id_rsa_backup
Добавляем публичный ключ в список авторизованных ключей на удаленной системе:
$ ssh remotehost "mkdir -m 700 .ssh; umask 077"; \
cat > .ssh/authorized_keys" < .ssh/id_rsa_backup.pub
Затем редактируем authorized_keys (ключ '-t' следует использовать при запуске программ, требующих для своей работы наличия псевдотерминала):
$ ssh -t remotehost vim .ssh/authorized_keys
from="192.168.0.*,212.34.XX.YY",command="cd /work; tar cvf - ./* | bzip2 -9",no-pty,no-agent-forwarding,no-X11-forwarding,no-port-forwarding ssh-rsa AAAA[...]
И запускаем процедуру резервного копирования:
$ ssh -i .ssh/id_rsa_backup remotehost > \
~/backup/work-`date +%d%m%Y`.tar.bz2 2>/dev/null
Каталог /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:
Передать файл, используя OpenSSH, можно одним из следующих способов:
Примечание редактора: при трансфере двоичных данных всегда проверяй размер исходных и целевых файлов – баги могут подстерегать в самых неожиданных местах:
Чтобы рекурсивно отправить весь каталог, набираем:
$ scp -r mydir user@host.domain.ru:~/
Для безопасного получения почты к fetchmail легко прикрутить ssh. Для этого создаем файл ~/.fetchmailrc с содержанием:
poll localhost with protocol pop3 and port 8110:
preconnect "ssh -f -q -C user@213.167.XX.YY \
-L 8110:213.167.XX.YY:110 sleep 10" password noIdea;
Забираем почту:
$ fetchmail
1 message for user at localhost (8062 octets).
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. Теперь монтируем удаленный ресурс:
$ smbmount //domain.ru/share /mnt -o username=user,ip=localhost,port=8139
Аналогично можно туннелировать и любой другой трафик. Например, организуем подключение к удаленному SMTP-серверу через SSH:
# ssh -L 25:domain.ru:25 user@domain.ru
Альтернативным решением будет использование файла authorized_keys и запуск с помощью xinetd.
# cat ~/.ssh/tunnel_key
command="nc localhost 25",no-X11-forwarding,no-agent-forwarding,no-port-forwarding ssh-rsa AAAA[...]
Подключаемся:
# ssh -i ~/.ssh/tunnel_key user@domain.ru
В ответ должны получить баннер удаленного почтового сервера. Теперь создаем файл для xinetd:
$ sudo vim /etc/xinetd.d/smtp
Другой вариант настройки форвардинга – использование файла ~/.ssh/config. Например, настроим 192.168.1.1 на перенаправление входящей и исходящей почты по шифрованному каналу для клиентов из 192.168.1.0/24 на mail.domain.ru:
$ vim .ssh/config
Кстати, прописав в ~/.ssh/config параметры всех используемых серверов, можно с легкостью управлять сразу всей стаей.
Теперь опросим серверы командой:
ksh% for i in 1 2; do ssh server$i "uptime"; done
Как вариант, для этих целей можно использовать интерпретатор Perl (пример для 10 подконтрольных серверов):
% perl -e 'foreach $i (1 .. 10) {print `ssh server$i "uptime"`}'
Если часто приходится работать с несколькими удаленными хостами, советую присмотреться к проекту ClusterSSH (clusterssh.sf.net). Он позволяет открыть несколько соединений по SSH и одновременно выполнять на них команды. Нужные пакеты уже есть в репозитарии Debian/Ubuntu:
$ sudo aptitude install clusterssh
И запускаем:
$ cssh one two three
Параметр ProxyCommand позволяет выполнить произвольную команду. Для примера подключимся через шлюз к файловому серверу, который находится за NAT:
$ ssh filesrv
Использование параметра ControlMaster позволяет ускорить доступ к удаленному серверу за счет того, что в специальном файле сохраняются все параметры предыдущего сеанса, которые и используются при повторном подключении. Для примера создадим две Host-секции:
# Здесь %r - имя, %h – хост и %p - порт
Теперь на сервере srv1 выполняем утилиту uptime. Логинимся на нем (чтобы создать локальный сокет для второго подключения), переходим на другую консоль и снова запрашиваем статистические счетчики:
ttyp0% time ssh srv1 uptime
Как видишь, при мультиплексировании соединений время выполнения команды uptime на удаленном сервере уменьшилось в 25 раз – настоящее турбореактивное ускорение!
Но это еще не все чудеса. OpenSSH можно использовать как специальный SOCKS-сервер, который поддерживает более гибкое проксирование, чем простое перенаправление портов. Например, команда:
$ ssh –D1080 user@domain.ru
создает локальный SOCKS5-сервер, который ждет подключения на localhost:1080. Альтернативный вариант – прописать директиву DynamicForward в .ssh/config:
Подключаемся, введя «ssh proxy». Протестировать работу SOCKS5-сервера можно такой командой:
$ echo -n "GET / HTTP/1.0\r\n\r\n" | nc -X 5 -x 127.0.0.1:1080 \
Теперь носки готовы к использованию:
$ tsocks thunderbird
В OpenSSH 4.9 появилась долгожданная поддержка chroot(2) для sshd, контролируемая с помощью опции ChrootDirectory. К примеру, заставим подключающегося по sftp пользователя warez переходить в измененный корневой каталог 0day:
$ sudo vim /etc/ssh/sshd_config
Автодополнение хостов можно выполнить за счет использования встроенных средств командной оболочки:
$ vim ~/.bash_profile
Параноидально настроенные администраторы, возможно, захотят, наоборот, зашифровать все IP и доменные адреса из файла .ssh/known_hosts. Делается это так:
+|1|TJ2SaXGqO8uHYeiA92KuNRIKR7M=|GpQB8Qz0tQPqA+nF+ghe37mpcHA= ssh-rsa AAAA[...]
Чтобы работал форвардинг, параметр AllowTcpForwarding в файле sshd_config должен быть установлен в значение «yes».
Программа ClusterSSH (clusterssh.sf.net) позволяет открыть несколько соединений по SSH и одновременно выполнять на них команды.
С помощью SHFS (SHell FileSystem, shfs.sf.net) очень просто монтировать файловые системы, расположенные на удаленных компьютерах.
По адресу www.jfranken.de/homepages/johannes/vortraege/ssh2_inhalt.en.html ты найдешь отличное руководство по созданию туннелей.