Menambahkan Outline SDK ke aplikasi seluler

Dokumen ini menguraikan cara mengintegrasikan Outline SDK ke dalam aplikasi seluler Anda, dengan berfokus pada library MobileProxy untuk pengelolaan proxy lokal yang disederhanakan.

MobileProxy adalah library berbasis Go yang dirancang untuk menyederhanakan integrasi fungsionalitas proxy ke dalam aplikasi seluler. Fitur ini menggunakan Go Mobile untuk membuat library seluler, sehingga Anda dapat mengonfigurasi library jaringan aplikasi untuk merutekan traffic melalui proxy lokal.

Aplikasi tanpa MobileProxy

Aplikasi konten tanpa MobileProxy

Aplikasi dengan MobileProxy

Aplikasi konten dengan MobileProxy

Langkah 1: Membangun library seluler MobileProxy

Gunakan gomobile untuk mengompilasi kode Go menjadi library untuk Android dan iOS.

  1. Buat clone repositori Outline SDK:

    git clone https://github.com/Jigsaw-Code/outline-sdk.git
    cd outline-sdk/x
    
  2. Buat biner Go Mobile dengan go build:

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

    Menambahkan Dukungan Psiphon

    Anda dapat menambahkan dukungan untuk menggunakan jaringan Psiphon dengan mengikuti langkah-langkah tambahan berikut:

    • Hubungi tim Psiphon untuk mendapatkan konfigurasi yang memberi Anda akses ke jaringan mereka. Hal ini mungkin memerlukan kontrak.
    • Tambahkan konfigurasi Psiphon yang diterima ke bagian fallback dari konfigurasi SmartDialer Anda.
    • Bangun Mobile Proxy menggunakan flag -tags psiphon:

      go build -tags psiphon -o "$(pwd)/out/" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind
      
    • Daftarkan Psiphon dengan Smart dialer di kode native Anda.

    Flag -tags psiphon diperlukan karena codebase Psiphon dilisensikan berdasarkan GPL, yang dapat memberlakukan batasan lisensi pada kode Anda sendiri. Anda mungkin ingin mempertimbangkan untuk mendapatkan lisensi khusus dari mereka.

  3. Buat library seluler dan tambahkan ke project Anda:

    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
    

    Di Android Studio, pilih File > Import Project… untuk mengimpor paket out/mobileproxy.aar yang dihasilkan. Untuk mendapatkan bantuan lainnya, lihat Membangun dan men-deploy ke Android di Go Mobile.

    iOS

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

    Seret paket out/mobileproxy.xcframework ke project Xcode. Untuk bantuan lebih lanjut, lihat Membangun dan men-deploy ke iOS di Go Mobile.

Langkah 2: Jalankan MobileProxy

  1. Lakukan inisialisasi dan mulai proxy lokal MobileProxy dalam runtime aplikasi Anda. Anda dapat menggunakan konfigurasi transportasi statis atau Smart Proxy untuk pemilihan strategi dinamis.
  • Konfigurasi transpor statis: Gunakan fungsi RunProxy dengan alamat lokal dan konfigurasi transpor.

    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: Smart Proxy secara dinamis memilih strategi DNS dan TLS berdasarkan domain pengujian yang ditentukan. Anda perlu menentukan strategi konfigurasi dalam format YAML (contoh).

    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()
    
  1. Kemudian, jika Anda menggunakan psiphon, daftarkan Psiphon dengan opsi Smart Dialer di kode native Anda.

Android:

import mobileproxy.Mobileproxy
import psiphon.Psiphon

// ...

val testDomains = Mobileproxy.newListFromLines("www.google.com\ni.ytimg.com")
// You can get a Psiphon config from the Psiphon team at sponsor@psiphon.ca.
val psiphonConfig = "<YOUR_PSIPHON_CONFIG_JSON_HERE>"
val config = """
dns:
  - {system: {}}
tls:
  - ""
fallback:
  - {"psiphon": \(psiphonConfig)}
"""

val options = Mobileproxy.newSmartDialerOptions(testDomains, config)

// Register Psiphon
Psiphon.registerConfig(options, "psiphon")

try {
    // Create the dialer
    val dialer = options.newStreamDialer()
    // ... use the dialer
} catch (e: Exception) {
    // Handle error
}

iOS:

import Mobileproxy
import Psiphon

// ...

let testDomains = MobileproxyNewListFromLines("www.google.com\ni.ytimg.com")
// You can get a Psiphon config from the Psiphon team at sponsor@psiphon.ca.
let psiphonConfig = "<YOUR_PSIPHON_CONFIG_JSON_HERE>"
let config = """
dns:
  - {system: {}}
tls:
  - ""
fallback:
  - {"psiphon": \(psiphonConfig)}
"""

let options = MobileproxyNewSmartDialerOptions(testDomains, config)

// Register Psiphon
PsiphonRegisterConfig(options, "psiphon")

do {
    // Create the dialer
    let dialer = try options.newStreamDialer()
    // ... use the dialer
} catch {
    // Handle error
}

Langkah 3: Konfigurasi klien HTTP dan library jaringan

Konfigurasi library jaringan Anda untuk menggunakan alamat dan port proxy lokal.

HttpClient Dart/Flutter

Tetapkan proxy dengan HttpClient.findProxy.

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

OkHttp (Android)

Tetapkan proxy dengan OkHttpClient.Builder.proxy.

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

JVM (Java, Kotlin)

Konfigurasi proxy yang akan digunakan dengan properti sistem:

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()))

Tampilan Web Android

Terapkan konfigurasi proxy ke semua tampilan web di aplikasi Anda dengan library 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
    )

Tampilan Web iOS

Mulai iOS 17, Anda dapat menambahkan konfigurasi proxy ke WKWebView menggunakan WKWebsiteDataStore properti:

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)

Tingkat lanjut: Membuat pustaka seluler kustom

Untuk kasus penggunaan lanjutan, Anda dapat membuat library seluler Anda sendiri:

  1. Buat library Go: Kembangkan paket Go yang membungkus fungsi SDK yang diperlukan.
  2. Membuat library seluler: Gunakan gomobile bind untuk menghasilkan Android Archives (AAR) dan Apple Frameworks. Contoh:
  3. Integrasikan ke aplikasi Anda: Tambahkan library yang dihasilkan ke aplikasi seluler Anda.