Тестируем функционал из-под разных IP

Привет всем!

Сегодня я хочу поделится одной из возможностью тестирования функционала веб приложения из под разных IP адресов. Так как в топике много букв (и даже картинки есть!), решила я сделать содержание с навигацией.

Содержание

  1. Предисловие
  2. Формулировка задачи
  3. Поиски и фрагменты решений
  4. От теории к практики
  5. Техническая комплектация решения
  6. Настройка окружения для работы с приложением
  7. Запуск приложения
  8. Литература

Предисловие

Несколько недель назад ко мне в скайп постучался один таинственный незнакомец, и спросил меня совета, каким способом можно проверить со стороны пользовательского интерфейса то, что пользователь после 3-х попыток ввода неправильного пароля был заблокирован по IP на 5 минут. До этого я не встречала подобных задач, и мне показалось интересным в этом немного разобраться. Результатом своей работы я и хочу поделиться.

Формулировка задачи

Тест кейс по его высказываниям я набросала следующий

Название: Блокировка входа в систему по IP после неверно введенных данных

  1. Открываем в браузере страницу входа в систему
  2. Вводим логин
  3. Вводим неверный пароль
  4. Нажимаем кнопку входа
  5. Проверяем, что на странице отображается ошибка о неверно введенном логине/пароле
  6. Повторяем действия со второго по пятый шаг еще 2 раза
  7. Проверяем, что на странице отображается ошибка о превышении неудачных попыток входа в систему
  8. Меняем IP адрес
  9. Открываем в браузере страницу входа в систему
  10. Вводим логин
  11. Вводим верный пароль
  12. Нажимаем кнопку входа
  13. Проверяем, что мы успешно вошли в систему

В распоряжении у меня небыло пользовательского интерфейса, единственно, что я знала, что форма аутентификации в приложении стандартная: канал шифрованный на базе HTTPS, поле ввода логина, поле ввода пароля и собственно кнопочка войти.

Поиски и фрагменты решений

После определения задачи и неуспешного поиска готовых решений мне стало ясно, что для взаимодействия с интерфейсом можно взять Selenium Webdriver (который мне больше знаком, чем другие подобные решения), который, кроме всего прочего, может помочь закрыть вопросы с возможным изменением DOM модели после загрузки странички или в результате взаимодействия с UI (посредством JavaScript’а например).

В результате поиска средств по смене IP для тестирования веб приложения я остановилась на решении под названием TOR. По сути этот инструмент решает вопросы сохранение анонимности пользователей в сети за счет того, что запрос от клиента к серверу проходит через сеть проксирующих узлов в результате оставляя наш реальный IP невидимым для конечного сервера. Для более наглядного восприятия я постаралась это изобразить на рисунке ниже:

В теории, каждый новый запрос может пойти через другие мостовые узлы (relay), но на практике я этого так и не увидела. Проверяла я таким образом: выполняла запрос за определением своего внешнего IP адреса к разным веб ресурсам, и все они показывали мне один и тот же TOR’овский IP адрес, полученный в начале. Может быть переключение между мостовыми узлами (relay) срабатывает в аварийном случае, например, когда мостовой узел (relay) не отвечает, например из рисунка выше, если б узел в Германии упал, и Украина пересоединилась с США, как я показала на рисунке ниже:

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

От теории к практики

Реализовывать решение по тест кейсу я не стала, так как думаю, что многие знакомы с API Selenium Webdriver’а, а если нет, то существует много классных статей на эту тему, что не составит большого труда найти то, что вам будет по душе. Из задачи таинственного незнакомца, описанной в начале топика, я взяла лишь интересный для себя кусочек (так как мой ответ незнаю на решение его проблемы, его устроил быстрей, чем я даже ожидала ...). Этот сладкий кусочек относится к автоматизации взаимодействия с браузером от имени другого хоста (компьютера). В результате я написала приложение с консольным интерфейсом. Все, что приложение умеет делать, это посещать разные источники по HTTP/HTTPS, переданные в него в качестве аргумента. Если будет желание к приложению приделать хвост (образно), то исходники есть в открытом доступе. Выкачать исходники приложения можно с помощью команды:

git clone git@github.com:irinkav/anonymous-lover.git
. Финальную версию своего решения я изобразила следующим образом:

Техническая комплектация решения

Написала приложение на следующих технологиях:

  • Apache Maven (maven.apache.org) — для придания формы приложению (помогает в сборке, управлению зависимостями ...)
  • Selenium Webdriver (docs.seleniumhq.org/projects/webdriver) — для взаимодействия с веб страничками при помощью реального браузера
  • Jsoup (jsoup.org) — наследие, которое осталось в коде, и довольно неплохо себя там чувствует. Использовала его для выполнения запросов за контентом для быстрого получения информации о своем внешнем IP. Это решение гораздо легче Selenium Webdriver’а из-за того, что никаких браузеров не нужно подымать, а всего лишь строить запрос (GET/POST...) к веб серверу за контентом, и работать с DOM моделью контента при помощи удобного API на базе CSS selector’ов...
  • commons-exec (commons.apache.org/proper/commons-exec) — для запуска внешних программ. Я запускаю консольный TOR Socks прокси сервер с помощью этой библиотеки. Почему выбрала ее? Потому что она умеет порождать дочерний процесс от основного (процесса приложения) и управлять его жизненным циклом. Например, по завершению основного процесса тушатся все его подпроцессы порожденные им (с помощью ShutdownHookProcessDestroyer хука). Это нужно мне для того, чтоб по каждому новому запуску приложения стартовал TOR Socks прокси сервер как дочерний процесс, цеплял IP, и я его могла использовать для серфинга просторов интернета. О консольном TOR Socks прокси сервере поговорю немного и ниже в статье
  • commons-cli (commons.apache.org/proper/commons-cli) — для упрощения работы с приходящими аргументами из командной строки
  • консольный TOR Socks прокси сервер (www.torproject.org/index.html.en) — собственно для проксирования траффика между браузером и веб сервером. Использую Torproject реализацию TOR клиента.

Свое приложение проверяла на двух платформах: Linux и Windows и, конечно же, у меня все работало ;-)

Настройка окружения для работы с приложением

Для настройки окружение на работу через TOR сеть с помощью моей программки нужно:

  1. Скачать и установить Tor Browser Bundle (www.torproject.org/...​oad/download-easy.html.en). Он подается в разном виде, то есть у него сборки есть под разные платформы Windows/Mac/Linux.
  2. Скачать и установить Java SE 7+ (www.oracle.com/...​k7-downloads-1880260.html). Я проверяла приложение на 7 версии, поэтому за младшие версии сказать ничего не могу, собственно, как и за старшие
  3. Скачать и установить Apache Maven 3+ (maven.apache.org/download.cgi)

Запуск приложения

Для того, чтоб запустить программу нам нужно найти место, куда мы установили Tor Browser Bundle, и скопировать полные пути (желательно) к исполняемому файлу Tor\tor.exe (Tor/tor в случае с Linux, и, подозреваю, на Mac’е также...) и к директории Data. Они нам пригодятся на следующем шаге.

  • tor.exe — собственно консольный TOR Socks прокси сервер
  • Data — директория, где TOR Socks прокси сервер хранит свои конфигурации

Итак,

  1. Заходим в директории с программой
  2. Запускаем командную строку (консоль, терминал, cmd...)
  3. Выполняем в директории команду на сборку приложения: mvn clean install
  4. Из target/anonymous-lover-1.0-dist.zip копируем архив куда душе угодно (почему так я назвала приложение, напишу в конце статьи, дабы суть чище держать)
  5. Распаковываем архив anonymous-lover-1.0-dist.zip
  6. Заходим в распакованных архив
  7. Выполняем из командной строки (в моем примере пусть будет такая команда):

    java -jar anonymous-lover-1.0.jar --url 'https://dou.ua/forums/topic/9914/' --use-proxy --check-ip --tor-proxy-path 'c:\_tools\torBrowser\Tor\tor.exe' --tor-proxy-data-directory-path 'C:\_tools\torBrowser\Data'

    , где
    • anonymous-lover-1.0.jar — исполняемый Java архив
    • —url — страничка, которую мы хотим посетить. Результат странички сохраняется в директорию output корневой директории программы
    • —use-proxy — сделать посещение безопасным (в теории для этого был разработан TOR), то есть использовать режим проксирования траффика с помощью TOR сети
    • —check-ip — проверить IP и записать его в файл для потомков (шутка). Файл ложится в директорию output корневой директории программы. Если не хотите проверять внешний IP, то просто опускайте этот аргумент при общении с приложением
    • —tor-proxy-path — путь к файлу запуска TOR Socks прокси сервера
    • —tor-proxy-data-directory-path — путь к файлу конфигурации TOR Socks прокси сервера

В команде подразумевалось, что браузер Firefox был установлен в известное для Selenium Webdriver’а место. Однако если это не так, то всегда можно воспользоваться еще одним аргументом: —firefox-binary-path — указывает на путь к файлу запуска Firefox браузера. Например, значением этого аргумента может быть: c:\_tools\firefox\firefox.exe.

Также нужно иметь ввиду, что по умолчанию TOR Socks прокси сервер открывает и слушает Socks порт под номером 9150, но это можно изменить правкой в файл конфигурации в Data/Tor/torrc-defaults в строку с SocksPort 9150. После изменения может понадобится дать моему приложению понять, на каком порте крутится (слушает) прокси. Сделать это можно с помощью аргумента —proxy-port — порт TOR Socks прокси сервера (SocksPort параметр из Data/Tor/torrc-defaults).

Другую полезную информацию по TOR Socks прокси серверу можно черпнуть по ссылке: www.torproject.org/docs/tor-manual.html.en.

PS: Приложение назвала anonymous-lover, так как дома скучно что-то писать без изюминки. А тут, вроде как, и из названия понятно, чем приложение является для страничек.

Вообщем-то на этом и окончилась моя игра с TOR’ом.

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

Спасибо за внимание.

Литература

За время решения проблемы пользовалась следующими источниками:

👍НравитсяПонравилось0
В избранноеВ избранном0
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

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

Спасибо, @reality_hacker, согласна. Я думаю, что это самый простой способ смены IP для тестирования приложения в локальной сети из всех предложенных ниже.

SSH (linux) / Putty (windows)

Спасибо, Андрей, но хочу уточнить, тайна Вашего высказывания раскрывается по линку: straightedgelinux.com/...owto/socks.html?

Прям вспомнил как писал дипломы. Вроде бы как все красиво картинки, заглавия, содержание даже есть; а как начинаешь читать никакой последовательности.
Я тоже не понимаю почему все так мудрено как с реализацией так и с ее описанием.
Задача(насколько я понял): Проверить действительно ли после 3 неверный попыток аутентификации, четвертая попытка будет блокироваться в течении 10 минут. А также то что аутентификация с иного ip доступна.
1 часть реализации: Отправка запроса
1.1 Определить url, key params, request method.
2.2 Сделать запрос используя информацию из п.1.1
2. часть: смена ip
VPN (еще есть люди которые не держат свой сервак с vpn для выхода не из хацапетовки?)
Чужой proxy сотни их (можно и свой если есть время для настройки), и другие сервисы по смене ip.
Если сеть внутренняя, вообще хватаем любой доступный ip. В чем проблема повесить на один интерфейс сколько угодно ip-шников?
Если уж решили использовать tor. Читаем документацию внимательно:
1. ExitNodes
A list of preferred nodes to use for the last hop in circuits, when possible.
2. MaxCircuitDirtiness (стандартно 10 минут, мы можем наедятся на один и тот же внешний ip так как круг должен не меняется)
3. TrackHostExits (пытается удержать для определенного хоста внешний ip время указанное в TrackHostExitsExpire стандартно 1800 секунд, то есть полчаса)

Задача(насколько я понял): Проверить действительно ли после 3 неверный попыток аутентификации, четвертая попытка будет блокироваться в течении 10 минут. А также то что аутентификация с иного ip доступна.
1 часть реализации: Отправка запроса
1.1 Определить url, key params, request method.
2.2 Сделать запрос используя информацию из п.1.1
2. часть: смена ip
VPN (еще есть люди которые не держат свой сервак с vpn для выхода не из хацапетовки?)

Вариант, согласна, спасибо

Чужой proxy сотни их (можно и свой если есть время для настройки), и другие сервисы по смене ip.

Ну раз Вы много знайте (сами дипломы, как никак, писали не последовательно. Это из Вашей первой реплики выплывает...), то наверняка читали и такой документ, как www.w3.org/.../ct-guidelines, которому должны следовать все HTTP proxies, а именно раздел 4.1.6 Additional HTTP Header Fields, где написано, что proxy должны добавлять в заголовки HTTP запроса информацию об IP адресе инициатора запроса. Поэтому сказать сотни — ровным счетом ничего не сказать в этом конкретном случае. Либо уж, если начали говорить об этом, то приведите пожалуйста примеры хоть одного proxy и другого сервиса по смене IP для решения проблемы, описанной в топике. Будет хоть подкреплено фактами...

Если сеть внутренняя, вообще хватаем любой доступный ip. В чем проблема повесить на один интерфейс сколько угодно ip-шников?

Вариант, согласна, спасибо

Если уж решили использовать tor. Читаем документацию внимательно:
1. ExitNodes
A list of preferred nodes to use for the last hop in circuits, when possible.
2. MaxCircuitDirtiness (стандартно 10 минут, мы можем наедятся на один и тот же внешний ip так как круг должен не меняется)
3. TrackHostExits (пытается удержать для определенного хоста внешний ip время указанное в TrackHostExitsExpire стандартно 1800 секунд, то есть полчаса)
Мне кажеться, что это не к месту было писать, так как эти перечисленные параметры легко меняются в файле конфигурации TOR клиента. См. www.torproject.org/...-manual.html.en, и Вы меня ничем тут не удивили, так как я в статье оставила ссылку на эту документацию, сказав, что по ней много интересного можно найти по TOR proxy... Спасибо, что прочитали...

Мне было бы интересно продолжить с Вами дискуссию по топику, Рома. Буду ждать ответа от Вас.

Спасибо.

Я тоже не понимаю почему все так мудрено как с реализацией так и с ее описанием.
2. часть: смена ip
VPN (еще есть люди которые не держат свой сервак с vpn для выхода не из хацапетовки?)

Рома, хотела бы еще от Вас услышать легкость решения на базе VPN (предложенного Вами), раз уж Вас задела моя легкость на базе TOR решения. А именно, как Вы представляйте себе эту легкость, и чем она легче моей легкости (TOR решение) в контексте моего топика, где в моем случае все, что нужно сделать — просто поставить TOR прокси сервер?

Вы ошибаетесь, ваше решение нисколько никоим образом меня не задевает. Однако я бы не воспользовался решением на основе Tor так как имею чисто субъективное личное мнение, на основе опыта использования несколько летней давности, о его работе. В последний раз когда я имел дело с сетью Tor ничего кроме большого ping-a и ошибки с 20% запросов не запомнилось.

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

то наверняка читали и такой документ, как www.w3.org/.../ct-guidelines, которому должны следовать все HTTP proxies

Нет не читал и не буду так как меня вполне устраивают искажающие/анонимизирующие прокси сервера.

пожалуйста примеры хоть одного proxy и другого сервиса по смене IP

Да здесь я неправ сейчас не вижу ни одного подобного сервиса, который бы принял как параметр адрес назначения. Все стали умными токены используют, правда какая им разница если они потом встраивают рекламу в результат не совсем понятно. Обойти и это конечно можно но в данном контексте это решение окажется мудренее чем использование Tor-а.

Спасибо, Рома, будет еще что-то полезное добавить, пишите, буду рада Вас снова видеть в комментариях.

а ручками нельзя это за 2е минуты протестировать было ? обязательно нада весь этот огород ???

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

Спасибо, @mobile.

До чего сложно. На тестовой системе делаем возможность из куки (например) подменить IP клиента и всё ограничивается селениумом.

До чего сложно. На тестовой системе делаем возможность из куки (например) подменить IP клиента и всё ограничивается селениумом.

Спасибо Ярик за комментарий.

Куки и IP совсем разные вещи, и решают разные проблемы.

Куки служат для идентификации HTTP запросов исходящих от одного и того же клиента (по сути идентификация клиента).

IP решает проблемы идентификации узлов (компьютеров) в сети.

Как раз для того, чтоб систематизировать эти знания (я так думаю), появились на свет различные сетевые модели (почитать о двух из них можно здесь: en.wikipedia.org/wiki/OSI_model). К примеру,
по модели OSI, понятие HTTP появляется лишь на самом верхнем уровне — прикладном уровне (именно на этом уровне и появляется понятие кукисов и других состовляющих HTTP. Почитать детали можно здесь: en.wikipedia.org/...ansfer_Protocol), в то время как IP живет на сетевом уровене (межсетевой уровень по модели TCP/IP: en.wikipedia.org/...#Internet_layer).

Если мы заменим в приложении функциональность бан по IP, на нечто (я, честно, извините, не поняла, что Вы имели ввиду в своем высказывании), то мы будем тестировать это нечто, а не бан по IP.

Если я ошибаюсь, жду от Вас проясняющий комментарий.

Спасибо.

Спасибо за развернутый ответ :)
Видимо, я недостаточно ясно выразился. Для тестирования (тем более автоматизированного) совершенно не обязательно менять IP по-настоящему. Достаточно как-то сигнализировать тестируемой системе, что клиент (Selenium) отныне имеет указанный IP. И подменять им на стадии загрузки настоящий.
Например функционал, проверяющий IP получает его через функцию getIp();
В продакшене getIp() возвращает безусловный IP текущего клиента, в тестовой среде по сигналу мы можем вернуть любой IP, какой мы захотим.
Возможно, в твоем случае тестируемая система абсолютный черный ящик, но во всех других случаях это гораздо проще и надежнее.

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

Спасибо, Ярик, хороший ответ.

Но тут скорей речь не о методе проведения тестирования отталкиваясь от знания про систему, а о уровне тестирования системы. Своим решением я попыталась закрыть системное тестирование (так же известное, как end-to-end testing или system testing) и приемочное тестирование (известное, как acceptance testing). И на этих уровнях, мне кажется, очень важно тестировать систему в таком состоянии (без моков, в смысле умышленной подмены части функционала для получения заведомо ожидаемого поведение), в каком она будет разворачиваться на боевых окружениях и/или у заказчика.

Что Вы думайте, Ярик, по этому поводу?

Мне кажется, не стоит возводить всё в абсолют. Для этой подсистемы IP адрес — входной параметр. При правильном построении системы не имеет значения, как мы получаем этот входной параметр. Влияет лишь то, что сначала он был одним, а стал другим.
На мой взгляд, использование TOR’а в данном случае лишь увеличивает возможность отказа. Что будет, если не вовремя сменится выходная нода?
Ещё один минус данного подхода — сложность ограничения доступа к тестовому серверу извне.

Спасибо, согласна, еще один аргумент против моего решения.

Думаю, что действительно стоит задуматься о более надежном решении, чем TOR.

Если будут предложения, то пишите пожалуйста в комментариях к статье, буду рада снова услышать Ваше мнение. Но вариант с моками, описанный как вариант от Вас выше мне не нравится, по причине того, что конечное тестирование (непосредственно до деливери, или сразу после) нужно проводить на реальном приложении.

Спасибо, Ярик!

Кстати, Ярик, я об этом забыла написать в статье, но я провела тест на выполнение 1000 обращений за IP из TOR сети, из них только ~100 были с задержкой от 10 до 20 сек, остальные в пределах 7 сек. Отказа не встречала, но и не отрицаю того, что его не может быть. В целом отказ может произойти с чем угодно, и тут важно, на сколько грамотно продумано решение, которое используем. В TOR’е есть решение, обеспечивающее отказоустойчивость (автоматическим переключением узлов), но на сколько оно действенно, я не смогла увидеть из своих тестов.

К чему тут TOR городить было, tcprewrite хватило бы...

Жесть, но инструмент интересный. Городить на TOR’е взялась именно потому, что уж очень tcprewrite не дружелюбным показался. Думаю, что те, кто посмотрит на него и на TOR почувствуют эту разницу. С TOR клиентом все просто, запускаешь его как socks прокси, браузеру указала socks хост и порт, через что ходить за страничками, а настройку и управление всем маршрутом от браузера до web сервера TOR клиент сам делает, и вполне сносно с конфигурацией по умолчанию. В tcprewrite нужно мурыжится с низкоуровневой сетевой конфигурацией, чтоб это решение работало везде и было универсальным, при том, на сколько я понимаю, все еще может упереться в настройки роутера, от чего набор ключей тоже может меняться от сети к сети. Вот, почему я остановилась на TOR’е.

Попробуйте, пожалуйста, расширенными комментариями возражать, если что, чтоб я не переспрашивала, потому как тема достаточно сложная, и высказывание

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

О Небо...
Прошу, пишите проще, короче и не додумывайте за оппонента.

Суть моего комментария сводится к тому, что задача забить гвоздь решается с помощью микроскопа.

Нужно поменять IP — делайте это на том уровне, где этому и место (а не на самом верху сетевого стека). tcprewrite — это просто пример. Никто не мешает решать ту же проблему установкой простого proxy перед сервером и манипуляцией его (proxy) настроек во время тестирования.

P.S. Хотите этого или нет, но «мурыжится» с подобными инструментами придется научится. Если, конечно, есть желание стать классным инженером.

Суть моего комментария сводится к тому, что задача забить гвоздь решается с помощью микроскопа.
Я так и решила задачу, но при этом сделала наиболее простым способом из доступных мне, я пока в этом убеждена.
Нужно поменять IP — делайте это на том уровне, где этому и место (а не на самом верху сетевого стека). tcprewrite — это просто пример. Никто не мешает решать ту же проблему установкой простого proxy перед сервером и манипуляцией его (proxy) настроек во время тестирования.
Это я и сделала, TOR клиент так и работает в режиме socks прокси сервера.
P.S. Хотите этого или нет, но «мурыжится» с подобными инструментами придется научится. Если, конечно, есть желание стать классным инженером.
Постоянно нахожусь под воздействием желания без надобности не спускаться по стеку TCP/IP ниже и ниже без весомых на то аргументов, а таких я не нашла. Поэтому отталкивалась от того инструмента, который решает проблему, причем, как я пока убеждена наиболее универсальным и простым способом, а именно не нужно никаких прокси отдельных держать где-то в локальной сети, поддерживать их работу, чтоб использовать другой IP, если эта медвежья услуга идет из коробки TOR решения.

В целом, Андрей, я согласна с Вами, что где-то можно tcprewrite использовать, как замену TOR’а. Все скорей зависит от конкретного случая.

Буду ждать от Вас аргументированного и убедительного комментария, что в моем случае tcprewrite лучше подходит, нежели TOR.

Спасибо, Андрей.

Ирина — Тор действительно лучше подходит, если тестируемый сервис находится снаружи периметра среды, однако совершенно не годится, если внутри.
tcprewrite же наоборот.
Возможно имеет смысл предусмотреть оба эти кейса.

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

Не совсем — если сервис еще не в продуктиве, то Вы не сможете его протестировать через Tor по причине наличия отсутствия у сервера «честного» IP-адреса и доступа к нему «из мира».

Согласна, один аргумент есть. Спасибо, Тим!

Спасибо Сереже, верстку поправили.

Подписаться на комментарии