Утро 26 ноября началось для меня с интересной новости — ребята из Perfect Privacy опубликовали информацию об уязвимости Port Fail, которая позволяет раскрывать IP-адрес клиентов VPN-сервисов с функцией проброса портов. Я немного понегодовал из-за того, что ее назвали уязвимостью, т.к. это никакая не уязвимость, а особенность маршрутизации: трафик до IP-адреса VPN-сервера всегда идет напрямую, в обход VPN. Вполне очевидная вещь, подумал я, о которой должен знать любой сетевой администратор. Заметка вменяемая и технически грамотная, придраться можно только к слову vulnerability (уязвимость). Но потом за дело взялись СМИ, и пошло-поехало…
Критическая уязвимость во всех протоколах VPN на всех операционных системах. У-у-у, как страшно!
В новости, опубликованной на Geektimes, изначально имевшей желтый заголовок, было сказано о награде в $5000 за найденную «уязвимость» от Private Internet Access — одного из крупнейших VPN-сервисов. «$5000 за типичную, совершенно очевидную любому сетевику вещь?» — подумал я — «Невероятно!», и высказал свое негодование по этому поводу в комментариях, попутно расписав еще одну, не менее очевидную, особенность маршрутизации, с которой сталкивался любой настраивавший работу двух и более интернет-провайдеров на одном компьютере: ответ на входящий запрос не обязательно уйдет через этого же провайдера и с этим же IP, чего запросившая сторона совсем не ожидает. Если мы представим, что вместо второго провайдера у нас VPN-соединение, то отправив запрос на IP-адрес нашего провайдера, при определенных условиях может получиться так, что ответ на наш запрос мы получим с IP VPN-сервера.
Как такое может происходить?
Когда вы подключаетесь к 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 в других, «менее развитых» странах, чтобы не попасться в сканеры этих злодеев, и компании от этого грустят.
Итак, как могут воспользоваться этой особенностью маршрутизации копирайтные тролли:
- Пользователь, которому провайдер выдает «белый» (маршрутизируемый) IP-адрес, подключается к VPN, запускает BitTorrent-клиент и скачивает некоторые файлы, оставаясь после скачивания на раздаче. BitTorrent-клиент прослушивает порт и открывает его, в случае необходимости, через UPnP.
- Компания-тролль собирает все IP-адреса на этой раздаче, в том числе и IP-адрес и порт VPN-сервера нашего пользователя.
- Компания-тролль массово отправляет UDP-пакеты BitTorrent-клиентам на все IP-адреса в интернете, на порты, собранные ранее. Можно уложиться в десятки минут при использовании 10-гигабитного канала.
- BitTorrent-клиент пользователя, получив входящий пакет на сетевой интерфейс провайдера, отправляет ответ через VPN-интерфейс, с IP VPN-сервера.
- Компания-тролль обнаруживает настоящий 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-провайдерам, ответ получил только от 3: Private Internet Access и Perfect Privacy выпустили обновленный клиент с возможностью блокировки входящих соединений, Astrill написал, что они не считают эту особенность существенной, и что она не имеет отношения к VPN. Технически, они правы, однако в их клиенте есть защита от других клиентских проблем — утечек IPv6, DNS и WebRTC, и почему не добавить еще одну, остается для меня загадкой.
Кстати, вышел OpenVPN 2.3.9 с многочисленными исправлениями Windows-ошибок и долгожданной опцией --block-outside-dns
, которая исправляет утечки DNS на Windows 8.1 и 10.
Так я и получил свои $5000 от Private Internet Access и $1000 сверху от Perfect Privacy за еще одну ерунду, и мне, честно говоря, за это даже несколько стыдно. Часть денег уйдет разработчикам OpenVPN и strongSwan.
Автор: ValdikSS