
Если вы когда-нибудь пытались просмотреть сетевые запросы десктопного или мобильного приложения через HTTPS-прокси, то наверняка сталкивались со странной ситуацией: прокси настроен, корневой сертификат установлен и доверен, системный прокси прописан, а в списке запросов пусто. Или приложение начинает выдавать ошибку сразу после включения перехвата.
Ниже будет описан набор реальных сценариев, со схемами работы на сетевом уровне и примерами того, как это выглядит в прокси-приложении. Для этого я использую Сольпугу и несколько демо-приложений с разными условиями.
1. Приложение вообще не использует прокси и устанавливает соединение напрямую
Самый простой и очень частый случай. Приложение либо полностью игнорирует системные настройки прокси, либо использует собственный HTTP-клиент, который читает прокси только из переменных окружения / собственной конфигурации.
Типичные примеры:
Flutter (часто игнорирует системный прокси)
Кастомные реализации на
OkHttp/URLSessionс особыми конфигурациямиПриложения, которые проверяют наличие специальной переменной (типа
HTTP_PROXYв Linux) и отказываются так работать
Тут мало что можно сделать, разве что в случае кастомных реализаций делать специальные сборки для работы через внешние прокси.

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

2. Приложение использует прокси, но не доверяет его сертификату
Трафик доходит до прокси, но TLS-рукопожатие падает, потому что приложение (или система) не доверяет его корневому сертификату.
Прокси-сервер для каждого имени хоста генерирует на лету конечный (leaf) сертификат и подписывает его своим собственным корневым центром сертификации. Приложение принимает подменный сертификат только в том случае, если корневой сертификат прокси-сервера находится в хранилище доверенных сертификатов, к которому оно фактически обращается.
На устройстве могут быть системное хранилище и отдельное пользовательское. На Android 7+ приложения по умолчанию доверяют только системному хранилищу, а на iOS профиль конфигурации должен быть помечен как полностью доверенный; в противном случае сертификат устанавливается, но игнорируется.
В этом случае можно попробовать добавить корневой сертификат в системное хранилище или разрешить в приложении обращение к пользовательскому, если это возможно.


3. TLS-рукопожатие начинается, но SSL Pinning прерывает его до установки соединения
SSL Pinning - распространённая практика в приложениях, которые работают с чувствительными данными. Во время соединения, после обычной проверки цепочки сертификатов, приложение дополнительно проверяет открытый ключ сервера (или весь сертификат) на соответствие жестко зашитому в код значению (SPKI pin / certificate pin). Поддельный же конечный сертификат содержит открытый ключ прокси-сервера, а не реального сервера. Даже если система полностью доверяет корневому центру сертификации прокси-сервера, проверка не проходит, и соединение так и не устанавливается.

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

4. Приложение использует собственный TLS-стек или отдельное хранилище сертификатов
Некоторые приложения не используют системный TLS и системное хранилище сертификатов. Они либо:
либо используют собственный
BoringSSL/OpenSSL/mbedTLS,либо имеют встроенное хранилище доверенных сертификатов,
либо реализуют pinning на уровне своего стека.
Например, Firefox на Linux может потребовать отдельного импорта корневого сертификата через свои настройки в свое хранилище. В этом случае даже правильно установленный системный корневой сертификат прокси ничего не даёт.

В этом случае запросы могут проходить частично, либо не проходить вовсе. Например, здесь сертификат установлен, запросы Curl и Lynx бегают, а Firefox артачится:

5. Разные части приложения используют разные сетевые библиотеки и каналы связи
Очень частый случай в больших приложениях. Основной функционал ходит через один HTTP-клиент (который «уважает» прокси), а аналитика, пуши, веб-сокеты, загрузка изображений, платежный SDK - через другой сетевой стек.
В результате часть запросов видна, а часть нет.

6. Приложение использует протокол или транспорт, который не поддерживается конкретным прокси-приложением
Даже если приложение поддерживает работу через прокси-сервер и не использует pinning, оно может использовать протокол, который конкретный прокси плохо или совсем не поддерживает.
HTTP/2: требует полноценной поддержки бинарного формата данных, синхронизацию для stateful HPACK. Многие прокси пропускают только HTTP/1.1 и теряют часть запросо.
HTTP/3 / QUIC: работает поверх UDP. Классические дебаг-прокси почти всегда TCP-only. Если сеть разрешает UDP/443 - клиент устанавливает QUIC напрямую, минуя прокси.

В TCP-прокси такой трафик просто отсутствует, либо трансформируется в HTTP/1, если источник поддерживает несколько типов соединения (заголовок alt-svc):

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

