Пользователь
192,0
рейтинг
20 декабря 2015 в 22:13

Разработка → Еще одна «критическая» «уязвимость» «VPN» и почему Port Fail — ерунда

Утро 26 ноября началось для меня с интересной новости — ребята из Perfect Privacy опубликовали информацию об уязвимости Port Fail, которая позволяет раскрывать IP-адрес клиентов VPN-сервисов с функцией проброса портов. Я немного понегодовал из-за того, что ее назвали уязвимостью, т.к. это никакая не уязвимость, а особенность маршрутизации: трафик до IP-адреса VPN-сервера всегда идет напрямую, в обход VPN. Вполне очевидная вещь, подумал я, о которой должен знать любой сетевой администратор. Заметка вменяемая и технически грамотная, придраться можно только к слову vulnerability (уязвимость). Но потом за дело взялись СМИ, и пошло-поехало…

image

Критическая уязвимость во всех протоколах VPN на всех операционных системах. У-у-у, как страшно!

В новости, опубликованной на Geektimes, изначально имевшей желтый заголовок, было сказано о награде в $5000 за найденную «уязвимость» от Private Internet Access — одного из крупнейших VPN-сервисов. «$5000 за типичную, совершенно очевидную любому сетевику вещь?» — подумал я — «Невероятно!», и высказал свое негодование по этому поводу в комментариях, попутно расписав еще одну, не менее очевидную, особенность маршрутизации, с которой сталкивался любой настраивавший работу двух и более интернет-провайдеров на одном компьютере: ответ на входящий запрос не обязательно уйдет через этого же провайдера и с этим же IP, чего запросившая сторона совсем не ожидает. Если мы представим, что вместо второго провайдера у нас VPN-соединение, то отправив запрос на IP-адрес нашего провайдера, при определенных условиях может получиться так, что ответ на наш запрос мы получим с IP VPN-сервера.

image

Как такое может происходить?

Когда вы подключаетесь к VPN, маршрут по умолчанию, который до этого был установлен через вашего провайдера, меняется на маршрут через VPN.
Приложения, которые слушают порт и принимают на него входящие соединения, в большинстве своем полагаются на операционную систему при формировании ответа на пришедший входящий пакет. Это отлично работает, когда у вас один сетевой интерфейс, но ситуация меняется с несколькими интерфейсами, в зависимости от ОС и протокола:

Windows:
  • OpenVPN (def1) — UDP уходит через VPN-интерфейс, TCP работает корректно
  • IPsec IKEv2 — UDP уходит через VPN-интерфейс, TCP отбрасывается

OS X:
  • OpenVPN (def1) — UDP уходит через VPN-интерфейс, TCP отбрасывается
  • IPsec IKEv2 — UDP уходит через VPN-интерфейс, TCP работает корректно

Linux:
  • OpenVPN (def1) — UDP и TCP уходят через VPN-интерфейс при rp_filter=0, отбрасываются при rp_filter=1

В Linux существует замечательная настройка Reverse Path Filtering (rp_filter), которая включена по умолчанию в большинстве современных дистрибутивов. Если фильтр включен, то программа, прослушивающая порт, не получит никаких входящих данных, если ОС уверена, что ответ будет направлен через другой интерфейс. Следует отметить, что в некоторых дистрибутивах (как минимум, в Debian) эта опция по умолчанию отключена, хоть и причины этого непонятны.
В Windows и OS X подобной функциональности, к сожалению, нет.

Чем это может быть чревато?

Как можно видеть, проблему представляют только входящие пакеты к приложениям, прослушивающим UDP-порт. Вряд ли на типичном компьютере пользователя таких приложений найдется много, но несколько, как правило, все же есть.

BitTorrent

Как вы можете знать, в некоторых странах, например, в США, Германии, Франции, Австрии, Канаде, Великобритании, существуют специальные организации, которые отслеживают участников интересующих их BitTorrent-раздач по просьбам правообладателей. Они соединяются с BitTorrent-трекерами и DHT-сетью и сохраняют все IP-адреса конкретной раздачи, чтобы потом отправить «письма счастья» — сообщения о том, что такой-то IP-адрес с таким-то портом раздавал такой-то файл в такое-то время, что это все незаконно, и что нужно-бы заплатить за это дело штраф. Жители этих стран используют VPN в других, «менее развитых» странах, чтобы не попасться в сканеры этих злодеев, и компании от этого грустят.

Итак, как могут воспользоваться этой особенностью маршрутизации компании, производящие мониторинг нарушений интеллектуальной собственности:
  1. Пользователь, которому провайдер выдает «белый» (маршрутизируемый) IP-адрес, подключается к VPN, запускает BitTorrent-клиент и скачивает некоторые файлы, оставаясь после скачивания на раздаче. BitTorrent-клиент прослушивает порт и открывает его, в случае необходимости, через UPnP.
  2. Компания, занимающиеся мониторингом, собирает все IP-адреса на этой раздаче, в том числе и IP-адрес и порт VPN-сервера нашего пользователя.
  3. Компания массово отправляет UDP-пакеты BitTorrent-клиентам на все IP-адреса в интернете, на порты, собранные ранее. Можно уложиться в десятки минут при использовании 10-гигабитного канала.
  4. BitTorrent-клиент пользователя, получив входящий пакет на сетевой интерфейс провайдера, отправляет ответ через VPN-интерфейс, с IP VPN-сервера.
  5. Компания обнаруживает настоящий IP клиента, раздающего интересующий их материал.

По моему мнению, эксплуатировать такой подход достаточно проблематично из-за того, что почти все BitTorrent-клиенты выбирают случайный порт при первом запуске, и отправить сообщения на все порты и все IP-адреса в интернете хоть и вполне возможно, но, как минимум, затруднительно делать постоянно. Однако, есть и клиенты, которые используют стандартные порты вроде 8999 или 6881.
Соединиться с таким клиентом не получится со стандартным сетевым стеком, однако можно модифицировать его таким образом, чтобы такие соединения устанавливались.

Skype

Используя эту технику, можно узнать настоящий IP интересующих вас пользователей Skype, если они используют VPN. Существует большое количество публичных Skype-резолверов, которые покажут вам IP и порт пользователя по Skype-логину. Далее, вам нужно прибегнуть к такой же технике, которую использовали бы правообладатели — разослать какие-нибудь данные на UDP-порт по всему интернету, и следить за ответами. Примечательно, что отсылать в Skype можно почти любой мусор! Воспользуемся замечательной программой nping из состава nmap:
# nping --udp -p 13318 --data-string 'hellothere!' -c 1 serv.valdikss.org.ru

Starting Nping 0.7.00 ( https://nmap.org/nping ) at 2015-12-20 19:54 MSK
SENT (0.0157s) UDP 195.154.127.59:53 > 92.42.31.8:13318 ttl=64 id=10802 iplen=39 
RCVD (0.0859s) UDP 185.61.149.121:4272 > 195.154.127.59:53 ttl=54 id=1534 iplen=32 
 
Max rtt: N/A | Min rtt: N/A | Avg rtt: N/A
Raw packets sent: 1 (39B) | Rcvd: 1 (46B) | Lost: 0 (0.00%)
Nping done: 1 IP address pinged in 1.01 seconds


Как защититься?

Хоть и я и не считаю эту особенность такой уж большой проблемой, мне все же интересно, как предотвратить утечки такого рода с технической точки зрения.
С Linux все предельно просто — для IPv4 достаточно установить опцию
net.ipv4.conf.*.rp_filter
в 1, если она еще не установлена. Мой интерфейс VPN называется tun0, а интерфейс с интернетом — wlp3s0, поэтому я делаю следующее:
# sysctl net.ipv4.conf.all.rp_filter=1
# sysctl net.ipv4.conf.default.rp_filter=1
# sysctl net.ipv4.conf.tun0.rp_filter=1
# sysctl net.ipv4.conf.wlp3s0.rp_filter=1

А для IPv6 необходимо добавить правило iptables:
# ip6tables -t raw -A PREROUTING -m rpfilter --invert -j DROP

В Windows существует мощная Windows Filtering Platform, с которой можно писать достаточно гибкие правила межсетевого экрана прямо в user-space, а если и этого не хватает, написать ядерный драйвер.
Как и в случае с утечками DNS в Windows 10, я постарался реализовать подобие Reverse Path Forwarding под Windows в виде плагина для OpenVPN. Он делает следующее:
  • Разрешает любые входящие IPv4 unicast UDP-пакеты с адресов 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 и подсетей активных сетевых адаптеров; любые входящие IPv6 unicast UDP-пакеты с fd00::/8, fe80::/10 и подсетей активных сетевых адаптеров.
  • Блокирует все новые unicast UDP-пакеты извне VPN-интерфейса.

Хоть это и не полноценный Reverse Path Forwarding, свою работу он делает довольно хорошо: ответы на UDP-запросы могут уйти в VPN-туннель только в том случае, если они пришли из диапазонов немаршрутизируемых адресов, но в таком случае они отбросятся на стороне VPN-сервера, т.к. они, собственно, немаршрутизируемые (работают только в пределах определенной локальной сети); программы, использующие UDP (например, BitTorrent Sync), не перестанут работать в внутри LAN, а соседи по провайдерской подсети все еще смогут с вами корректно связаться.
Скачать плагин можно здесь: github.com/ValdikSS/openvpn-block-incoming-udp-plugin

В OS X все несколько сложнее: PF не позволяет фильтровать только новые UDP-пакеты, поэтому приходится блокировать все входящие UDP, кроме локальных адресов, провайдерской подсети и самого VPN-сервера. Это плохо тем, что вы, например, не сможете использовать DNS провайдера, если захотите, т.к. ответы вам просто не будут доходить, необходимо будет вносить IP DNS-сервера в белый список.
В любом случае, сделать это можно приблизительно так:
echo 'pass in quick proto udp from 10.0.0.0/8 to any
pass in quick proto udp from 192.168.0.0/16 to any
pass in quick proto udp from 172.16.0.0/12 to any
pass in quick proto udp from 169.254.0.0/16 to any
pass in quick proto udp from 185.61.149.121/32 to any
block in quick on ! utun1 proto udp to any' |  sudo pfctl -Ef -
Где 185.61.149.121 — IP-адрес VPN-сервера, а utun1 — интерфейс VPN.

Послесловие

Если вы весь из себя злодей, и хотите попробовать проэксплуатировать эту особенность, вам поможет логирование пакетов в Linux средствами netfilter. Достаточно добавить следующее правило iptables, и все пакеты с Марса будут как на ладони:
iptables -I INPUT -m conntrack -p udp --sport 4455 --ctstate NEW -j LOG
Где 4455 — интересующий вас порт.

Сообщения об этой особенности я отправил 11 VPN-провайдерам, ответ получил только от 5: Private Internet Access, Perfect Privacy и Mullvad выпустили обновленный клиент с возможностью блокировки входящих соединений, Astrill написал, что они не считают эту особенность существенной, и что она не имеет отношения к VPN. Технически, они правы, однако в их клиенте есть защита от других клиентских проблем — утечек IPv6, DNS и WebRTC, и почему не добавить еще одну, остается для меня загадкой. Ребята из Cryptostorm подсказали ключ реестра Windows, который должен включать Reverse Path Forwarding, но он не работает, а TorGuard ничего не написали после ответа на некоторые вопросы с их стороны.

Кстати, вышел OpenVPN 2.3.9 с многочисленными исправлениями Windows-ошибок и долгожданной опцией --block-outside-dns, которая исправляет утечки DNS на Windows 8.1 и 10.

Так я и получил свои $5000 от Private Internet Access, $1000 сверху от Perfect Privacy и $1300 от Mullvad за еще одну ерунду, и мне, честно говоря, за это даже несколько неловко. Часть денег уйдет разработчикам OpenVPN и strongSwan.
Влад @ValdikSS
карма
620,0
рейтинг 192,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

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

  • +1
    Спасибо большое, очень грамотное замечание. Но всётаки не все юзеры скажем тогоже пингвинёнка понимают как работает маршрутизация, так что даже жёлтые новости будут им полезны.
  • +1
    iptables -P INPUT DROP
    iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    iptables -A INPUT -s <my-vpn-server-ip-address> -p udp -m udp --sport <vpn-server-port> -j ACCEPT
    iptables -A INPUT -i lo -j ACCEPT

    спасет отца русской демократии от утечек. Параноикам можно также закрыть все исходящие соединения, кроме отправки пакетов на VPN-сервер.
    • +3
      Но также, к сожалению, ломает и входящие соединения внутри локальной сети, например, что совсем не подходит для большинства пользователей.
      Так-то, в линуксе с этим успешно справляется firewalld. Классная штука, делит сетевые интерфейсы на зоны, как в Windows. Можно задать wi-fi-интерфейсу зону public, и по умолчанию все входящие соединения будут блокированы, а домашней сети назначить зону home. Причем зоны назначаются на каждое подключение через networkmanager, очень удобно.
  • 0
    Если:
    1. клиент за NAT-ом
    2. офис натится в ВПН
    то «уязвимость» не должна работать, верно?

    • 0
      1. Если у вышестоящего роутера UPnP, и провайдер выдает роутеру маршрутизируемый адрес, то сработает.
      2. Не сработает, вернее, не имеет смысла.
  • 0
    Кстати, вышел OpenVPN 2.3.9 с многочисленными исправлениями Windows-ошибок и долгожданной опцией --block-outside-dns, которая исправляет утечки DNS на Windows 8.1 и 10.

    Опцию можно просто в конфиг прописать? Точнее конфиг после этого останется кроссплатформенным, т.е. будет всё так же импортироваться в Android, молча работать на Windows младше 8.1 и в поведении Linux тоже ничего не изменится?
    • +3
      Нет, конфиг не останется кроссплатформенным — другие платформы будут сообщать о незнакомой им опции.
      Чтобы это работало так, как вы хотите, нужно либо посылать опцию с сервера (в этом случае клиенты игнорируют незнакомые опции), либо в клиентском конфиге использовать конструкцию с setenv opt:
      setenv opt block-outside-dns

      Либо с ignore-unknown-option:
      ignore-unknown-option block-outside-dns
      block-outside-dns

      Я бы использовал версию с setenv, т.к. она поддерживается старыми клиентами, в отличие от ignore-unknown-option.
      • 0
        Благодарю, тогда просто в конфиг сервера внесу, об этой возможности я даже не подумал.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.