Ajouter le SDK Outline à votre application mobile

Ce document explique comment intégrer le SDK Outline à des applications mobiles et se concentre sur la bibliothèque MobileProxy afin de simplifier la gestion des proxys locaux.

MobileProxy est une bibliothèque basée sur Go conçue pour simplifier l'intégration de fonctionnalités de proxy dans les applications mobiles. Elle utilise Go Mobile pour générer des bibliothèques mobiles. Vous pouvez ainsi configurer les bibliothèques réseau de vos applications pour acheminer le trafic via un proxy local.

Application sans MobileProxy

Application de contenu sans MobileProxy

Application avec MobileProxy

Application de contenu avec MobileProxy

Étape 1 : Créer des bibliothèques mobiles MobileProxy

Utilisez gomobile pour compiler le code Go en bibliothèques pour Android et iOS.

  1. Clonez le dépôt du SDK Outline :

    git clone https://github.com/Jigsaw-Code/outline-sdk.git
    cd outline-sdk/x
    
  2. Créez les binaires Go Mobile avec go build :

    go build -o "$(pwd)/out/" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind
    

    Ajouter la compatibilité Psiphon

    Vous pouvez rendre possible l'utilisation du réseau Psiphon en suivant ces étapes :

    • Contactez l'équipe Psiphon pour obtenir une configuration qui vous donne accès à son réseau. Un contrat peut être nécessaire.
    • Ajoutez la configuration Psiphon reçue à la section fallback de votre configuration SmartDialer.
    • Créez le MobileProxy à l'aide de l'option -tags psiphon :

      go build -tags psiphon -o "$(pwd)/out/" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind
      

    L'option -tags psiphon est nécessaire, car le codebase Psiphon est sous licence GPL, ce qui peut imposer des restrictions de licence à votre propre code. Vous pouvez envisager d'obtenir une licence spéciale auprès de Psiphon.

  3. Générez les bibliothèques mobiles et ajoutez-les à votre projet :

    Android

    PATH="$(pwd)/out:$PATH" gomobile bind -ldflags='-s -w' -target=android -androidapi=21 -o "$(pwd)/out/mobileproxy.aar" github.com/Jigsaw-Code/outline-sdk/x/mobileproxy
    

    Dans Android Studio, sélectionnez File > Import Project (Fichier > Importer un projet) pour importer le bundle out/mobileproxy.aar généré. Pour en savoir plus, consultez la section sur la création et le déploiement sur Android de la documentation Go Mobile.

    iOS

    PATH="$(pwd)/out:$PATH" gomobile bind -ldflags='-s -w' -target=ios -iosversion=11.0 -o "out/mobileproxy.xcframework" github.com/Jigsaw-Code/outline-sdk/x/mobileproxy
    

    Faites glisser le bundle out/mobileproxy.xcframework dans le projet Xcode. Pour en savoir plus, consultez la section sur la création et le déploiement sur iOS de la documentation Go Mobile.

Étape 2 : Exécuter le MobileProxy

Initialisez et lancez le proxy local MobileProxy dans l'environnement d'exécution de votre application. Vous pouvez utiliser une configuration de transport statique ou le Smart Proxy pour sélectionner une stratégie de façon dynamique.

  • Configuration de transport statique : utilisez la fonction RunProxy en incluant une adresse locale et une configuration de transport.

    Android

    import mobileproxy.*
    
    val dialer = StreamDialer("split:3")
    
    // Use port zero to let the system pick an open port for you.
    val proxy = Mobileproxy.runProxy("localhost:0", dialer)
    // Configure your networking library using proxy.host() and proxy.port() or proxy.address().
    // ...
    // Stop running the proxy.
    proxy.stop()
    

    iOS

    import Mobileproxy
    
    let dialer = MobileproxyStreamDialer("split:3")
    
    // Use port zero to let the system pick an open port for you.
    let proxy = MobileproxyRunProxy("localhost:0", dialer)
    // Configure your networking library using proxy.host() and proxy.port() or proxy.address().
    // ...
    // Stop running the proxy.
    proxy.stop()
    
  • Smart Proxy : le Smart Proxy sélectionne des stratégies DNS et TLS de façon dynamique en fonction des domaines de test spécifiés. Vous devez spécifier la stratégie de configuration au format YAML (exemple).

    Android

    val testDomains = Mobileproxy.newListFromLines("www.youtube.com\ni.ytimg.com")
    val strategiesConfig = "..."  // Config YAML.
    val dialer = Mobileproxy.newSmartStreamDialer(testDomains, strategiesConfig, Mobileproxy.newStderrLogWriter())
    
    // Use port zero to let the system pick an open port for you.
    val proxy = Mobileproxy.runProxy("localhost:0", dialer)
    // Configure your networking library using proxy.host() and proxy.port() or proxy.address().
    // ...
    // Stop running the proxy.
    proxy.stop()
    

    iOS

    import Mobileproxy
    
    var dialerError: NSError?
    let testDomains = MobileproxyNewListFromLines("www.youtube.com\ni.ytimg.com")
    let strategiesConfig = "..."  // Config YAML.
    let dialer = MobileproxyNewSmartStreamDialer(
        testDomains,
        strategiesConfig,
        MobileproxyNewStderrLogWriter(),
        &dialerError
    )
    
    var proxyError: NSError?
    // Use port zero to let the system pick an open port for you.
    MobileproxyRunProxy("localhost:0", dialer, &proxyError)
    // Configure your networking library using proxy.host() and proxy.port() or proxy.address().
    // ...
    // Stop running the proxy.
    proxy.stop()
    

Étape 3 : Configurer les clients HTTP et les bibliothèques réseau

Configurez vos bibliothèques réseau pour qu'elles utilisent l'adresse et le port du proxy local.

HttpClient Dart/Flutter

Configurez le proxy avec HttpClient.findProxy.

HttpClient client = HttpClient();
client.findProxy = (Uri uri) {
  return "PROXY " + proxy.address();
};

OkHttp (Android)

Configurez le proxy avec OkHttpClient.Builder.proxy.

val proxyConfig = Proxy(Proxy.Type.HTTP, InetSocketAddress(proxy.host(), proxy.port()))
val client = OkHttpClient.Builder().proxy(proxyConfig).build()

JVM (Java, Kotlin)

Configurez le proxy avec les propriétés système :

System.setProperty("http.proxyHost", proxy.host())
System.setProperty("http.proxyPort", String.valueOf(proxy.port()))
System.setProperty("https.proxyHost", proxy.host())
System.setProperty("https.proxyPort", String.valueOf(proxy.port()))

WebView Android

Appliquez une configuration de proxy à toutes les vues Web de votre application avec la bibliothèque androidx.webview :

ProxyController.getInstance()
    .setProxyOverride(
        ProxyConfig.Builder()
            .addProxyRule(this.proxy!!.address())
            .build(),
        {}, // execution context for the following callback - do anything needed here once the proxy is applied, like refreshing web views
        {} // callback to be called once the ProxyConfig is applied
    )

WebView iOS

À partir d'iOS 17, vous pouvez ajouter une configuration de proxy à une WKWebView en utilisant sa propriété WKWebsiteDataStore :

let configuration = WKWebViewConfiguration()
let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(proxyHost), port: NWEndpoint.Port(proxyPort)!)
let proxyConfig = ProxyConfiguration.init(httpCONNECTProxy: endpoint)
let websiteDataStore = WKWebsiteDataStore.default()
websiteDataStore.proxyConfigurations = [proxyConfig]
let webview = WKWebView(configuration: configuration)

Options avancées : générer une bibliothèque mobile personnalisée

Pour les cas d'utilisation avancés, vous pouvez générer vos propres bibliothèques mobiles :

  1. Créez une bibliothèque Go : créez un package Go réunissant les fonctionnalités de SDK nécessaires.
  2. Générez des bibliothèques mobiles : utilisez gomobile bind pour créer des archives Android (AAR) et des frameworks Apple. Exemples :
  3. Intégrez-les à votre application : ajoutez les bibliothèques générées à votre application mobile.