OpenSSH: демонстрация фокусов с их последующим разоблачением
Хакеров и опытных админов отличает способность находить изящные решения поставленных задач. Как ты смотришь на то, чтобы использовать OpenSSH для создания виртуальных частных сетей? Причем, без применения SSH-перенаправлений, соксификации и сторонних разработок, таких как, например, OpenVPN.
VPN на базе SSH
В последнее время технология VPN получила завидное распространение. Обычно, упоминая ее, подразумевают либо стандартные протоколы туннелирования PPTP и L2TP/IPsec, либо специализированные решения, вроде OpenVPN, и лишь немногие знают о более простой альтернативе – SSH-туннелинг. Поднятые на втором или третьем уровне OSI зашифрованные туннели обеспечат приложениям полноценный и прозрачный доступ к любым ресурсам удаленной сети. А учитывая, что SSH-сессии не только шифруются (по умолчанию задействован алгоритм AES), но и сжимаются, мы, кроме приватности, получим небольшой прирост в скорости и экономию драгоценных мегабайтов. Немаловажно, что такой подход не требует знания протоколов защиты сетевого трафика, вмешательства в ядро операционной системы, заморочек с фильтрацией пакетов или наличия особых программ.
Для примера возьмем два сервера: srv1 с IP-адресами 212.34.XX.YY и 192.168.2.1 подключен к сегменту внутренней сети 192.168.2.0/24, а srv2 с 213.167.XX.YY и 192.168.1.1 шефствует над подопечными из 192.168.1.0/24. Настроим VPN-туннель средствами OpenSSH, в котором будут использоваться адреса 10.0.0.1 и 10.0.0.2. Для наглядности сценарий можно представить следующим образом:
Стоит отметить, с помощью OpenSSH возможно построение не только Site-to-Site VPN (межсайтовое подключение, в котором два маршрутизатора создают туннель в интернете), но и Client-to-Site (VPN-подключение удаленного доступа для проводных и беспроводных клиентов).
Ключевые элементы сетевой конфигурации рассмотрены, теперь приступаем к настройкам. Логинимся на srv1 и правим главный конфигурационный файл sshd:
srv1% sudo vim /etc/ssh/sshd_config
# Разрешаем туннелирование layer-3
PermitTunnel point-to-point
# VPN на базе OpenSSH требует привилегий суперпользователя, поэтому аутентификацию под учетной записью root разрешаем только с доверенных хостов
PermitRootLogin no
Match Host 213.167.XX.YY,192.168.2.*,127.0.0.1
PermitRootLogin yes
По окончании настроек не забываем отправить демону сигнал SIGHUP, чтобы он смог перечитать свой конфиг:
srv1% sudo sh -c "kill -HUP `sed q /var/run/sshd.pid`"
Далее разрешаем прохождение пакетов на используемых туннельных псевдоустройствах (на tun0 у меня висит OpenVPN, tun1 – для OpenSSH; tun представляет собой нечто вроде драйвера IP-туннелей):
При помощи команды ifconfig проверяем его состояние:
srv1% ifconfig tun1
tun1: flags=51<UP,POINTOPOINT,RUNNING> mtu 1500
groups: tun
inet 10.0.0.1 --> 10.0.0.2 netmask 0xfffffffc
Не забываем добавить в таблицу маршрутизации удаленную подсеть:
srv1% sudo route add 192.168.1.0/24 10.0.0.2
Второй сервер выступает в роли SSH-клиента, поэтому процедура конфигурирования здесь чуть проще:
srv2% sudo sh -c "echo 'Tunnel point-to-point' \
>> /etc/ssh/ssh_config"
Остальные настройки и действия практически идентичны описанным выше: правим и активируем рулесеты файрвола, поднимаем tun1, присваиваем ему сетевой адрес (обрати внимание, порядок следования IP-адресов изменен) и добавляем статический маршрут:
И, наконец, самый ответственный момент – устанавливаем защищенное соединение между двумя сетями:
srv2% sudo ssh -f -w 1:1 212.34.XX.YY true
Чтобы снизить накладные расходы, к списку аргументов имеет смысл добавить: «-o Compression=yes -x -a –n» (сжимать передаваемые данные, отключить пересылку пакетов X11, запретить аутентификацию с помощью агента и направить /dev/null на стандартный входной поток STDIN).
Теперь проверим доступность удаленного узла, находящегося «за первым сервером»:
srv2% ping 192.168.2.101
PING 192.168.2.101 (192.168.2.101): 56 data bytes
64 bytes from 192.168.2.101: icmp_seq=0 ttl=127 time=2.508 ms
Если все ОК, то можно и дальше развивать предложенную схему, упрощая или, наоборот, усложняя настройки. Например, применить беспарольную аутентификацию на базе ключей, нарисовать конфигурационный файл для автоматического создания псевдоустройства tun1:
srv2% sudo sh -c "echo '10.0.0.2 10.0.0.1 netmask 0xfffffffc' \
> /etc/hostname.tun1"
Занести необходимые статические маршруты и запуск «ssh -f –w» в один из сценариев начальной загрузки (/etc/rc.local). Или в отдельный скрипт, чтобы все выполнялось одной командой, без дополнительных телодвижений.
Чтобы использовать OpenSSH на уровне OSI 2, нужно в качестве значения директив PermitTunnel и Tunnel использовать ethernet, а затем объединить в мост внешний сетевой интерфейс и псевдоустройство tunX (см. bridge(4)).
Управляющие последовательности SSH
Продолжим фокусничать. Таинство магии управляющих последовательностей откроется, если в SSH-сессии сначала нажать <Enter>, затем – управляющий символ сеанса (по умолчанию тильда, задается директивой EscapeChar) и специальную клавишу, которая указывает, какую именно функцию следует выполнить. Проще всего это показать на конкретных примерах.
Допустим, мы с mail.domain.ru зашли на bastion.domain2.ru и решили, что неплохо было бы открыть обратный шифрованный туннель к почтовому серверу для безопасной загрузки сообщений. С помощью комбинации клавиш «<Enter>~C» можно интерактивно управлять локальным и удаленным форвардингами (ключи '-L' и '-R'):
bastion% <Enter>~C
ssh> -R 8110:mail.domain.ru:110
Forwarding port.
Проверяем работу созданного почтового туннеля:
bastion% telnet localhost 8110
+OK Dovecot ready.
В ответ получен баннер от Dovecot. Значит, все в порядке.
Кстати, обратившись к подсказке, получим список всех доступных ключей и дополнительных параметров:
bastion% <Enter>~C
ssh> help
Commands:
-L[bind_address:]port:host:hostport Request local forward
Если в ~/.ssh/config установить значение директивы PermitLocalCommand в yes, то мы сможем выполнять команды в локальном шелле (то есть на хосте, с которого зашли):
ns% ssh mx3
mx3% <Enter>~C
ssh> !uptime /* команда выполняется на хосте ns */
Если на предыдущем узле требуется выполнить сразу несколько команд, то SSH-сессию лучше временно «засуспендить» (приостановить выполнение программы ssh):
mx3% <Enter>~<Ctrl-Z>
[1] + Suspended "ssh" "$@"
Чтобы перевести SSH-сессию из остановленного режима в активный, воспользуйся командой fg.
Список текущих SSH-соединений можно просмотреть комбинацией:
mx3% <Enter>~#
The following connections are open:
#0 client-session (t4 r0 i0/0 o0/0 fd 5/6 cfd -1)
А для быстрого завершения SSH-сессии ставим точку:
mx3% <Enter>~.
Connection to 213.167.XX.YY closed.
Админ должен быть ленив!
Чтобы в консоли не вводить полное доменное имя, порт и учетную запись для подключения к удаленной системе, стоит заручиться поддержкой директивы Host:
% vim ~/.ssh/config
Host mx2
Hostname mx2.domain.ru
Port 2022
User admin
Таким образом, нам достаточно ввести «ssh mx2», – и мы попадем на заветный сервер. Уже не плохо, однако каждый раз приходится набирать четыре «лишних» символа (ssh и пробел). Лень сподвигает на написание двухстрочного сценария, «съедающего» ssh, но сохраняющего все переданные в командной строке аргументы, пробелы и кавычки:
% cd ~/bin
% vim myssh
#!/bin/sh
exec /usr/bin/ssh `/usr/bin/basename $0` $@
Наделяем скрипт атрибутом исполнения и создаем символическую ссылку на псевдоним удаленного сервера:
% chmod +x myssh
% ln -s myssh mx2
Вводить ssh больше не требуется (P.S. подкаталог bin должен быть прописан в переменной окружения PATH):
Если узлов несколько, то для каждого создаем аналогичную символическую ссылку, выбрав в качестве имени его hostname.
Небольшой оптимизации можно достигнуть, отказавшись от вызова утилиты basename(1) и применив встроенные возможности командной оболочки:
% vim myssh
#!/bin/sh
exec /usr/bin/ssh ${0##*/} $@
Обходим файрволы
Многие администраторы в целях безопасности скрывают свои сервера в демилитаризованной зоне либо за NAT'ом и разрешают входящие соединения только с доверенных IP-адресов и по определенным портам. Поэтому доступ ко многим полезным ресурсам получить напрямую нельзя. Это как раз тот случай, когда использование SSH-форвардинга может исправить ситуацию. Некоторые примеры были рассмотрены в предыдущем номере журнала, в статье «Калейдоскоп тайных знаний». Вот еще один вариант:
% vim ~/.ssh/config
# Шлюз на базе OpenBSD
Host gate
Hostname gate.domain.ru
# Для ускорения соединений включаем мультиплексирование SSH-сессий
ControlMaster auto
ControlPath ~/.ssh/ctl-%r-%h-%p
# Перенаправляем локальный порт на файловый сервер (Win2k3 с поднятым VShell)
LocalForward 8022 192.168.1.101:22
# Подключаясь к localhost:8022, мы будем попадать в файлопомойку
Host fileserver
Hostname localhost
Port 8022
ControlMaster auto
ControlPath ~/.ssh/ctl-%r-%h-%p
HostKeyAlias fileserver
Соединяемся с узлом gate и проверяем возможность подключения к локальному порту 8022:
% ssh -N -f gate
% telnet localhost 8022
SSH-2.0-VShell_3_0_4_656 VShell
Теперь можно логиниться на файловый сервер, который находится за NAT'ом, в обход рулесетов, установленных на шлюзе:
% ssh fileserver
Microsoft Windows [Version 5.2.3790]
C:\Documents and Settings\Smelaya\My Documents>
Как видишь, SSH-туннель – это самый простой способ, позволяющий обойти файрвол и получить доступ к закрытому админом сервису. Есть и специализированные приложения, предназначенные для более удобной организации SSH-туннелей. Например, RSTunnel (Reliable SSH Tunnel, rstunnel.sf.net), Corkscrew (www.agroman.net/corkscrew) и другие.
Безопасный SFTP
Многие хостинговые компании предоставляют своим пользователям доступ по FTP. Назначение каталогов может быть разное, но нас интересует, как сделать доступ безопаснее. Здесь на помощь также может прийти SSH:
% sudo vim /etc/ssh/sshd_config
Subsystem sftp internal-sftp
# Секция с хостинговыми клиентами
Match Group wwwusers
# Отключаем форвардинг
X11Forwarding no
AllowTcpForwarding no
# Работаем по защищенному протоколу SFTP в chroot окружении
ForceCommand internal-sftp
ChrootDirectory /var/www/hosting/%u
Теперь зарегистрированные пользователи будут допущены только к «своему» каталогу, при подключении модификатор «%u» будет заменен именем пользователя. При необходимости можно использовать «%h», который соответствует домашнему каталогу юзера.
Ограничение подключений к SSH
Сервис SSH – любимая мишень злоумышленников, поэтому следует принять некоторые предосторожности. Одна из них – ограничение количества подключений, чтобы избежать DoS-атаки и брутефорса паролей. Если в логах ты находишь большое количество записей вроде: «Failed password for root from» или «Invalid user admin from», можешь быть уверен – к твоему серверу подбирают пароли при помощи программ-брутфорсеров. Паниковать не стоит, эту проблему можно решить очень просто. Приведу правила для iptables:
# iptables -A INPUT -p tcp –dport 8022 -i eth1 -m state \
–state NEW -m recent –set
# iptables -A INPUT -p tcp –dport 8022 -i eth1 -m state \
–state NEW -m recent –update –seconds 300 \
–hitcount 3 -j DROP
Так мы разрешили три подключения к 8022 порту в течение пяти минут. В PF не сложнее:
% sudo vim /etc/pf.conf
table <sshbf> persist
block in log quick on $ext_if inet from <sshbf>
pass in log on $ext_if inet proto tcp to $ext_if port ssh keep state \
Здесь фильтр пакетов не допустит более пять одновременных соединений к 22 порту за 60 секунд. При желании правила можно ужесточить.
Заключение
С помощью семейства команд SSH можно не только обеспечить аутентификацию и шифрование данных между хостами, существенно затрудняя перехват со стороны других узлов, но и создать виртуальную частную сеть, объединяющую несколько компьютеров или сетей, обойти эшелонированные заслоны, заботливо выставленные админом, и наделить различные приложения новым функционалом. Набор сетевых инструментов OpenSSH обладает чрезвычайно богатыми возможностями, и с ними стоит познакомиться поближе.
Для перенаправления X11-подключений следует использовать ключ '–Y':
$ ssh -Y user@domain.com
Причем в конфиге /etc/ssh/sshd_config параметр «X11Forwarding» должен быть установлен в yes. Если X-сервер запущен на локальной системе, то активируем и «X11UseLocalhost».
INFO
Аутентификация и последующее шифрование SSH-сессии выполняется незаметно для пользователей.
Управляющая последовательность использует специальный управляющий символ (escape-символ), чтобы идентифицировать начало команды.
Некоторые примеры продвинутой работы с OpenSSH смотри в предыдущем номере журнала, в статье «Калейдоскоп тайных знаний».
WWW
Для борьбы с перебором пароля можно использовать специальные приложения: DenySSH (wiki.wonko.com/software/denyssh), pam-abl (pam-abl.sf.net), DenyHosts (denyhosts.sf.net) и другие.