Если у вашей компании имеются серверы, работающие за границей, и доступ для внутренних пользователей вы предоставляете посредством VPN-протоколов (достаточно типовая схема, особенно после Covid — 2019, когда удалённая работа стала особенно популярной), то настало время действовать на опережение. Конечно, применение административного ресурса, возможно, защитит ваши интересы от тотальных проблем в будущем, но лучше подстраховаться, чем в один прекрасный день получить 100500 сообщений от систем мониторинга о недоступности опекаемых клиентов. Статья демонстрирует, как скрыть от противодействия со стороны систем глубокого анализа трафика сервисы компании, доступ к бизнес-процессам которых обеспечивается посредством VPN, используя для этого туннели shadowsocks.

Текущий год сетевым инженерам и системным администраторам запомнится за майский и августовский перебои с сетями. Во втором случае были частично парализованы даже серверы, расположенные в отечественных дата-центрах (судя по всему, для персонала это тоже стало большой неожиданностью), и при этом не работал не только доступ посредством VPN. Получить информацию от технической поддержки, почему даже критически важный ssh-протокол отказывается отрабатывать до православного сервера, кроме отписок про нештатную ситуацию и мы уже работаем над этим, не вышло. В этом году на Хабре стали регулярно появляться статьи про частное применение протоколов shadowsocks, xray, dnstt и других для сохранения доступа к любимым сайтам в современных реалиях. Техническим специалистам уже стало абсолютно ясно, что случились первые звонки, и скоро весь этот DPI заработает по-настоящему. Новости пестрят ещё более серьёзными заявлениями о предстоящих блокировках. Ниже я покажу решение связанной, но другой задачи: применение туннеля shadowsocks для охранения работоспособности территориально распределённой локальной сети, построенной на базе OpenVPN. Если ваша локалка убегает далеко за пределы границ государства, то этот материал для вас.

В старые времена отечественному сетевому инженеру, работающему на предприятии, достаточно было строить локальные сети, которые со временем вышли за пределы офисов и расползлись между городами и странами. Наступило время VPN-протоколов и связанных с ними технических решений вроде pki. Очевидно, что в настоящее время мы вступили в период необходимости туннелирования распределённых локальных сетей. Сформулируем техническое задание. Существует корпоративная сеть, имеющая клиентов в зарубежном сегменте интернет. Подключение удалённых клиентов осуществляется по протоколу OpenVPN, порт сервера tcp/1200. Сеть должна сохранить работоспособность после воздействия на неё не контролируемого нами DPI.

В качестве эксперимента соберём практически нативный Linux-туннель между двумя серверами, работающими по обе стороны кордона, прямо поверх ssh-соединения. Без использования сторонних протоколов и программ:

# На одном из серверов сгенерируем пару RSA-ключей
ssh-keygen -t rsa -b 2048 -f ~/test
# Посмотрим содержимое открытого ключа
cat test.pub

ssh-rsa AAAAB3NzaC1yc…q4IVyz test@test_key

# На другом сервере сохраним его
echo 'ssh-rsa AAAAB3NzaC1yc…q4IVyz test@test_key' >> .ssh/authorized_keys
# Тестируем соединение
ssh -i ~/test test@test.ru
# Если всё нормально, запускаем туннель
ssh -i ~/test -D 3000  test@test.ru
# Проверяем состояние tcp сетевых соединений
netstat –tlnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      139625/ssh

Туннель запущен, теперь завернём в него трафик VPN. Для этого дополним конфигурацию OpenVPN-клиента приведённой ниже строкой и перезапустим службу:

socks-proxy 127.0.0.1 3000

Трафик OpenVPN будет вложен внутрь ssh-соединения. Обращаемся к VPN-серверу и наблюдаем работоспособность соединения:

ping 192.168.16.1
PING 192.168.16.1 (192.168.16.1) 56(84) bytes of data.
64 bytes from 192.168.16.1: icmp_seq=1 ttl=64 time=1.90 ms

Разорвать ssh-туннель обычным exit не выйдет, поэтому при тестировании можно просто прибивать его:

# Смотрим PID нужного нам процесса
netstat -tlnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      139625/ssh

# Прибиваем процесс
kill -9 139625

Можно убедиться, что никакие пинги до VPN-сервера больше не идут. Задача выполнена, но в прод такое выпускать не следует. Протокол ssh многофункциональный, вряд ли будет подвержен санкционному влиянию, так как глобально обеспечивает функционирование интернета. Однако это в первую очередь протокол удалённого управления, а из этого вытекают дополнительные эксплуатационные издержки. На текущий момент существуют уже проверенные временем туннельные протоколы, которые предназначены для обхода DPI. Тем более, с маскированием трафика они справляются гораздо лучше, так как разрабатывались изначально с этим требованием. Выбор пал на shadowsocks – открытый, надёжный, быстрый, обычно не детектируемый, простой в настройке и документированный. Устанавливаем необходимые пакеты на VPN-сервер, конфигурируем и запускаем службу:

apt install shadowsocks-libev
nano /etc/shadowsocks-libev/config.json

{
	"server": "0.0.0.0",
	"mode":"tcp_and_udp",
	"server_port":24,
	"password":" ahC....uzah",
	"timeout":300,
	"method":"chacha20-ietf-poly1305"
}

systemctl restart shadowsocks-libev
# Проверяем соединения на сервере
netstat –tlnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:24              0.0.0.0:*               LISTEN      14103/ss-server	

Размер ключа должен быть равен 32 символам, автоматически сгенерировать можно так:

apt install pwgen
pwgen 32 1

ahC....uzah

Сервер к работе готов, перемещаемся за кордон и настраиваем туннель на клиенте. Устанавливаем необходимые пакеты, выключаем серверную часть программы, конфигурируем и запускаем службу:

apt install shadowsocks-libev
systemctl stop shadowsocks-libev								
systemctl disable shadowsocks-libev		
nano /etc/shadowsocks-libev/test.ru.json

{
	"server": "ip адрес сервера",
	"mode":"tcp_and_udp",
	"server_port":24,
	"local_address": "127.0.0.1",
	"local_port":3000,
	"password":" ahC....uzah ",
	"timeout":300,
	"method":"chacha20-ietf-poly1305"
}

systemctl start shadowsocks-libev-local@test.ru.service
# Проверяем соединения на клиенте
netstat –tlnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      118341/ss-local

Туннель сконфигурирован и запущен. Выполним тест работоспособности прокси. При первой проверке нам должен вернуться IP-адрес нашего VPN-сервера, при второй – действительный адрес сервера:

curl --proxy socks5://127.0.0.1:3000 https://ifconfig.me
curl https://ifconfig.me

Теперь можно перезапустить клиента VPN и так же убедиться в его работоспособности:

systemctl restart openvpn
tail /var/log/openvpn/user196.log –F

После публикации статьи в комментариях была указано, что современным и рекомендуемым к использованию является протокол Shadowsocks-2022 (aead-cipher-2022) и его актуальная реализация. Следующий набор методов шифрования относятся к AEAD-2022: 2022-blake3-aes-128-gcm, 2022-blake3-aes-256-gcm, 2022-blake3-chacha20-poly1305, 2022-blake3-chacha8-poly1305. Его настройка принципиально не отличается от того, что представлено выше. Однако необходимого пакета нет в apt для Debian, поэтому ниже представляю полную инструкцию по настройке туннеля Shadowsocks-2022:
# Останавливаем туннель, созданный выше
systemctl stop shadowsocks-libev

apt install snapd
snap install core
snap install shadowsocks-rust

Посмотрим, какие службы были установлены:
snap services shadowsocks-rust

Service                           Startup   Current   Notes
shadowsocks-rust.sslocal-daemon   disabled  inactive  -
shadowsocks-rust.ssserver-daemon  disabled  inactive  -

На серверной части подготовим конфиг, в котором укажем метод шифрования из нужного набора, новый пароль и протестируем запуск:
# Генерируем пароль и кодируем в base64
# (именно в таком виде он будет в конфигурационном файле)
pwgen 31 1 | base64
c29v...hZQo=

nano /root/shadowsocks.json

{
	"server": "0.0.0.0",
	"mode":"tcp_and_udp",
	"server_port":24,
	"password":"c29v...hZQo=",
	"timeout":300,
	"method":"2022-blake3-aes-256-gcm"
}

# Проверяем запуск
/usr/bin/snap run shadowsocks-rust.ssserver-daemon -c /root/shadowsocks.json

Если ошибок не возникло, тогда запускаем службу работать на постоянку:
snap start --enable shadowsocks-rust.ssserver-daemon
# Передаём параметром подготовленный выше конфигурационный файл
nano /etc/systemd/system/snap.shadowsocks-rust.ssserver-daemon.service

[Unit]
Description=Service for snap application shadowsocks-rust.ssserver-daemon -c /root/shadowsocks.json
Requires=snap-shadowsocks\x2drust-563.mount
Wants=network.target
After=snap-shadowsocks\x2drust-563.mount network.target snapd.apparmor.service
X-Snappy=yes
[Service]
EnvironmentFile=-/etc/environment
ExecStart=/usr/bin/snap run shadowsocks-rust.ssserver-daemon
SyslogIdentifier=shadowsocks-rust.ssserver-daemon
Restart=on-failure
WorkingDirectory=/var/snap/shadowsocks-rust/563
TimeoutStopSec=30
Type=simple
[Install]
WantedBy=multi-user.target

# Стартуем
systemctl daemon-reload
systemctl restart snap.shadowsocks-rust.ssserver-daemon.service
systemctl status snap.shadowsocks-rust.ssserver-daemon.service

Проделываем аналогичные действия на стороне клиента (забугорного сервера):
# Останавливаем туннель, созданный выше
systemctl stop shadowsocks-libev-local@test.ru.service

apt install snapd
snap install core
snap install shadowsocks-rust

# Подготавливаем файл конфигураций
nano /root/shadowsocks.json

{
	"server": "ip адрес сервера",
	"mode":"tcp_and_udp",
	"server_port":24,
	"local_address":"127.0.0.1",
	"local_port":3000,
	"password":"c29v...hZQo=",
	"timeout":300,
	"method":"2022-blake3-aes-256-gcm"
}

# Проверка запуска клиента
/usr/bin/snap run shadowsocks-rust.sslocal-daemon -c /root/shadowsocks.json

# Настройка службы
snap start --enable shadowsocks-rust.sslocal-daemon
nano /etc/systemd/system/snap.shadowsocks-rust.sslocal-daemon.service

[Unit]
Description=Service for snap application shadowsocks-rust.sslocal-daemon
Requires=snap-shadowsocks\x2drust-563.mount
Wants=network.target
After=snap-shadowsocks\x2drust-563.mount network.target snapd.apparmor.service
X-Snappy=yes
[Service]
EnvironmentFile=-/etc/environment
ExecStart=/usr/bin/snap run shadowsocks-rust.sslocal-daemon -c /root/shadowsocks.json
SyslogIdentifier=shadowsocks-rust.sslocal-daemon
Restart=on-failure
WorkingDirectory=/var/snap/shadowsocks-rust/563
TimeoutStopSec=30
Type=simple
[Install]
WantedBy=multi-user.target

# Запуск службы
systemctl daemon-reload
systemctl restart snap.shadowsocks-rust.sslocal-daemon.service
systemctl status snap.shadowsocks-rust.sslocal-daemon.service
systemctl restart openvpn

Всё должно завестись также как и для shadowsocks-libev. Из академического интереса запишем и взглянем на передаваемый трафик:

apt install tcpdump
tcpdump -w test.pcap

# Используемые фильтры в Wireshark
ip.addr == адрес vpn сервера && tcp.port == 1200
ip.addr == адрес vpn сервера && tcp.port == 24

На 1200 tcp пакетов ожидаемо не обнаружено. Зато на 24 tcp видим не похожий ни на что поток данных, это и есть работа протокола shadowsocks:

Техническое задание выполнено. Эксплуатируемая корпоративная сеть сохранит работоспособность даже в условиях противодействия со стороны систем глубокого анализа трафика. Если нет, и прокаченный грамотными специалистами DPI будет в автоматическом режиме находить и блокировать ни на что не похожий трафик, вроде нашего shadowsocks, тогда мигрируем в другие скрытые туннельные протоколы, и игра в кошки-мышки продолжится. Так как у нас работает полноценный vpn, то можно придумывать разные надстройки, маркируя трафик и маршрутизируя пакеты самым необычным для клиентов образом, например, выпуская их в интернет через закордонный шлюз. Но это уже другая история.

Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх ????️

Комментарии (32)


  1. MiraclePtr
    05.09.2023 13:06
    +12

    shadowsocks-libev - это старая, уже давно активно не развиваемая версия SS, оригинальный протокол, ей используемый, содержит ряд уязвимостей, облегчающих его детектирование (replay-атаки и т.д.), и в наши дни не считается безопасным.

    Современным и рекомендуемым к использованию является протокол Shadowsocks-2022 (aead-cipher-2022 ), его актуальная реализация https://github.com/shadowsocks/shadowsocks-rust


    1. olegtsss Автор
      05.09.2023 13:06
      +6

      Опробую, сразу внесу правки в текст статьи, чтобы не зарывать актуальную информацию в комментарии. Спасибо.


  1. werdender
    05.09.2023 13:06
    +1

    Официальный виндовый клиент OpenVPN Connect не поддерживает опцию socks-proxy. Желающим обфусцировать openvpn под виндой можно использовать community edition клиента.


    1. olegtsss Автор
      05.09.2023 13:06

      Сервера, к которым организуется доступ, работают на Linux, на Windows встречаются только клиенты.


      1. werdender
        05.09.2023 13:06
        +2

        Так я же и пишу, что официальный клиент на Windows не поддерживает опцию socks-proxy.


        1. olegtsss Автор
          05.09.2023 13:06

          Туннель строится между серверами на Linux. Клиенты ничего не знают про туннель. Они подключаются к ресурсу, не ведая, как все проложено.


          1. skymal4ik
            05.09.2023 13:06
            +1

            Это называется site-to-site vpn. Можно использовать этот термин, чтобы не было путаницы :)


            1. olegtsss Автор
              05.09.2023 13:06

              Не обязательно. Посмотрите на картинку, которая идет главной к статье. Там изображена топология звезда. Куча серверов, один из которых находится за границей. Вот его соединение и туннелируется. Клиенты при этом подсоединяются к vpn серверу как полноценные пиры. Это не site-to-site. Но для site-to-site все описанное тоже работает.


    1. HomeMan
      05.09.2023 13:06

      У него нет внешних ovpn клиентов.

      У него есть локальная сеть в условной Москве, и вторая локальная сеть в условном Дублине.

      Есть задача связать их в единую сеть при помощи ovpn, избежав ковровых бомбардировок.

      Я понял это так.


      1. olegtsss Автор
        05.09.2023 13:06

        Примерно так. Чтобы иностранный сегмент не попал в простой на пару дней разбора полетов. Простоя в сервисе вообще не должно быть. Нужно всегда стараться минимизировать риски. Клиенты для windows - это не про тему материала.


  1. LRC
    05.09.2023 13:06

    Коллеги, а почему бы не использовать технологию port forwarding внутри ssh соединения, а сам openvpn запустить с data-ciphers none ?


    1. olegtsss Автор
      05.09.2023 13:06
      +1

      Так можно. Нужно нарастить схему обвязками, которые будут восстанавливать туннель при падении. И нужно понимать, что ssh - это протокол управления, ему не нужна высокая скорость, отсюда можно словить сюрпризы, вроде max 128 кбит\с в провайдерском Qos.

      Да, речь идет не о полном туннелировании вообще всей VPN сети, а только закордонных серверов. Соответственно настройки шифрования везде будут и будут одинаковые.


      1. LRC
        05.09.2023 13:06

        А как же бэкапы по scp ?
        Лично для себя нагородил огород
        openvpn client -> ssh port forwarding -> socks5 (dante) -> udp openvpn server
        когда мтс начал баловаться с блокировками чистого openvpn причем на офисной выделенке 100мбит
        померил спидтестом дало скорость 105мбит (я думаю сжатие добавило) остался доволен

        Да на айфон такое не запилишь, поставил xray сервер, а на мобилки V2BOX


        1. olegtsss Автор
          05.09.2023 13:06

          Scp для backup - это скорее решение на горячую руку. Если отвалится соединение дольше положенного таймаута - ваше копирование оборвется (файл будет битый). Тут лучше использовать что-то вроде rsync, более адаптированного инструмента для этого (который ssh умеет, разумеется).


      1. shmutz
        05.09.2023 13:06
        -3

        >ssh - это протокол управления, ему не нужна высокая скорость, отсюда можно словить сюрпризы, вроде max 128 кбит\с в провайдерском Qos.

        ну и буллщит. сколько по миру гоняется трафика rsync-ом или scp первый раз слышу, чтобы где-то его принудительно лимитили (что за фраза вообще про QOS, QOS обычно наоборот - когда приоритет бампают )


        1. olegtsss Автор
          05.09.2023 13:06
          +3

          Провайдерский Qos приоритизирует трафик. Он может быть настроен как угодно. Ограничение по скорости для выделенного типа трафика - это часть Qos. И шейпинг для managment packets - это реальность. А когда по этой нарезанной полосе полезут большие объемы трафика - этого следует ожидать следующим шагом.


  1. legos
    05.09.2023 13:06

    Интересно было бы почитать, как сделать аналогичное с wireguard-тоннелями.


    1. olegtsss Автор
      05.09.2023 13:06

      Вот здесь практики нет. В wireguard не создаются ведь интерфейсы?


    1. TheChief5055
      05.09.2023 13:06
      +1

      А зачем? Заверните WG в udp2raw и будет вам счастье.


    1. uneasy
      05.09.2023 13:06
      +1

      Все абсолютно точно так же. Поднимаете shadowsocks туннель и в настройках wireguard на обоих сторонах адрес пира меняете на 127.0.0.1:PORT


  1. Tzimie
    05.09.2023 13:06

    О, статья на удаление по последнему приказу минцифры)


    1. olegtsss Автор
      05.09.2023 13:06

      Что там по приказу, не развернете мысль подробнее?


      1. Tzimie
        05.09.2023 13:06

        https://habr.com/ru/news/758638/


        1. olegtsss Автор
          05.09.2023 13:06
          +2

          Ну это да, я на нее в статье ссылаюсь тоже. Пока только чтения, поэтому в вашем комментарии более уместно слово "будущему" вместо "последнему".


    1. RighteousHippie
      05.09.2023 13:06
      +1

      Хабру будет проще не соблюдать этот маразматичный бред. Потому что Хабр без годных статей по сетям и VPN - это будет уже не тот Хабр. Большинство читателей тут айти сообщество, даже если Хабр заблокируют, они всё равно найдут способ открыть и почитать.


      1. V-King
        05.09.2023 13:06

        Вспоминается, как заблочили рутрэкер, а на следующий день тысячи пользователей сидели на этом рутрэкере и обсуждали, как им заблокировали ресурс и на каком месте они вращали блокировки роскомнадзора :)


        1. Tzimie
          05.09.2023 13:06
          +1

          Как я понимаю, хабр получает деньги от рекламы от российских фирм, и в этом проблема


  1. Sad_Bro
    05.09.2023 13:06

    сохранил в pdf, спасибо


  1. Opaspap
    05.09.2023 13:06

    Кстати, snapd не очень хорошо (мягко говоря) работает в Docker, что делает сложным апгрейд протокола по этой инструкции.


    1. olegtsss Автор
      05.09.2023 13:06

      Соберите из исходников)


    1. uneasy
      05.09.2023 13:06

      Да нужный бинарник под свою архитектуру просто скачайте, и все:

      https://github.com/shadowsocks/shadowsocks-rust/releases


      1. olegtsss Автор
        05.09.2023 13:06

        Ещё проще! С unix based приятно иметь дело.