OpenSSH: демонстрация фокусов с их последующим разоблачением
Ульяна Смелая
Хакеров и опытных админов отличает способность находить изящное решение какой-либо задачи. Как ты смотришь на то, чтобы использовать OpenSSH для создания виртуальных частных сетей, причем без применения SSH-перенаправлений, соксификации и сторонних разработок, таких как, например, OpenVPN?
Содержание:
- VPN на базе SSH
- Управляющие последовательности SSH
- Админ должен быть ленив!
- Обходим файерволы
- Безопасный SFTP
- Ограничение подключений к SSH
- Заключение
- Врезка
- Боковые выносы
В последнее время широкое распространение получила технология VPN. Интересна она не только тем, что обеспечивает защиту передаваемой информации за счет шифрования трафика между несколькими узлами или сетями, оставляя снифферы и программы MitM-атак не у дел. Есть и другие плюсы, среди которых:
-
объединение территориально разрозненных сетей для предоставления безопасного доступа к внутренним ресурсам организации;
-
снижение расходов на содержание корпоративных сетей (т.к. в качестве магистрали для передачи корпоративного IP-трафика используется всемирная паутина, кроме того, при открытии нового филиала или появлении сотрудника, которому разрешено пользоваться удаленным доступом, не нужно никаких дополнительных затрат);
-
организация совместного доступа в интернет;
-
возможность сокрытия своего реального IP-адреса;
-
гарантия требуемых параметров качества обслуживания (Quality of Service) для передачи голоса/видео поверх IP.
Обычно при упоминании о 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=51mtu 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 (см. ).
Управляющие последовательности 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", и мы попадем на заветный сервер. Уже не плохо, однако каждый раз приходится набирать 4 "лишних" символа (ssh и пробел). Лень сподвигает на написание двухстрочного сценария, "съедающего" ssh, но сохраняющего все переданные в командной строке аргументы, пробелы и кавычки:
% cd ~/bin
% vim myssh #!/bin/sh exec /usr/bin/ssh `/usr/bin/basename $0` $@
Наделяем скрипт атрибутом исполнения и создаем символическую ссылку на псевдоним удаленного сервера:
% chmod +x myssh % ln -s myssh mx2
Вуаля, вводить ssh больше не требуется (примечание: подкаталог bin должен быть прописан в переменной окружения PATH):
% mx2 uptime 5:16PM up 45 days, 8:40, 0 users, load averages: 0.55, 0.40, 0.35
Если узлов несколько, то для каждого создаем аналогичную символическую ссылку, выбрав в качестве имени его hostname.
Кстати, небольшой оптимизации можно достигнуть, отказавшись от вызова утилиты и применив встроенные возможности командной оболочки:
% 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 SettingsSmelayaMy Documents>
Как видишь, SSH-туннель – это самый простой способ, позволяющий обойти файервол и получить доступ к закрытому админом сервису. Есть и специализированные приложения, предназначенные для более удобной организации SSH-туннелей. Например, RSTunnel (Reliable SSH Tunnel, ), Corkscrew () и другие.
Многие хостинговые компании предоставляют своим пользователям доступ по 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 является любимой мишенью злоумышленников, поэтому следует принять некоторые меры безопасности. Одна из них – ограничение количества подключений, чтобы избежать 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
Таким образом мы разрешили 3 подключения к 8022 порту в течение 5 минут. В 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)
Здесь фильтр пакетов не допустит более 5 одновременных соединений к 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 (), pam-abl (), DenyHosts () и другие.
- VShell Server для Windows: .
Статья опубликована в июльском номере журнала "Xakep" за 2008 год.






Статья хорошая, пожалуй самое полное освещение вопроса в рунете, но хочется добавить один момент:
при поднятие туннелей на tun девайсах выше озвученная схема, будет работать только для хостхост, если же необходимо хостсеть, или сетьсеть – то разумно добавить поддержку proxy-arp (в случае сетьсеть на обоих гейтах).
Примерно так: arp -s tun_ip ether_int_if|auto pub
В противном случае: в сниф-логе с внутр. интерфеса машины в удаленной сети будем видеть многозначительные arp whohas без ответа и пакеты соответственно назад ходить не будут ;-)
Я вот тут сейчас покумекал… вобщем отказался от прокси-арп, можно поступить интереснее оказывается… вобщем после создания интерфейса, когда ifconfig-ом задаем его параметры, можно добавить в конец ключик «arp» и ifconfig сам «родит» tun-интерфейсу MAC от балды – в итого имеет неописуемую красоту ;-)