- PVSM.RU - https://www.pvsm.ru -

Опыт маскировки OpenVPN-туннеля с помощью obfsproxy

Преамбула

В связи с наметившимися [1] тенденциями [2] решил я обфусцировать свой скромный OpenVPN-туннель, просто чтобы набить руку — мало ли пригодится…

Дано: дешевая VPS [3] с белым IP, работающая под Ubuntu Trusty Server Edition и служащая OpenVPN сервером.
Требуется: по-возможности замаскировать OpenVPN туннель под обычный трафик, желательно без изобретения велосипедов.

obfsproxy

Поскольку на VPS [3] уже была поднята Tor-нода, мысль об obfsproxy [4] пришла сама собой. Как оказалось, утилита действительно умеет притворяться SOCKS-proxy, а значит, обфусцировать не только соединения Tor, но и практически произвольный трафик. Пошарившись по Сети, я нашел несколько мануалов, но многие были либо устаревшими, либо выпускали из виду необходимые подробности.

Важно! Версии.

  • OpenVPN версий младше 2.3.4 содержит баг [5], мешающей нормальной работе с SOCKS прокси. Если вы хотите использовать режим socks, убедитесь, что у вас установлена подходящая версия OpenVPN.
  • Судя по всему, obfsproxy до сих пор не включен в репозиторий Tor, а в репозиториях Debian/Ubuntu могут лежать старые версии без подержки scramblesuit. В этом случае obfsproxy нужно устанавливать [6] с помощью утилиты pip (пакет python-pip):
     pip install obfsproxy
    

    По окончании установки убедитесь, что используется версия obfsproxy с поддержкой scramblesuit:

     obfsproxy scramblesuit -h
    

  • Версию obfsproxy для Windows можно извлечь из пакета Tor Browser [7], найдя подкаталог TorPluggableTransports.

Из man obfsproxy можно почерпнуть следующее

 obfsproxy [logging_options] [--data-dir path] transport [--dest destination] [--password BASE32PASS] mode listen_addr

Чуть подробнее:

  • --data-dir statepath — каталог для размещения временных данных. Необходим, если obfsproxy работает не в managed режиме.
  • transport — выбирает метод обфускации трафика и режим его передачи. Нас интересуют следующие транспорты:
    • scramblesuit — сравнительно новый метод, который мы и будем использовать.
    • dummy — отладочный метод, при котором трафик передаётся как есть, без обфускации.

  • mode — выбирает режим работы прокси. Нас интересуют следующие режимы:
    • server — принимает клиентские соединения, деобфусцирует и перенаправляет на адрес destination. Этот режим пригодится на стороне сервера.
    • client — прозрачное проксирование: принимает данные, обфусцирует и отправляет серверу по адресу destination. То, что мы будем использовать на клиентской стороне.
    • socks — имитация socks-прокси.

    Разница между режимами client и socks в том, что в первом случае адрес удаленного хоста, к которому пытается подключиться целевое приложение, должен быть заменен на адрес opbfsproxy-клиента, тогда как во втором случае целевое приложение использует obfsproxy как SOCKS-прокси. Для наших целей подойдёт и client.

  • --dest destination — для сервера: задаёт пару адрес-порт, куда будут перенаправляться деобфусцированные соединения. Для клиента: задаёт адрес obfsproxy сервера.
  • --password BASE32PASS — задание ключа(pre-shared key) для метода scramblesuit. Ключ должен быть строкой длиной не менее 20 символов, закодированной в base32, и совпадать на клиенте и на сервере. Подходящий ключ можно сгенерировать так:
    python -c "import os,base64; print base64.b32encode(os.urandom(20))"
    

  • --password-file filepath — альтернативный метод задания ключа для метода scramblesuit, на случай если вы не хотите писать pre-shared key в открытом виде.
  • log_options включает в себя следующие ключи:
    • --log-file path — задает расположение журнала.
    • --log-min-severity level — События какого уровня (debug, info, warning, error) записывать.
    • --no-safe-logging — по умолчанию obfsproxy вырезает адреса из лога, но данный ключ позволяет изменить это поведение.
    • --no-log — отключает ведение журнала совсем (по умолчанию).

Сам VPN-сервер можно либо спрятать за obfsproxy полностью (заставив слушать 127.0.0.1), либо оставить его на внешнем сетевом интерфейсе на случай отказа obfsproxy. Я выбрал второй вариант как более надежный.
Таким образом, для запуска obfsproxy на серверной стороне достаточно выполнить что-то вроде:

obfsproxy --log-file /var/log/obfsproxy-openvpn.log --log-min-severity info scramblesuit --password BASE32LONGPASS --dest 1.2.3.4:1800 server 1.2.3.4:81

где 1.2.3.4 — внешний IP хоста, 1800 — порт, который слушает OpenVPN, 81 — порт, который будет слушать obfsproxy.
Серьезным недостатком является неумение obfsproxy запускаться в режиме демона, но это можно обойти.

Запуск на клиенте практически идентичен серверу:

obfsproxy scramblesuit --password BASE32LONGPASS --dest 1.2.3.4:81 {client|socks} 127.0.0.1:81

где 1.2.3.4:81 — адрес, который слушает obfsproxy-сервер, 127.0.0.1:81 — адрес, который слушает клиент.

Настройка OpenVPN

Важно: OpenVPN должен использовать протокол TCP.
Если мы используем режим client, то просто заменяем адрес удаленного сервера в конфигурационном файле openvpn на адрес локального obfsproxy:

#remote 1.2.3.4 1800 #заменяем старый адрес сервера 
remote 127.0.0.1 81 #вместо этого пытаемся подключиться к клиентской части obfsproxy

Режим socks

Для работы в режиме socks настраиваем OpenVPN немножко по-другому:

#remote 1.2.3.4 1800 #заменяем старый адрес сервера 
remote 1.2.3.4 81 #на адрес obfsproxy-сервера (важно! иначе работать не будет)
socks-proxy-retry
socks-proxy 127.0.0.1 81 #пытаемся задействовать socks proxy

Учитывая необходимость заменять адрес OpenVPN-сервера на адрес obfsproxy-сервера, я не вижу особой пользы от режима прокси — приложения, в которых адреса подключения зашиты намертво, так все равно не запроксируешь.

Если openvpn-трафик блокируется лишь иногда (например, только в рабочей сети), можно использовать следующий прием. В файле конфигурации OpenVPN запишем следующее:

<connection>
    remote 1.2.3.4 1800 #сначала пытаемся подключиться напрямую
</connection>
<connection>
    remote 127.0.0.1 1800 #если не удалось, подключаемся через obfsproxy
</connection>

OpenVPN будет пытаться задействовать каждую секцию <connection> поочередно, пока не произведет успешное подключение.

Что касается запуска obfsproxy, к сожалению, сам OpenVPN не поддерживает pre-connect скрипты (запуск команды перед попыткой подключения). Вы можете попытаться установить один из неофициальных патчей [8], запускать obfsproxy вручную, либо воспользоваться одним из следующих методов.

openvpn-gui для Windows

Если вы используете обертку openvpn-gui для подключения вручную (или автоматически с ключом --connect), то проще всего будет создать в папке config файл XXXXXX_pre.bat, где XXXXXX — имя файла конфигурации (без расширения .ovpn). Этот файл будет автоматически выполнен перед тем как openvpn-gui попытается подключиться. Содержимое файла будет выглядеть примерно так:

start "window title" /MIN "%USERPROFILE%Tor BrowserTorPluggableTransportsobfsproxy.exe" --log-min-severity info --data-dir "%TEMP%obfs-openvpn" scramblesuit --password-file obfsproxy.key --dest 1.2.3.4:1801 client 127.0.0.1:1800

  • window title — заголовок окна, необходим.
  • %USERPROFILE%DesktopTor BrowserTorPluggableTransportsobfsproxy.exe — путь к исполняемому файлу obfsproxy. По умолчанию Tor Browser ставится на рабочий стол, хотя это и не обязательно.
  • %TEMP%obfs-openvpn — путь для размещения файлов состояния obfsproxy.
  • obfsproxy.key — путь к файлу с ключом, если вы его используете.
  • 1.2.3.4:1801 — адрес, который слушает серверная часть obfsproxy.
  • 127.0.0.1:1800 — адрес, который будет слушать клиентская часть.

Использование команды start (без ключа /wait она работает как аналог оператора & в shell) необходимо, так как openvpn-gui ожидает завершения pre-up скрипта перед попыткой подключения. Недостатком этого метода является консольное окно, постоянно висящее в фоне. При желании его можно спрятать утилитой hidcon [9] или аналогичной.

obfsproxy как сервис

Если OpenVPN запускается как сервис, то имеет смысл организовать запуск obfsproxy таким же образом.
Создать сервис можно утилитой srvany [10] от MS или какой-либо альтернативной утилитой, вроде NSSM [11]. Вопрос запуска приложения как службы Windows выходит за рамки статьи, так что я просто укажу, что такой подход позволит задавать зависимости от и для других сервисов, тем самым гарантируя что obfsproxy будет доступен в момент запуска OpenVPN.

Этот подход можно совместить с предыдущим, используя bat-файл, запускаемый openvpn-gui, для запуска созданного сервиса командой net start.

Влияние на скорость

Проверка проводилась посредством старого доброго speedtest.net используя один и тот же сервер в Лондоне (OpenVPN-сервер хостится [3] в Латвии, клиент — в европейской части России) с клиентской машины под Windows 7.
С обфускацией: 105ms, 7Mbps/5Mbps в среднем.
Без обфускации: 105ms, 16Mbps/3.2Mbps(sic!) (скорость down гуляла от 14 до 18Mbps, скорость up была стабильна)
Без VPN: 55ms, 25Mbps/14Mbps (down от 23 до 26Mbps)

Честно говоря, медленный upload при отсутствии обфускации обескураживает — провайдер ничего не говорит о возможных урезаниях VPN трафика. Но в целом результаты вполне приемлемые. Остается надеяться, что мне не придется этим воспользоваться.

Автор: Vindicar

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/openvpn/85219

Ссылки в тексте:

[1] наметившимися: http://geektimes.ru/post/246380/

[2] тенденциями: http://geektimes.ru/post/245486/

[3] VPS: https://www.reg.ru/?rlink=reflink-717

[4] obfsproxy: https://www.torproject.org/projects/obfsproxy.html.en

[5] баг: https://community.openvpn.net/openvpn/ticket/377

[6] устанавливать: https://www.torproject.org/projects/obfsproxy-instructions.html.en

[7] Tor Browser: https://www.torproject.org/projects/torbrowser.html.en

[8] патчей: https://digitaldj.net/blog/2013/09/09/a-pre-connect-patch-for-openvpn/

[9] hidcon: https://code.google.com/p/andrew-grechkin/downloads/detail?name=hidcon-v1.1.4.7z

[10] srvany: http://support.microsoft.com/kb/137890

[11] NSSM: http://nssm.cc/

[12] Источник: http://habrahabr.ru/post/251569/