05 февраля 2020

«Я тебя по IP вычислю»: как хакеры рассекречивают звенья цепи Tor

Пишу, перевожу и иллюстрирую IT-статьи. На proglib написал 140 материалов. Увлекаюсь Python, вебом и Data Science. Открыт к диалогу – ссылки на соцсети и мессенджеры: https://matyushkin.github.io/links/ Если понравился стиль изложения, упорядоченный список публикаций — https://github.com/matyushkin/lessons
Рассказ о видах необычных атак на relay и guard узлы Tor и решениях, которые предложил автор блога The Hacker Factor.
«Я тебя по IP вычислю»: как хакеры рассекречивают звенья цепи Tor

Публикация является переводом поста Нила Кравеца в его блоге The Hacker Factor.

***

С момента запуска службы Tor, предоставляющей доступ к Internet Archive, я повидал широкий спектр атак на основе Tor и задокументировал многие из них в различных записях блога. Например:

  • Attacked Over Tor: 3 плохих бота, 1 агрессивный сканер и 1 атакующий бот.
  • Остановка атак Tor: способы подавления агрессивных DDoS-ботов.
  • Возвращение атак Tor: множество различных типов атак, с которыми мой сервер столкнулся через соединение Tor.
  • Новая атака Tor: обновленное решение для обновленного метода атаки.

Но в последний месяц я заметил новый тип атаки. Мне потребовалось некоторое время, чтобы понять, что пытается сделать атакующая сторона. Похоже, попытка состояла в том, чтобы составить частичный план цепочки серверов Tor, используемых моей скрытой службой.

Примечание: В этой публикации вы увидите два типа написания: Tor и tor. Заглавная буква используется для имени протокола, строчная – для имени программы.

Типичное обращение

Чтобы идентифицировать атаки, нужно сначала определить типичное обращение. К сожалению, даже в режиме полной отладки базовый исходный код tor-демона не предоставляет достаточно информации. Я изменил свою копию исходного кода, чтобы сделать ее более информативной. Например, мой tor-демон регистрирует каждую точку встречи (rendezvous point). По сути, я отредактировал src/or/rendservice.c и добавил инструкцию print в функцию rend_service_receive_introduction:

          tor_assert (launched-> build_state); 

   / ** Войти в точку встречи ** / 
    log_warn (LD_REND, "Rendezvous [% s]", safe_str_client (exte_info_describe (rp)));

   / * Заполнить состояние цепочки.  * / 
    

Прежде чем кто-либо спросит: нет, это не нарушает конфиденциальность. Rendezvous – это промежуточный узел, расположенный за пределами исходных каналов, установленных как браузером, так и службой. И да, журналы автоматически удаляются через неделю.

При типичном обращении я увижу, как демон tor подключается к точке Rendezvous, а через мгновение образуется множество HTTP-соединений с сервером. Например, это я подключаюсь к своему серверу с помощью Tor браузера:

        Jan 30 09:26:51 Tor[24247]: Rendezvous [$F5746F6257DFE87E3A90753C2A0439926C55552F~$F5746F6257DFE87E3A at 82.169.130.61]
[30/Jan/2020:09:26:54 -0700] "archivecrfip2lpi.onion" 200 10301 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
[30/Jan/2020:09:26:54 -0700] "archivecrfip2lpi.onion" 200 7312 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
[30/Jan/2020:09:26:54 -0700] "archivecrfip2lpi.onion" 200 6492 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
[30/Jan/2020:09:26:54 -0700] "archivecrfip2lpi.onion" 200 3827 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
    

IP-адрес от точки rendezvous всегда является узлом Tor, а шестнадцатеричные значения перед ним являются уникальным отпечатком узла Tor. Это публичная информация, вы можете посмотреть её на metrics.torproject.org. В этом случае узел Randezvous имеет псевдоним Hijnn, он существует по адресу 82.169.130.61, и когда я писал этот текст, он работал уже 8 дней 21 час 32 минуты и 47 секунд.

В Tor входной узел guard может быть и внесён в публичный список, и нет. Узлы guard, не включенные в список, обычно зарезервированы как bridges – они не включены в список для предотвращения цензурирования по IP. Однако узлы ретрансляции, встречи и выхода должны быть общедоступными, так как через них идет большой объем трафика Tor. Это часть анонимности Tor: ваш трафик неотличим от остального.

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

Типичное обращение и боты

Многие боты имеют поведение отличное от типичного. Например, могут одновременно выполнять только единственное однопоточное HTTP-соединение. Плохо написанные боты будут выполнять один HTTP-запрос на один узел rendezvous. Однако агрессивные боты могут быть обнаружены по тому факту, что они согласовывают несколько узлов встречи перед отправкой через них большого количества HTTP-запросов. Например:

        Jan 30 14:19:22 Tor[17199]: Rendezvous [$1B710612CB33CA26B7CF9964DFE79E60B45FAF60~$1B710612CB33CA26B7 at 35.228.99.44]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$BFC1305C8B37E5161C2E37135DF2D4E53CC38ACE~$BFC1305C8B37E5161C at 188.68.46.164]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$53134D9637D9FBE565FA1E3AF82B23CC964C56D6~$53134D9637D9FBE565 at 37.59.76.255]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$41EEC4CFA01E8982643F1AF3CD84315329D2B58E~$41EEC4CFA01E898264 at 95.211.147.99]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$2A621A40FF3081F612946FDFB8DC781BCE859A05~$2A621A40FF3081F612 at 116.203.88.24]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$861BCFDD148973985E7FE97C7455C9E4AC4E13BE~$861BCFDD148973985E at 148.251.22.104]
Jan 30 14:19:22 Tor[17199]: Rendezvous: Circuit closing
Jan 30 14:19:22 Tor[17199]: Rendezvous [$C0E6A667064385B9CB5A685CEB06B85EDDA6AA00~$C0E6A667064385B9CB at 77.123.155.45]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$204ECC4FF8F93862E82FA19C53B5BC98B1AF6046~$204ECC4FF8F93862E8 at 54.37.207.84]
Jan 30 14:19:22 Tor[17199]: Rendezvous: Circuit closing
Jan 30 14:19:22 Tor[17199]: Rendezvous [$964B4E8A75263A69769541F2764563DABDD995D2~$964B4E8A75263A6976 at 68.67.32.31]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$F1FE9BEF7DE30B2BA1547270495A6CE662C9C9E5~$F1FE9BEF7DE30B2BA1 at 83.162.159.206]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$E2CF09F998248C71139B24B2C92740AEDB1C6D2A~$E2CF09F998248C7113 at 107.180.239.164]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$75A931404453030821C547A4FAA9094A06C48C7A~$75A931404453030821 at 46.101.183.160]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$A0547D9D5383B4A6314CBAF3006EAECA197CD82F~$A0547D9D5383B4A631 at 148.251.137.3]
[30/Jan/2020:14:19:22 -0700] "web.archivecrfip2lpi.onion" 404 7782 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
Jan 30 14:19:22 Tor[17199]: Rendezvous [$CE1FD7659F2DFE92B883083C0C6C974616D17F3D~$CE1FD7659F2DFE92B8 at 185.15.72.62]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$24B1DF80768332990BA8F1230BA41D95D82D52BD~$24B1DF80768332990B at 81.7.10.86]
Jan 30 14:19:22 Tor[17199]: Rendezvous: Circuit closing
Jan 30 14:19:22 Tor[17199]: Rendezvous: Circuit closing
Jan 30 14:19:22 Tor[17199]: Rendezvous [$6940247E04C839D268543E7F62566A91E40567E3~$6940247E04C839D268 at 176.9.57.152]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$E95955CD7AB012DE770711878F147C784FC13D37~$E95955CD7AB012DE77 at 164.132.226.30]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$24F97F98C45E4754655BE66799049763DAEE99CE~$24F97F98C45E475465 at 136.243.4.139]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$B630BE802A803403F4BBEDF1C4B7BE7B31A89305~$B630BE802A803403F4 at 212.51.159.148]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$00D2269DBC1A39D137160789C7B614197DB30C70~$00D2269DBC1A39D137 at 51.15.97.42]
Jan 30 14:19:22 Tor[17199]: Rendezvous [$11C9529C9D0671545EAEF80DFE209AD977BCE908~$11C9529C9D0671545E at 95.91.4.56]
Jan 30 14:19:22 Tor[17199]: Rendezvous: Circuit closing
[30/Jan/2020:14:19:23 -0700] "web.archivecrfip2lpi.onion" 404 7782 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
[30/Jan/2020:14:19:23 -0700] "web.archivecrfip2lpi.onion" 404 7872 "" "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0"
Jan 30 14:19:23 Tor[17199]: message repeated 9 times: [ Rendezvous: Circuit closing]
Jan 30 14:19:23 Tor[17199]: Rendezvous: Circuit closing
    

Все эти точки встречи являются известными узлами Tor. Наблюдаемое поведение провоцируется агрессивным сканером, порождающим одновременного много процессов сканирования.

Сообщения Circuit closing означают, что мой сервер обнаружил сканер и заблокировал его перед первым GET-запросом. Мое обнаружение имеет ноль ложных срабатываний. То, как вы устанавливаете соединения через Tor, является строго определенным и профилируемым атрибутом. Вы не анонимны.

Вперёд наоборот

Еще в 2017 году я упомянул об одном странном злоумышленнике. Я не знаю точно, чего он хотел. Но так как это не обычный пользователь, я классифицирую его действия как атаку. Если он указывал адрес точки встречи, то адрес отображался в неправильном порядке байтов. Например, 95.216.53.157 является известным узлом Tor, но этот бот запрашивал rendezvous, используя обратный порядок: 157.53.216.95. Обратный адрес уже не является известным узлом Tor. Даже fingerprints сервера были неправильными. В результате запросы соединения не выполнялись, но это не мешало ему пытаться снова и снова.

Это продолжалось годами. Как ни странно, иногда соединение проходило успешно. Я подозреваю, что злоумышленник управлял некоторыми враждебными узлами. Если он видел обратный адрес или неправильный fingerprints, он исправлял их. Это можно было использовать в качестве флага для отслеживания объема трафика или идентификации последнего узла в цепочке Tor моего сервера.

Бот с частным адресом

В конце прошлого года бот-любитель обратных адресов был остановлен. Он был заменен ботом «с частным адресом». Вот несколько примеров:

        Jan 30 07:35:59 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:01 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:03 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:04 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:06 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:08 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:09 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:10 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]
Jan 30 07:36:11 Tor[24247]: Rendezvous [$6B4108C2ACE1A805173B756A138A50C8770DAD2F~$6B4108C2ACE1A80517 at 149.248.4.19]

Jan 30 09:35:11 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:20 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:21 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:21 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:22 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:23 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:23 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:24 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:25 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]
Jan 30 09:35:26 Tor[24247]: Rendezvous [$7285A9997A37F9BB39C8007FA975331DE84F48A1~$7285A9997A37F9BB39 at 139.180.198.17]

Jan 30 13:02:24 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:24 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:25 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:27 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:27 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:28 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:29 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:30 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:31 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
Jan 30 13:02:31 Tor[17199]: Rendezvous [$7555AE0CF28142B4BF82E3BDAF006338D72C1123~$7555AE0CF28142B4BF at 45.76.134.212]
    

Как правило, одновременно отправляются 8-10 запросов, повторяясь несколько раз в час. IP-адреса не случайны. Я посмотрел, что одни и те же IP-адреса поступают партиями. Согласно metrics.torproject.org, IP-адреса и fingerprints не являются известными узлами Tor. Они даже не отображаются в кэше известных дескрипторов моего демона. Однако эти IP-адреса работают под управлением Tor и имеют открытый порт OR (9001/tcp).

В отличие от бота-любителя обратных адресов, который предоставлял фиктивные адреса, все эти IP-адреса соответствуют известным облачным провайдерам. Обычно это Choopa LLC – облачный провайдер, который регулярно используется при враждебных атаках.

Насколько я могу судить, бот стреляет такими пакетами и ждёт откликов от узла Tor. Таким образом, он узнаёт, что мой onion сервис использует этот конкретный узел в relay узле Tor.

Цепочка узлов Tor

Если вы используете Tor Browser, то вы можете просмотреть свою схему Tor (путь через сеть Tor). Например:

«Я тебя по IP вычислю»: как хакеры рассекречивают звенья цепи Tor

Типичный путь между браузером и onion сервисом Tor состоит из 7 переходов: от моего браузера до моего guard (в данном примере расположенного в Великобритании) и через два relay узла (Франция и Германия). У сервиса onion также есть его guard и два relay, которые неизвестны браузеру Tor. На рисунке показано «Relay, Relay Relay», но самый нижний relay узел на деле соответствует guard сервиса. Итак, это две цепочки узлов Tor – одна от браузера, другая от службы – которые встречаются посередине.

Что же делает злоумышленник? Я думаю, что пытается наметить следующий неизвестный relay! И так как цепочка меняется каждые несколько минут, он постоянно опрашивает текущий последний relay, используемый моим onion сервисом.

Цепные эксплойты

Определение последнего узла в цепочке не говорит атакующему, где я нахожусь. Однако это предоставляет злоумышленнику полезную информацию. Что он делает? Пытается найти мой guard узел.

Некоторые узлы Tor являются частью зарегистрированных семейств. Обычно это группа узлов Tor, которые работают в одной организации. Например, niftyspinymouse 5.196.213.57 является частью большого семейства связанных узлов Tor. В момент написания публикации в этом семействе было 68 активных узлов. На следуюещем скриншоте показаны только некоторые из них.

«Я тебя по IP вычислю»: как хакеры рассекречивают звенья цепи Tor

Охранный узел Tor меняется редко, даже если остальная часть цепочки часто варьируется. Более того, демон tor никогда не создаст цепочку, используя два узла, которые являются частью одного и того же известного семейства. Поэтому если кто-то видит, что маршрут использует niftyspinymouse, то он сразу знает, что мой guard узел не является ни одним из этих 68 узлов Tor.

Итак, узел guard редко меняется, но два других узла меняются часто. Опрашивая последний узел моей цепочки, злоумышленник может создать большой список исключений. Если он сможет исключить всё остальное, он найдёт мой guard узел. Если не исключит всё, то хотя бы сможет свести задачу к небольшому числу возможных guard узлов.

Идентификация возможного сторожевого узла не выдаёт реального адреса моего сервера. Однако известен тип атаки, когда атакующий DDoS'ит защитный узлел. Это отрубает guard и временно переводит мой сервис в оффлайн, пока службой не будет найден новый guard. Но охранный узел выполняет свою задачу, и не выдаёт, где находится мой сервер.

Существует второй тип атаки. Атакующий может запустить один или несколько враждебных охранных узлов. Если он сможет сбить меня с толку достаточным количеством guard-узлов, мой тор-демон в конечном итоге выберет одного из этих охранников. Тогда злоумышленник сможет определить мой фактический сетевой адрес и напрямую атаковать мой сервер. Так и произошло со мной однажды.

Наконец, демон tor отслеживает плохие узлы. Если злоумышленник сможет заставить моего демона tor пометить достаточное количество узлов как плохие, атакующий сможет перевести мою службу в офлайн, потому как процесс tor не сможет подключиться ни к одному охранному узлу. И такое тоже случалось со мной раньше. Это был один из самых неприятных перерывов в работе моей onion службы.

Подавления атак

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

Первый вариант – использовать ExcludeNodes torrc для исключения целых стран (например, ExcludeNodes {br},{ru},{pl} ) вместе со "StrictNodes 1" . Это говорит моему демону tor, что он никогда не будет намеренно подключаться к узлам в некоторых странах. Пытаясь идентифицировать мой защитный узел, злоумышленник может исключать большую часть сети Tor. Но всегда есть как минимум несколько сотен возможных мест, где мог бы находиться мой guard – и это предполагает, что я не использую bridge. Измененный мной демон tor случайным образом исключает разные страны каждый раз, когда выбирает новый узел guard. Думаю, что проект Tor должен серьезно рассмотреть вопрос о том, чтобы сделать это параметром конфигурации для onion серверов.

Второй вариант – изменить IP-адрес сервера. Таким образом, даже если злоумышленники найдут ваш адрес, вы станете «движущейся» целью. С IPv4 вы можете застрять с фиксированным адресом, потому что доступно мало адресов. Однако если вы используете IPv6, то это относительно просто настроить. Я имею в виду, конечно, если злоумышленник каким-то образом станет моим guard, то он знает мой адрес IPv6 и может быстро сузить мою подсеть до диапазона /64 или /92. Но есть еще миллионы адресов для моего сервера. Каждый раз, когда я выбираю новый охранный узел, я могу выбрать новый адрес.

Замечание: Если бы только Tor имел лучшую поддержку IPv6. В настоящее время лишь 15% узлов Tor поддерживают IPv6, и вы не можете запустить узел Tor только для IPv6.

Третий вариант: каждый tor демон загружает список известных общедоступных узлов и сохраняет его локально во время работы. См. $HOME/.tor/cached-microdescs* . Точка встречи должна быть в этом списке, потому как у вас не должно быть частного узла rendezvous. Если бы демон tor проверял, что точка встречи известна, прежде чем пытался подключиться к ней, такой тип атаки полностью провалился бы.

Жаль, что ExcludeNodes не поддерживает ASN. В противном случае я бы предложил занести в черный список все серверы Choopa.

Заключение

Если вы запускаете какой-либо сервис в старом-добром Интернете, вы обязательно увидите слепое сканирование и обычные атаки. Эксплойты WordPress, инъекции SQL и сканирование на наличие последних уязвимостей являются обычным явлением. А на Tor? Я вижу больше атак и ботов с плохим поведением, чем обычных пользователей. И очень немногие атаки можно обобщить. Так что, с точки зрения исследователя безопасности, атаки на Tor – одни из самых креативных.

***

Если вы любите Tor, Библиотека программиста также рекомендует статью Луковое ПО: используем TOR для анонимного парсинга.

Больше полезной информации вы можете получить на нашем телеграм-канале «Библиотека хакера».

Источники

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ