Thêm Outline SDK vào ứng dụng di động

Tài liệu này trình bày cách tích hợp Outline SDK vào ứng dụng di động, tập trung vào thư viện MobileProxy để đơn giản hoá việc quản lý proxy cục bộ.

MobileProxy là một thư viện dựa trên Go được thiết kế để đơn giản hoá việc tích hợp các chức năng proxy vào ứng dụng di động. Thư viện này sử dụng Go Mobile để tạo thư viện dành cho thiết bị di động, cho phép bạn định cấu hình thư viện kết nối mạng của ứng dụng để định tuyến lưu lượng truy cập thông qua một proxy cục bộ.

Ứng dụng không có MobileProxy

Ứng dụng nội dung không có MobileProxy

Ứng dụng có MobileProxy

Ứng dụng nội dung có MobileProxy

Bước 1: Tạo thư viện di động MobileProxy

Sử dụng gomobile để biên dịch mã Go thành thư viện cho Android và iOS.

  1. Sao chép kho lưu trữ Outline SDK:

    git clone https://github.com/Jigsaw-Code/outline-sdk.git
    cd outline-sdk/x
    
  2. Tạo các tệp nhị phân Go Mobile bằng go build:

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

    Thêm tính năng hỗ trợ Psiphon

    Bạn có thể thêm tính năng hỗ trợ để sử dụng mạng Psiphon bằng cách làm theo các bước bổ sung sau:

    • Hãy liên hệ với nhóm Psiphon để lấy cấu hình cấp cho bạn quyền truy cập vào mạng của họ. Bạn có thể cần phải ký hợp đồng.
    • Thêm cấu hình Psiphon đã nhận được vào phần fallback của cấu hình SmartDialer.
    • Tạo Proxy di động bằng cờ -tags psiphon:

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

    Bạn phải sử dụng cờ -tags psiphon vì cơ sở mã Psiphon được cấp phép theo GPL. Điều này có thể áp đặt các quy định hạn chế về giấy phép đối với mã của riêng bạn. Bạn nên cân nhắc việc xin giấy phép đặc biệt của họ.

  3. Tạo thư viện dành cho thiết bị di động và thêm các thư viện đó vào dự án:

    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
    

    Trong Android Studio, hãy chọn File > Import Project… (Tệp > Nhập dự án…) để nhập gói out/mobileproxy.aar đã tạo. Để được trợ giúp thêm, hãy xem phần Tạo và triển khai cho Android của 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
    

    Kéo gói out/mobileproxy.xcframework vào dự án Xcode. Để được trợ giúp thêm, hãy xem phần Tạo và triển khai cho iOS của Go Mobile.

Bước 2: Chạy MobileProxy

Khởi chạy và bắt đầu proxy cục bộ MobileProxy trong thời gian chạy của ứng dụng. Bạn có thể sử dụng cấu hình truyền tải tĩnh hoặc Proxy thông minh để chọn chiến lược động.

  • Cấu hình truyền tải tĩnh: Sử dụng hàm RunProxy với địa chỉ cục bộ và cấu hình truyền tải.

    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()
    
  • Proxy thông minh: Proxy thông minh sẽ tự động chọn chiến lược DNS và TLS dựa trên các miền kiểm thử đã chỉ định. Bạn cần chỉ định chiến lược cấu hình ở định dạng YAML (ví dụ).

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

Bước 3: Định cấu hình ứng dụng HTTP và thư viện kết nối mạng

Định cấu hình thư viện mạng để sử dụng địa chỉ và cổng proxy cục bộ.

HttpClient Dart/Flutter

Đặt proxy bằng HttpClient.findProxy.

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

OkHttp (Android)

Đặt proxy bằng OkHttpClient.Builder.proxy.

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

JVM (Java, Kotlin)

Định cấu hình proxy để sử dụng với thuộc tính hệ thống:

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

Chế độ xem web Android

Áp dụng cấu hình proxy cho tất cả thành phần hiển thị web trong ứng dụng bằng thư viện 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
    )

Khung hiển thị web trên iOS

Kể từ iOS 17, bạn có thể thêm cấu hình proxy vào WKWebView bằng cách sử dụng thuộc tính 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)

Nâng cao: Tạo thư viện tuỳ chỉnh cho thiết bị di động

Đối với các trường hợp sử dụng nâng cao, bạn có thể tạo thư viện dành cho thiết bị di động của riêng mình:

  1. Tạo thư viện Go: Phát triển một gói Go bao gồm các chức năng SDK bắt buộc.
  2. Tạo thư viện dành cho thiết bị di động: Sử dụng gomobile bind để tạo Thư viện Android (AAR) và Khung Apple. Ví dụ:
  3. Tích hợp vào ứng dụng: Thêm thư viện đã tạo vào ứng dụng dành cho thiết bị di động.