После прочтения статьи уважаемого ValdikSS решил изучить DPI своего провайдера и, при благоприятном развитии событий, найти пути его обхода. Ниже — результаты моих изысканий.

Итак, провайдер — ТТК Ульяновск (бывш. DARS Telecom), PPPoE-подключение с выделением внешнего IP на время сессии. Блокировка осуществляется заворачиванием заблокированных подсетей/хостов на свой DPI. DNS не подменяется.

% traceroute ya.ru
traceroute to ya.ru (87.250.250.242), 64 hops max, 40 byte packets
 1  bras.ulttk.ru (79.132.125.1)  0.899 ms  0.787 ms  0.817 ms
 2  ulk06.ulk26.transtelecom.net (217.150.41.98)  1.552 ms  1.536 ms  1.536 ms
 3  * * *
 4  Yandex-gw.transtelecom.net (188.43.3.213)  21.828 ms  15.955 ms  17.003 ms

% traceroute rutracker.org
traceroute to rutracker.org (195.82.146.214), 64 hops max, 40 byte packets
 1  bras.ulttk.ru (79.132.125.1)  1.778 ms  0.843 ms  0.751 ms
 2  ulk06.ulk26.transtelecom.net (217.150.41.98)  1.656 ms  1.698 ms  1.439 ms
 3  * * *
 4  188.43.0.18 (188.43.0.18)  16.589 ms
    BlackList-gw.transtelecom.net (188.43.30.130)  16.435 ms
    BL-gw.transtelecom.net (188.43.31.170)  16.377 ms
 5  Filter-gw.transtelecom.net (188.43.30.33)  17.006 ms  16.859 ms  17.080 ms

% traceroute kinozal.tv
traceroute: Warning: kinozal.tv has multiple addresses; using 104.24.107.53
traceroute to kinozal.tv (104.24.107.53), 64 hops max, 40 byte packets
 1  bras.ulttk.ru (79.132.125.1)  0.810 ms  0.809 ms  0.739 ms
 2  ulk06.ulk26.transtelecom.net (217.150.41.98)  1.653 ms  1.802 ms  1.736 ms
 3  * * *
 4  Filter-gw.transtelecom.net (188.43.30.34)  16.451 ms
    BL-gw.transtelecom.net (188.43.31.170)  16.405 ms  16.418 ms
 5  Filter-gw.transtelecom.net (188.43.30.33)  99.751 ms  78.541 ms  17.021 ms
 6  Cloudflare-msk-gw.transtelecom.net (188.43.3.65)  212.754 ms  107.803 ms  117.062 ms
 7  104.24.107.53 (104.24.107.53)  28.015 ms  17.216 ms  17.357 ms

Причем некоторые сайты просто и незатейливо заблокированы по IP (спасибо хоть RST присылают). Например, bt-анонсеры Рутрекера:

02:48:58.530078 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    ip109.176.ulttk.ru.22099 > bt.rutracker.org.http: Flags [S], cksum 0xd538 (correct), seq 3425095266, win 65535, options [mss 1452,nop,wscale 6,sackOK,TS val 1991139339 ecr 0], length 0
02:48:58.546482 IP (tos 0x0, ttl 61, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    bt.rutracker.org.http > ip109.176.ulttk.ru.22099: Flags [R.], cksum 0x13b9 (correct), seq 0, ack 3425095267, win 0, length 0

Для тех же сайтов, где нужно показать страничку блокировки работает пассивный DPI. Рассмотрим на примере Рутрекера:

02:27:28.605860 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    ip109.176.ulttk.ru.27338 > rutracker.org.http: Flags [S], cksum 0xeafc (correct), seq 3703194126, win 65535, options [mss 1452,nop,wscale 6,sackOK,TS val 1989849414 ecr 0], length 0
02:27:28.646812 IP (tos 0x0, ttl 58, id 0, offset 0, flags [DF], proto TCP (6), length 48)
    rutracker.org.http > ip109.176.ulttk.ru.27338: Flags [S.], cksum 0x81d2 (correct), seq 2683499593, ack 3703194127, win 14600, options [mss 1400,nop,wscale 8], length 0
02:27:28.646913 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    ip109.176.ulttk.ru.27338 > rutracker.org.http: Flags [.], cksum 0xe266 (correct), seq 1, ack 1, win 1028, length 0
02:27:28.647281 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 117)
    ip109.176.ulttk.ru.27338 > rutracker.org.http: Flags [P.], cksum 0xb1d5 (correct), seq 1:78, ack 1, win 1028, length 77: HTTP, length: 77
        GET / HTTP/1.1
        Host: rutracker.org
        User-Agent: curl/7.56.0
        Accept: */*
02:27:28.663665 IP (tos 0x0, ttl 61, id 0, offset 0, flags [DF], proto TCP (6), length 286)
    rutracker.org.http > ip109.176.ulttk.ru.27338: Flags [FP.], cksum 0xf88c (correct), seq 1:247, ack 78, win 0, length 246: HTTP, length: 246
        HTTP/1.1 301 Moved Permanently
02:27:28.663724 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    ip109.176.ulttk.ru.27338 > rutracker.org.http: Flags [.], cksum 0xe126 (correct), seq 78, ack 248, win 1024, length 0
02:27:28.664047 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    ip109.176.ulttk.ru.27338 > rutracker.org.http: Flags [F.], cksum 0xe121 (correct), seq 78, ack 248, win 1028, length 0
02:27:28.695429 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
    ip109.176.ulttk.ru.42348 > dib-filtr-gw.transtelecom.net.http: Flags [S], cksum 0x0556 (correct), seq 2835326510, win 65535, options [mss 1452,nop,wscale 6,sackOK,TS val 1989849504 ecr 0], length 0

Посмотрим на данный вывод подробнее. С момента 605860 до 646913 клиент осуществляет тройное рукопожатие с «настоящим» Рутрекером. В 647281 клиент посылает HTTP-запрос Рутрекеру длинной 77 байт, но вместо обычного ACK получает от «поддельного» Рутрекера FPA с HTTP-перенаправлением длинной 246 байт. Причем, заметьте, с корректным ACK 78, но левым, в рамках данного TCP-соединения, номером последовательности SEQ. Далее клиент закрывает соединение и переходит куда сказали. ACK и HTTP-ответ от Рутрекера так и не приходят.

В принципе, понятно зачем провайдеру потребовался этот странный TCP с флагами FPA: FIN для начала завершения соединения со стороны клиента, PUSH для проталкивания этого сегмента в TCP-очереди клиента, а корректный ACK чтоб всё выглядело красиво и этот «поддельный» TCP-сегмент не был отброшен TCP\IP-стеком клиента. Но этот FPA его же и погубил.

Итак, основная стратегия — отбрасывать TCP-сегменты с установленными флагами FPA, как-бы приходящие с адресов заблокированных ресурсов.

В качестве роутера в моей домашней сети трудится FreeBSD на старом Атоме, пакетным фильтром работает pf. Основной проблемой стало то, что pf — это statefull-фаервол, т.е. после первого же нашего разрешенного исходящего SYN в адрес Рутрекера в таблицу состояний фаервола заносится запись (state) и все последующие запросы и, что нам особенно важно, ответы в пределах данного TCP-соединения ни через какие правила фаервола более не проходят, они все разрешены.

Подобное поведение сильно увеличивает производительность брандмауэра и сокращает количество правил, но в нашем случае препятствует эффективной фильтрации. Поэтому все запросы/ответы к заблокированным ресурсам будем производить в stateless-режиме, т.е. без сохранения состояния. В pf правила получились такие:

WAN="ng0"
LAN="re0"
Blocked="{ заблок.IP1, заблок.IP2, заблок.IP3, и т.д. }"
...
# -UNBLOCK-
# for LAN hosts
pass in quick on $LAN proto tcp from $LAN:network to $Blocked no state
block drop out quick on $LAN proto tcp from $Blocked to $LAN:network flags FPA/FPA
pass out quick on $LAN proto tcp from $Blocked to $LAN:network no state
# -UNBLOCK-
# for me (router itself, for testing)
pass out quick on $WAN proto tcp from ($WAN) to $Blocked no state
block drop in quick on $WAN proto tcp from $Blocked to ($WAN) flags FPA/FPA
pass in quick on $WAN proto tcp from $Blocked to ($WAN) no state
...

Директива no state в разрешающих правилах запрещает сохранение состояния, первое правило в блоке UNBLOCK разрешает исходящие на заблокированный ресурс, второе правило блокирует «поддельные» входящие с установленными флагами FPA, третье — разрешает все остальные входящие. Директива quick во всех правилах прекращает просмотр фаерволом всех последующих правил фильтрации при совпадении с данным правилом. Результат (тройное рукопожатие пропущено):

01:48:10.221343 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 117)
    ip109.176.ulttk.ru.42714 > rutracker.org.http: Flags [P.], cksum 0xccb6 (correct), seq 1:78, ack 1, win 1028, length 77: HTTP, length: 77
        GET / HTTP/1.1
        Host: rutracker.org
        User-Agent: curl/7.56.0
        Accept: */*
01:48:10.237686 IP (tos 0x0, ttl 61, id 0, offset 0, flags [DF], proto TCP (6), length 286)
    rutracker.org.http > ip109.176.ulttk.ru.42714: Flags [FP.], cksum 0x136e (correct), seq 1:247, ack 78, win 0, length 246: HTTP, length: 246
        HTTP/1.1 301 Moved Permanently
01:48:10.563977 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 117)
    ip109.176.ulttk.ru.42714 > rutracker.org.http: Flags [P.], cksum 0xccb6 (correct), seq 1:78, ack 1, win 1028, length 77: HTTP, length: 77
        GET / HTTP/1.1
        Host: rutracker.org
        User-Agent: curl/7.56.0
        Accept: */*
01:48:10.604853 IP (tos 0x0, ttl 58, id 42669, offset 0, flags [DF], proto TCP (6), length 40)
    rutracker.org.http > ip109.176.ulttk.ru.42714: Flags [.], cksum 0x00c5 (correct), seq 1, ack 78, win 58, length 0
01:48:10.605043 IP (tos 0x0, ttl 58, id 42670, offset 0, flags [DF], proto TCP (6), length 422)
    rutracker.org.http > ip109.176.ulttk.ru.42714: Flags [P.], cksum 0x9bc5 (correct), seq 1:383, ack 78, win 58, length 382: HTTP, length: 382
        HTTP/1.1 301 Moved Permanently
        Server: nginx
        Date: Thu, 26 Oct 2017 21:48:10 GMT
        Content-Type: text/html
        Content-Length: 178
        Location: http://rutracker.org/forum/index.php
        Connection: keep-alive

221343 — HTTP-запрос к Рутрекеру
237686 — ответ от провайдерского DPI с флагами FPA (дамп с внешнего интерфейса роутера, поэтому он тут виден; клиент его не получает)
563977 — клиент ответа так и не дождался, повторяет запрос
604853 — настоящий Рутрекер присылает ACK
605043 — настоящий Рутрекер присылает HTTP-ответ

P.S. То же самое можно проделать с помощью любого современного фаервола, pf здесь только потому, что я его использую. Так же внимательный читатель мог заметить, что IP-спуфинг, осуществляемый DPI провайдера, элементарно детектируется по IP TTL (58 против 61). Но pf не умеет фильтровать все поля IP-пакетов, только основные. При использовании других фаерволов несовпадение IP TTL можно использовать как дополнительный признак «поддельного» пакета, наряду с TCP FPA.

That's All Folks!

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


  1. Pochemuk
    30.10.2017 14:40

    Все хорошо, но можно ли обойтись без упоминания в правилах адресов/ссылок на заблокированные ресурсы? Как изменится поведение фильтра без первого правила?


    1. taurusbusy Автор
      30.10.2017 18:29

      Спасибо. Поправил.


  1. alkoro
    30.10.2017 14:40

    Очевидно, это новое знание требует добавления в GoodbyeDPI.


  1. KluchnikovAleksey
    30.10.2017 15:02
    -8

    Ну молодец. Умный умный. А никто и не знал. Только вот узнал такое и сидеть надо тихо, чтобы не портить другим людям.


  1. EvilGenius18
    30.10.2017 15:20

    taurusbusy у вас в Ульяновске ТТК тоже не дает использовать Google DNS?

    В Питере вместо Google DNS, резолвит через те же:

    BL-gw.transtelecom.net
    Filter-gw.transtelecom.net


    1. dammer
      30.10.2017 16:38

      Это работает в ТТК, гугл не нужен, и бонусом резолвит зоны типа lib где много полезных зеркал.


    1. taurusbusy Автор
      30.10.2017 18:19

      У нас Google DNS так же заворачиваются на Filter-gw, но ответы не подменяются:

      # host rutracker.org
      rutracker.org has address 195.82.146.214
      rutracker.org has IPv6 address 2a02:4680:22::214
      rutracker.org mail is handled by 5 mail.rutracker.org.
      # host rutracker.org 8.8.8.8
      Using domain server:
      Name: 8.8.8.8
      Address: 8.8.8.8#53
      Aliases:
      rutracker.org has address 195.82.146.214
      rutracker.org has IPv6 address 2a02:4680:22::214
      rutracker.org mail is handled by 5 mail.rutracker.org.
      

      Первый запрос ходит не через провайдерский DNS, а через unbound с такой записью:
      forward-zone:
          name: "rutracker.org"
          forward-addr: 77.88.8.8
          forward-addr: 193.58.251.251


      1. EvilGenius18
        30.10.2017 18:25

        Хорошо, что пока еще не подменяют ничего.

        Спасибо за ответ


      1. rippy
        31.10.2017 10:31

        да все ТТК-улн подменяет
        [evk:prtech:~]>host rutracker.org
        rutracker.org has address 62.33.207.197
        rutracker.org has address 62.33.207.196
        rutracker.org has IPv6 address 2a00:1e48:99:6::2:2
        rutracker.org has IPv6 address 2a00:1e48:99:6::2:3
        [evk:prtech:~]>host rutracker.org 8.8.8.8
        Using domain server:
        Name: 8.8.8.8
        Address: 8.8.8.8#53
        Aliases:

        rutracker.org has address 195.82.146.214
        rutracker.org has IPv6 address 2a02:4680:22::214
        rutracker.org mail is handled by 5 mail.rutracker.org.


        1. taurusbusy Автор
          31.10.2017 10:48

          Совершенно верно, если выставлены провайдерские DNS, то картина, возможно, именно такая. Но ТТК не подменяет ответы от других публично доступных DNS-серверов, а уж разрулить запросы по форвардерам умеет любой кеширующий DNS, будь то unbound, bind или др. Разумеется, удобнее всего делать это на границе подконтрольной вам сети, например, на домашнем роутере.
          Для борьбы с подменой вообще всех DNS-ответов существует dnscrypt.


  1. bravo-ej
    30.10.2017 19:20

    Интересно, спасибо. Только это не DPI. Он бы таким не занимался. На самом деле схема эта очевидная и работает банально на случае, кто быстрее ответит. На маршрутизаторе оператора зеркалится трафик на небольшой сервачок и если система увидит запрос к ресурсу из списка — она вот такое вытворяет. Пакет от заблокированного ресурса вам наверное прилетит, только вы его уже не будете ждать.
    Что будет, когда списки вырастут ещё больше — сложно представить. Мы у себя внедряли такое (шибко подробностей не знаю, другой отдел), и налетали на штрафы от ркн за пропуски больше допустимого процента — банально система не успевала срабатывать в ответ на запросы ревизора от ркн. В итоге мы их перепробовали несколько и на чём то остановились по результатам тестов. Но принцип у них у всех один и тот же. Иначе это должна быть железка, через которую надо пропускать весь пиринг с операторами — а это совсем дорого уже только по железу, не говоря уже о софте и внедрение.

    Для подстраховки оператор может организовать для ревизора лаг на секундочку, что б наверняка )) но мы без этого обошлись естественно (иначе нафиг на такую систему блокировки тратить деньги).


    1. taurusbusy Автор
      31.10.2017 10:12

      Пакет от заблокированного ресурса вам наверное прилетит, только вы его уже не будете ждать.

      После провайдерского FPA ни ACK, ни HTTP-ответ от заблокированного ресурса уже не приходят. Специально tcpdump-ом искал их на внешнем интерфейсе роутера.
      На маршрутизаторе оператора зеркалится трафик на небольшой сервачок и если система увидит запрос к ресурсу из списка — она вот такое вытворяет.

      ЕМНИП трафик зеркалируется только для СОРМа, блокировки каждый провайдер реализует в меру своих технических возможностей. У ТТК возможностей хоть отбавляй, поэтому не удивлюсь, если они под свой DPI зарегистрировали отдельную AS и глобально сливают туда весь трафик к заблокированным ресурсам. Для них — это проще всего.


      1. bravo-ej
        31.10.2017 15:53

        Пообсуждали с коллегой. Стало понятно (мне), что принцип хоть и одинаков (или сильно похож), но методы и алгоритмы действия при этом у каждого продукта «фильтрации» свои. Тут мы правды не найдём, хотя бы потому, что никто из нас не знает, как оно у ТТК на самом деле (особенно в обособленном бизнесе в той локации). Да и тема не моя.


  1. madixi
    30.10.2017 21:59

    У меня такой же провайдер, на роутере openwrt, всего одно слово ipv6.


    1. rippy
      31.10.2017 10:31

      ipv6 не спасает от подмены DNS, я выше привел резолвинг через DNS ТТК


      1. Bonio
        31.10.2017 15:02

        В моем случае спасает. Все запросы на любые ipv4 dns сервера перехватываются провайдером и подменяются, а на ipv6 dns сервера, через туннель, не подменяются.
        Правда я все равно пользуюсь dnscrypt для скрытия dns трафика от провайдера. Трафик через туннель хоть пока и не перехватывается, но идет в открытом виде, что, теоретически, не мешает начать его анализировать какими-нибудь dpi.
        К тем провайдерам, которые предоставляют нативную поддержку ipv6 это, наверное, не относится.


  1. scruff
    31.10.2017 12:35

    Не много не понятен механизм подделки Рутрекера — как в принципе можно подделать его IP да так, чтобы FPA принял клиент как за оргинальный?


    1. taurusbusy Автор
      01.11.2017 16:10

      Принцип атаки, осуществляемой ТТК, довольно подробно описан здесь (способ с TCP-битом RST). Т.к. ТТК является провайдером доступа в Интернет, то для него осуществлять подобный вид MITM-атаки не представляет никакой технической или организационной сложности.