>_ DevTrendspl

Język

Strona główna

Języki

Sekcje

Frontend Backend Mobilne DevOps AI / ML GameDev Blockchain Systemy wbudowane Bezpieczeństwo
Kotlin

Jak przechwytywać ruch HTTPS na Androidzie bez certyfikatów i ręcznej konfiguracji proxy

Każdy programista Androida kiedyś spędził co najmniej pół dnia roboczego na konfiguracji debugera sieci. Scenariusz jest zawsze taki sam: chcesz zobaczyć, co aplikacja wysyła do backendu, a zamiast tego otrzymujesz SSLHandshakeException.

Następnie rozpoczyna się rytuał. Najpierw generujesz certyfikat CA podpisany samodzielnie. Potem próbujesz zainstalować go w magazynie zaufanych certyfikatów na urządzeniu testowym. Począwszy od Androida 7.0 (API 24), system domyślnie ignoruje certyfikaty użytkownika, więc musisz zmodyfikować network_security_config.xml, skonfigurować trust-anchors dla kompilacji debug, a następnie przebudować APK. Jeśli Twój projekt ma skonfigurowany SSL Pinning lub testujesz na Androidzie 14, gdzie obsługa certyfikatów systemowych stała się jeszcze bardziej restrykcyjna, proste sprawdzenie nagłówka odpowiedzi zamienia się w osobne zadanie inżynieryjne.

Biblioteka atlantis-android od zespołu Proxyman rozwiązuje ten problem radykalnie: eliminuje konieczność konfigurowania proxy i dotykania certyfikatów systemowych urządzenia.

Capture HTTPS from Android app

Na czym polega idea Atlantis

Tradycyjne narzędzia takie jak Charles, Fiddler czy sam Proxyman zazwyczaj działają w schemacie Man-in-the-Middle (MitM). Urządzenie przekierowuje cały ruch na adres IP komputera, a aplikacja desktopowa przechwytuje żądania, odszyfrowuje je własnym certyfikatem i przesyła dalej. Dlatego właśnie problemy z zaufaniem certyfikatów i konfiguracją proxy Wi-Fi stają się kłopotliwe.

Atlantis działa inaczej. To kompaktowa biblioteka Kotlin, która osadza się bezpośrednio w kompilacji debug aplikacji jako interceptor klienta sieciowego. Interceptor odczytuje parametry żądań i odpowiedzi w momencie, gdy aplikacja już je utworzyła lub właśnie odszyfrowała. Biblioteka następnie serializuje te dane, kompresuje je za pomocą GZIP i przesyła bezpośrednio do aplikacji Proxyman na macOS przez oddzielny lokalny socket.

W rezultacie otrzymujesz szczegółowy log aktywności sieciowej bez żadnej interwencji w ustawieniach Androida, bez modyfikacji manifestu i bez manipulacji certyfikatami.

Co potrafi biblioteka

Atlantis obejmuje większość codziennych zadań debugowania sieci:

  • Przechwytywanie zwykłych żądań HTTP i HTTPS bezpośrednio z OkHttp.
  • Logowanie zdarzeń WebSocket: otwieranie połączenia, wysyłanie wiadomości, przychodzące pakiety i zamykanie sesji.
  • Pełna kompatybilność z popularnymi klientami sieciowymi, w tym Retrofit 2.9+ i Apollo Kotlin 3.x/4.x.
  • Automatyczne wykrywanie działającej instancji Proxyman w lokalnej sieci przez Network Service Discovery (mDNS).

Jeśli uruchamiasz projekt na oficjalnym emulatorze Androida, biblioteka może połączyć się z maszyną hosta bezpośrednio, omijając wykrywanie sieci.

Jak zintegrować z projektem

Biblioteka wymaga Androida z API 26 (Android 8.0) lub wyższym, OkHttp w wersji 4.x lub 5.x oraz Kotlin w wersji 1.9 lub wyższej.

Najpierw dodaj repozytorium JitPack do pliku settings.gradle.kts:

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }
    }
}

Następnie dodaj zależność do pliku build.gradle.kts swojej aplikacji. Najlepiej dodać ją wyłącznie przez debugImplementation, aby upewnić się, że kod debug nie trafi do kompilacji release:

dependencies {
    debugImplementation("com.github.ProxymanApp:atlantis-android:v1.0.0")
}

Biblioteka jest również dostępna w Maven Central pod artefaktem com.proxyman:atlantis-android:1.0.0.

Szybki start

Integracja zajmuje tylko kilka linijek kodu. Najpierw zainicjuj Atlantis w klasie Application:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        
        if (BuildConfig.DEBUG) {
            Atlantis.start(this)
        }
    }
}

Następnie dodaj interceptor do konfiguracji OkHttpClient:

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(Atlantis.getInterceptor())
    .build()

Jeśli używasz Retrofit, przekaż tę instancję okHttpClient do Retrofit.Builder(), a wszystkie żądania automatycznie pojawią się w oknie Proxyman.

Praca z WebSocket

Jeśli Twoja aplikacja używa websockets, standardowy interceptor OkHttp nie wystarczy, ponieważ wiadomości są przesyłane w ramach już otwartego połączenia. W takich przypadkach biblioteka udostępnia specjalny wrapper dla listenera:

val originalListener = object : WebSocketListener() {
    override fun onOpen(webSocket: WebSocket, response: Response) {
        // обработка открытия
    }
    override fun onMessage(webSocket: WebSocket, text: String) {
        // входящее сообщение
    }
}

val wrappedListener = Atlantis.wrapWebSocketListener(originalListener)
okHttpClient.newWebSocket(request, wrappedListener)

Teraz możesz obserwować przychodzące i wychodzące ramki w czasie rzeczywistym w kliencie desktopowym.

Co w środku

Kod źródłowy biblioteki jest minimalistyczny i udostępniony na licencji Apache 2.0. Repozytorium nie zawiera prawie żadnych ciężkich zależności zewnętrznych.

Architektura składa się z kilku wyraźnych modułów:

  • AtlantisInterceptor i AtlantisWebSocketListener przechwytują dane na poziomie stosu sieciowego.
  • GzipCompression i Base64Utils pakują treści żądań i ładunki binarne, zmniejszając obciążenie kanału komunikacyjnego między telefonem a komputerem.
  • NsdServiceDiscovery odpowiada za wykrywanie usługi _proxyman._tcp w lokalnej sieci przez API Android NSD.
  • Transporter otwiera połączenie TCP z aplikacją desktopową i przesyła dalej ustrukturyzowane pakiety.

Dzięki kompresji ruchu debugowanie praktycznie nie wpływa na wydajność aplikacji.

Ograniczenia, o których warto wiedzieć

Przed integracją biblioteki należy wziąć pod uwagę dwie kwestie.

Po pierwsze, Atlantis jest powiązany z klientem desktopowym Proxyman. Jeśli Twój zespół jest przyzwyczajony do wyłącznego korzystania z Wireshark lub Charles, nie będziesz mógł przesyłać tam danych przez ten interceptor.

Po drugie, biblioteka przechwytuje ruch tylko od klientów, do których jawnie dodałeś interceptor. Jeśli zewnętrzny SDK w Twojej aplikacji wykonuje wywołania sieciowe przez własny HttpURLConnection lub Cronet, Atlantis nie zobaczy tych żądań. Do pełnej analizy zewnętrznych binariów nadal będziesz musiał używać klasycznego proxy MitM.

Czy warto wypróbować

Jeśli Twoja główna maszyna deweloperska działa na macOS i już używasz Proxyman do debugowania iOS lub backendu, atlantis-android oszczędza mnóstwo czasu. Zapominasz na zawsze o konfigurowaniu proxy Wi-Fi na telefonach testowych, resetowaniu certyfikatów i modyfikowaniu network_security_config. Po prostu budujesz APK debug, otwierasz aplikację na telefonie, a cała wymiana sieciowa natychmiast pojawia się na ekranie.

Powiązane projekty