Волшебные криптотуннелиУльяна Смелая Хакер, номер #115, стр. 115-132-1 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. Для наглядности сценарий можно представить следующим образом: (10.0.0.1) 212.34.XX.YY 213.167.XX.YY (10.0.0.2) 192.168.2.0/24 --- srv1 --- [ internet ] --- srv2 --- 192.168.1.0/24 192.168.2.1 192.168.1.1 Стоит отметить, с помощью 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-туннелей): srv1% sudo vim /etc/pf.conf pass quick on { tun0, tun1 } inet all Загружаем правила из конфига: srv1% sudo pfctl -f /etc/pf.conf Создаем интерфейс tun1 и назначаем ему IP-адрес: srv1% sudo ifconfig tun1 create srv1% sudo ifconfig tun1 10.0.0.1 10.0.0.2 netmask 0xfffffffc При помощи команды 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 vim /etc/pf.conf pass quick on { tun0, tun1 } inet all srv2% sudo pfctl -f /etc/pf.conf srv2% sudo ifconfig tun1 create srv2% sudo ifconfig tun1 10.0.0.2 10.0.0.1 netmask 0xfffffffc srv2% sudo route add 192.168.2.0/24 10.0.0.1 И, наконец, самый ответственный момент – устанавливаем защищенное соединение между двумя сетями: 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 -R[bind_address:]port:host:hostport Request remote forward -KR[bind_address:]port Cancel remote forward Если в ~/.ssh/config установить значение директивы PermitLocalCommand в yes, то мы сможем выполнять команды в локальном шелле (то есть на хосте, с которого зашли): ns% ssh mx3 mx3% <Enter>~C ssh> !uptime /* команда выполняется на хосте ns */ 7:02PM up 100 days, 11 mins, 1 user, load averages: 0.13, 0.21, 0.23 <Enter> mx3% uptime /* команда выполняется на хосте mx3 */ 7:02PM up 4 days, 7:34, 1 user, load averages: 0.21, 0.23, 0.19 Если на предыдущем узле требуется выполнить сразу несколько команд, то 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): % mx2 uptime 5:16PM up 45 days, 8:40, 0 users, load averages: 0.55, 0.40, 0.35 Если узлов несколько, то для каждого создаем аналогичную символическую ссылку, выбрав в качестве имени его 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 \ (max-src-conn-rate 5/60, overload <sshbf> flush global) Здесь фильтр пакетов не допустит более пять одновременных соединений к 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) и другие. VShell Server для Windows: www.vandyke.com/products/vshell/. |