OpenSSH: ювелирное конфигурирование и изысканные методы использования
Ульяна Смелая
За последние несколько лет OpenSSH из набора программ для защищенной системы регистрации, выполнения команд на удаленном хосте и передачи файлов с одной машины на другую превратился в швейцарский армейский нож, просто потрясающий своими возможностями. Бьюсь об заклад, ты не используешь и половину из них.
Содержание:
- С места в карьер
- Настройки доступа
- Золотые ключики
- Защищаем сетевые соединения
- Продвинутое использование .ssh/config
- Секурные носки
- Поиграем в песочнице
- Вместо заключения
- Врезка: Из чего состоит 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 # Допустимые значения от 1 до 9 CompressionLevel 6
Высшую степень компрессии стоит применять только при дорогостоящем трафике или медленных каналах.
По умолчанию 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-подключения. Для примера создадим отдельную группу, членам которой и будет разрешен доступ:
$ sudo addgroup --gid 450 sshlogin $ sudo adduser petja sshlogin
И в конфиг OpenSSH прописываем:
AllowUsers admin@212.34.10.* AllowGroups sshlogin
В 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 зашел пользователь:
$ sudo vim /etc/ssh/sshrc echo $(date) $SSH_CONNECTION $USER $SSH_TTY | mail -s "ssh login" admin@domain.ru
Таким образом, можно полностью контролировать подключения пользователей.
Аутентификация при помощи пароля не всегда является безопасной, поэтому некоторые security-специалисты советуют ее отключить и воспользоваться авторизацией по ключам:
PasswordAuthentication no PubkeyAuthentication yes
Чтобы подстраховаться, стоит ограничить доступ беспарольным клиентам. Нужные параметры можно указывать прямо в ~/.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_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:
$ ssh remotehost touch /home/user/cvs.dump $ env RSH=`which ssh` sudo -E dump 0f remotehost:/home/user/cvs.dump /cvs
Передать файл, используя OpenSSH, можно одним из следующих способов:
$ ssh remotehost touch /home/user/cvs.dump $ env RSH=`which ssh` sudo -E dump 0f remotehost:/home/user/cvs.dump /cvs
Примечание редактора: при трансфере двоичных данных всегда проверяй размер исходных и целевых файлов, баги могут подстерегать нас в самых неожиданных местах:
% dd if=/dev/arandom of=/tmp/file1 bs=1k count=1k 2>/dev/null % ssh -t localhost "cat /tmp/file1" >/tmp/file2 % ls -l /tmp/file* -rw-r--r-- 1 andrushock wsrc 1048576 May 11 13:55 /tmp/file1 -rw-r--r-- 1 andrushock wsrc 1066982 May 11 13:56 /tmp/file2
Чтобы рекурсивно отправить весь каталог, набираем:
$ 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
service smtp
{
socket_type = stream
protocol = tcp
wait = no
user = root
disable = no
server = /usr/bin/ssh
server_args = -q -T -i /root/.ssh/tunnel_key user@domain.ru
groups = yes
bind = 127.0.0.1
}
Продвинутое использование .ssh/config
Другой вариант настройки форвардинга – использование файла ~/.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 параметры всех используемых серверов, можно с легкостью управлять сразу всей стаей.
$ vim .ssh/config Host server1 HostName ns.domain1.ru User admin Host server2 Hostname mail.domain2.ru User support
Теперь опросим серверы следующей командой:
ksh% for i in 1 2; do ssh server$i "uptime"; done 5:37PM up 1 day, 23:45, 1 user, load averages: 0.25, 0.22, 0.22 5:37PM up 51 days, 1:49, 0 users, load averages: 0.25, 0.25, 0.24
Как вариант, для этих целей можно использовать интерпретатор Perl (пример для 10 подконтрольных серверов):
$ perl -e 'foreach $i (1 .. 10) {print `ssh server$i "uptime"`}'
Если часто приходится работать с несколькими удаленными хостами, советую присмотреться к проекту ClusterSSH (). Он позволяет открыть несколько соединений по 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 выполняем утилиту , логинимся на нем (чтобы создать локальный сокет для второго подключения), переходим на другую консоль и снова запрашиваем статистические счетчики:
ttyp0% time ssh srv1 uptime
5:55PM up 37 days, 9:19, 1 user, load averages: 0.33, 0.32, 0.33
0m0.77s real 0m0.06s user 0m0.01s system
ttyp0% ssh srv1
ttyp1% time ssh srv1fast 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-сервера можно такой командой:
$ echo -n "GET / HTTP/1.0\r\n\r\n" | nc -X 5 -x 127.0.0.1:1080 \ www.domain.ru 80 | head -4 HTTP/1.1 200 OK Date: Sat, 23 Feb 2008 14:27:43 GMT Server: Apache X-Powered-By: PHP/4.4.1
Теперь носки готовы к использованию:
$ tsocks thunderbird
В OpenSSH 4.9 появилась долгожданная поддержка для 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
Автодополнение хостов можно выполнить за счет использования встроенных средств командной оболочки:
$ vim ~/.bash_profile complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' \ | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh
Параноидально настроенные администраторы, возможно, захотят наоборот зашифровать все IP и доменные адреса из файла .ssh/known_hosts. Делается это следующим образом:
$ echo 'HashKnownHosts' >> ~/.ssh/config $ ssh-keygen -H -f ~/.ssh/known_hosts $ head -1 ~/.ssh/known_hosts +|1|TJ2SaXGqO8uHYeiA92KuNRIKR7M=|GpQB8Qz0tQPqA+nF+ghe37mpcHA= ssh-rsa AAAA[...]
Врезка: Из чего состоит OpenSSH
- ssh-add – вспомогательная программа для добавления личных ключей в кэш;
- ssh-agent - демон, занимающийся кэшированием дешифрованных личных ключей;
- scp – утилита для безопасного копирования файлов между хостами;
- sftp – клиентская программа для sftp-server;
- sftp-server – серверная реализация защищенного ftp;
- ssh – клиент, обеспечивающий безопасное соединение;
- sshd – демон, ожидающий подключения, выполняющий аутентификацию и полностью обслуживающий ssh-клиента;
- ssh-keygen – утилита для создания и модификации ключей;
- ssh-keyscan – утилита для сбора публичных ключей;
- ssh-keysign – помощник при использовании метода аутентификации, основанного на проверке хостов.
INFO
-
Чтобы работал форвардинг, параметр AllowTcpForwarding в файле sshd_config должен быть установлен в значение "yes".
-
Программа ClusterSSH () позволяет открыть несколько соединений по SSH и одновременно выполнять на них команды.
-
С помощью SHFS (SHell FileSystem, ) очень просто монтировать файловые системы, расположенные на удаленных компьютерах.
WWW
-
По адресу найдешь отличное руководство по созданию туннелей на все случаи.
Статья опубликована в июньском номере журнала "Xakep" за 2008 год.





