ValdikSS / blockcheck

Russian ISP blocking type checker NOTE: NOT WORKING CURRENTLY. ВНИМАНИЕ: НЕ РАБОТАЕТ НА ТЕКУЩИЙ МОМЕНТ
MIT License
1.37k stars 143 forks source link

SNI based DPI detection #81

Open Mike-O-0 opened 5 years ago

Mike-O-0 commented 5 years ago

Блокировка HTTPS трафика у многих провайдеров происходит по полю SNI extension:servername . Есть исследование https://hal.inria.fr/hal-01202712/document где показано что при определённых условиях HTTPS сервер отдаст контент клиенту без указания последним servername(это не будет работать для CDN где использется virtualhosts). Можно ли в секцию обхода HTTPS добавить такую проверку? Сейчас в консоли проверяю так:

 mike@DNS:~$ echo -e "GET / HTTP/1.1\r\nHost: graniru.org\r\n\r\n" | openssl s_client -quiet -connect 95.211.178.194:443 | head -n 13
Can't use SSL_get_servername
depth=0 C = RU, ST = Russia, L = Moscow, O = Grani.Ru, CN = grani.ru, emailAddress = info@grani.ru
verify error:num=18:self signed certificate
verify return:1
depth=0 C = RU, ST = Russia, L = Moscow, O = Grani.Ru, CN = grani.ru, emailAddress = info@grani.ru
verify return:1
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Tue, 30 Apr 2019 12:11:05 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Tue, 30 Apr 2019 12:11:05 GMT
Cache-Control: max-age=0

75
<!DOCTYPE HTML>
<html lang="ru" xmlns:fb="https://www.facebook.com/2008/fbml">
  <head>

Без указания servername всё работает.


mike@DNS:~$ echo -e "GET / HTTP/1.1\r\nHost: graniru.org\r\n\r\n" | openssl s_client -quiet -connect 95.211.178.194:443 -servername graniru.org | head -n 13
^C

Принудительно указав servername получаем пустоту.

ValdikSS commented 5 years ago

Увы, только малая часть DPI у провайдеров пропускает TLS-соединения к заблокированным IP-адресам без SNI. Однако, я знаю другое эффективное решение — добавление точки в конец домена, что многими DPI воспринимается, как другой домен. Работает у большинства провайдеров РФ, в Турции, Иране. К сожалению, способ с точкой не соответствует стандарту (в RFC 6066 написано, что домен в SNI не должен содержать точку в конце), из-за чего поддерживается не всеми TLS-стеками, а также имеет проблемы с HTTP/2.

Есть еще другой способ, менее эффективный, но кое-где срабатывает — случайное изменение регистра домена в SNI. (echo -e "GET / HTTP/1.0\r\nHost: rutracker.org\r\n\r\n"; sleep 3) | openssl s_client -host rutracker.org -port 443 -servername "RuTrAcKeR.org"

ValdikSS commented 5 years ago

@LukyanovM, см. https://github.com/ValdikSS/blockcheck/issues/84 Попробуйте, пожалуйста.

Mike-O-0 commented 5 years ago

Прогнал на Tele2 на даче. Результат обнадёживает:

     Пробуем ClientHello с большим padding, поддельным SNI в начале и правильным до padding на rutracker.org
[✓] Сайт открывается
     Пробуем ClientHello с большим padding, поддельным SNI в начале и правильным после padding на rutracker.org
[✓] Сайт открывается

Технологически для линукса это тяжело реализовать? Я хочу болвану pr попробовать сделать, у него уже там фундаментальный труд по DPI.

ValdikSS commented 5 years ago

Изменение TLS-пакета требует его перешфировки (терминацию SSL). Вряд ли bol-val это будет делать. ClientHello с большим padding, поддельным SNI в начале и правильным до/после padding работает только на некоторых веб-серверах, не на всех, так что этот подход сломает многие сайты.