Topik ini menjelaskan cara mengimplementasikan koneksi IP langsung saat mengintegrasikan HTTPDNS ke dalam aplikasi iOS. Untuk informasi selengkapnya tentang integrasi HTTPDNS di iOS, lihat Integrasi iOS SDK.
1. Pendahuluan
Dalam lingkungan jaringan seluler, isu seperti DNS hijacking dan polusi cache DNS lokal sering menghambat resolusi nama domain yang akurat, sehingga menyebabkan kegagalan permintaan jaringan. Untuk mengatasi hal tersebut, HTTPDNS Alibaba Cloud menyediakan layanan resolusi nama domain rekursif yang andal. Layanan ini membantu aplikasi seluler menghindari risiko potensial dari DNS lokal serta meningkatkan tingkat keberhasilan dan stabilitas permintaan jaringan.
Namun, penggunaan HTTPDNS pada platform iOS mengharuskan Anda mengganti nama domain asli dalam permintaan dengan alamat IP yang telah diselesaikan sebelum menginisiasi permintaan tersebut. Hal ini dapat menimbulkan masalah tambahan, terutama dalam skenario kompleks seperti HTTPS dan Server Name Indication (SNI). Oleh karena itu, sebelum mengintegrasikan HTTPDNS, Anda harus memahami secara komprehensif potensi masalah beserta solusi yang tersedia guna memastikan penggunaan HTTPDNS yang aman dan tepat dalam bisnis Anda.
Topik ini menjelaskan masalah utama yang mungkin Anda temui saat menggunakan HTTPDNS di iOS, serta menyediakan solusi integrasi untuk berbagai skenario lengkap dengan kelebihan dan kekurangannya, guna membantu developer menyelesaikan integrasi HTTPDNS secara efisien.
2. Masalah saat menggunakan HTTPDNS di iOS
Dalam aplikasi seluler, jika Anda mengganti nama domain dalam URL asli, seperti example.com, dengan alamat IP yang diselesaikan oleh HTTPDNS, Anda sering menghadapi masalah berikut. Permasalahan ini berkaitan erat dengan peran bidang Host pada dua lapisan berbeda dalam protokol HTTPS: lapisan TLS/SSL dan lapisan HTTP.
Lapisan TLS/SSL: Dalam skenario HTTPS, klien pertama-tama melakukan jabat tangan TLS/SSL dan menggunakan Host dari URL untuk menyelesaikan tugas berikut:
Verifikasi sertifikat: Memverifikasi bahwa nama domain pada sertifikat server (Common Name atau Subject Alternative Name) sesuai dengan Host yang diminta.
SNI: Saat membangun koneksi TLS, klien mengirimkan informasi nama domain yang diminta (Host dalam URL) ke server agar server dapat mengembalikan sertifikat yang sesuai.
Lapisan HTTP: Setelah jabat tangan TLS selesai, klien menyertakan bidang
Hostdalam header permintaan HTTP untuk memberi tahu server mengenai situs atau resource spesifik yang diminta. Jika Anda mengganti nama domain dalam URL dengan alamat IP namun tidak mengatur secara manualHostdalam header HTTP, server mungkin tidak dapat mengidentifikasi nama domain aktual yang diakses, sehingga menyebabkan permintaan gagal atau mengembalikan konten yang tidak normal.
Berdasarkan peran Host pada berbagai lapisan tumpukan protokol HTTPS, mengganti nama domain dalam URL dengan alamat IP yang diselesaikan oleh HTTPDNS menyebabkan masalah teknis berikut:
Ketidaksesuaian nama domain dan sertifikat: Untuk permintaan HTTPS, jika Anda langsung menggunakan alamat IP yang diselesaikan oleh HTTPDNS sebagai Host dalam URL, lapisan TLS tidak dapat mencocokkan nama domain sertifikat yang benar (Common Name atau nama domain tambahan SAN), sehingga menyebabkan jabat tangan SSL gagal.
Isu SNI: Dalam skenario SNI, satu alamat IP server dapat dikaitkan dengan sertifikat untuk beberapa nama domain. Jika klien tidak mengirimkan informasi nama domain yang benar selama fase jabat tangan SSL dan hanya mengirimkan alamat IP, server tidak dapat mengembalikan sertifikat yang sesuai dengan nama domain tersebut, sehingga jabat tangan SSL gagal. Karena API jaringan tingkat tinggi di iOS, seperti
NSURLSession, tidak menyediakan antarmuka untuk mengonfigurasi SNI secara langsung, isu SNI sering kali sulit diselesaikan dengan metode sederhana.Header Host dan pengalamatan layanan: Jika Anda mengganti nama domain dalam URL dengan alamat IP tetapi lupa mengatur secara eksplisit
Hostdalam header permintaan HTTP ke nama domain asli, sisi server mungkin tidak dapat mengidentifikasi situs atau resource spesifik pada lapisan HTTP. Misalnya, dalam skenario CDN, server bergantung pada bidang Host untuk mendistribusikan konten yang benar. Jika Host berupa alamat IP, layanan menjadi tidak normal.Pilihan library jaringan dasar: API bawaan tingkat tinggi di iOS, seperti
NSURLSession, memiliki ekstensibilitas terbatas untuk menyesuaikan SNI atau verifikasi sertifikat manual. Jika developer ingin menangani SNI atau memodifikasi logika jabat tangan TLS, mereka perlu menggunakan antarmuka tingkat rendah, sepertiCFNetworkataulibcurl. Namun, hal ini meningkatkan biaya pengembangan dan maintenance.
Secara ringkas, mengganti langsung nama domain dalam URL dengan alamat IP yang diselesaikan oleh HTTPDNS memengaruhi verifikasi sertifikat dan transmisi SNI pada lapisan TLS dalam skenario HTTPS, serta dapat menyebabkan informasi header Host menjadi tidak normal pada lapisan HTTP. Oleh karena itu, saat mengintegrasikan HTTPDNS di iOS, Anda harus menangani masalah ini secara tepat sasaran untuk memastikan keandalan dan keamanan permintaan jaringan.
3. Solusi integrasi untuk skenario HTTP biasa dan HTTPS (non-SNI)
Untuk skenario HTTP biasa atau HTTPS + non-SNI, Anda umumnya dapat terus menggunakan NSURLSession bawaan sistem dan logika permintaan jaringan reguler dengan beberapa penyesuaian yang relatif sederhana. Perlu diperhatikan bahwa skenario HTTP biasa tidak melibatkan jabat tangan TLS atau verifikasi sertifikat. Sebaliknya, skenario HTTPS + non-SNI memerlukan verifikasi sertifikat, yang dapat Anda tangani dengan melakukan hook proses verifikasi dalam NSURLSession.
3.1 Skenario HTTP biasa
Untuk permintaan HTTP biasa, tidak ada jabat tangan TLS/SSL atau verifikasi sertifikat dalam tautan jaringan. Oleh karena itu, operasi inti untuk mengintegrasikan HTTPDNS hanya dilakukan pada lapisan HTTP:
Ganti Host dalam URL permintaan dengan alamat IP yang diselesaikan oleh HTTPDNS.
Sebagai contoh, jika URL permintaan asli adalah
http://example.com/apidan HTTPDNS menyelesaikannya ke alamat IP1.2.3.4, Anda dapat mengubah URL menjadihttp://1.2.3.4/api.
Atur secara eksplisit
Hostdalam header HTTP ke nama domain asli.Jika Anda menggunakan
NSMutableURLRequest, Anda dapat menambahkanrequest.allHTTPHeaderFields[@"Host"] = @"example.com";ke header permintaan. Hal ini memastikan bahwa server dapat mengidentifikasi nama domain yang benar pada lapisan aplikasi.
Kelebihan: Implementasi sederhana. Hanya memerlukan penggantian Host dan pengaturan header dalam permintaan HTTP yang sudah ada, sehingga upaya pengembangan rendah.
Kekurangan: Hanya berlaku untuk protokol HTTP biasa. Tidak dapat menyelesaikan isu verifikasi sertifikat dan terkait SNI dalam skenario HTTPS.
3.2 Skenario HTTPS (non-SNI)
Untuk situs HTTPS yang tidak menggunakan mekanisme SNI atau hanya mencakup beberapa nama domain tetap (sertifikat hanya mencakup domain-domain tersebut), Anda dapat mengintegrasikan HTTPDNS dan melakukan verifikasi sertifikat pada lapisan NSURLSession sebagai berikut:
Ganti Host dalam URL permintaan dengan alamat IP yang diselesaikan oleh HTTPDNS.
Sebagai contoh, jika URL permintaan asli adalah
https://example.com/apidan HTTPDNS menyelesaikannya ke alamat IP1.2.3.4, Anda dapat mengubah URL menjadihttps://1.2.3.4/api.
Atur secara eksplisit
Hostdalam header HTTP ke nama domain asli.Demikian pula, Anda dapat mengatur
request.allHTTPHeaderFields[@"Host"] = @"example.com";dalamNSMutableURLRequest.
Hook proses verifikasi sertifikat
Karena ini adalah permintaan HTTPS, verifikasi sertifikat diperlukan selama jabat tangan TLS. Pada titik ini, jika Anda langsung menggunakan alamat IP sebagai Host untuk pemeriksaan, akan terjadi isu ketidaksesuaian nama domain dan sertifikat.
Dalam metode callback
NSURLSessionDelegateURLSession:didReceiveChallenge:completionHandler:, saat Anda memverifikasiserverTrustyang diperoleh dari sistem, Anda dapat mengganti alamat IP dengan nama domain asli (example.com). Hal ini memungkinkan verifikasi sertifikat berhasil.Contoh kode:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSString *originalHost = [self getOriginalHostFromRequest:task.originalRequest]; SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; if ([self evaluateServerTrust:serverTrust forDomain:originalHost]) { // Sertifikat telah diverifikasi. NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); } else { // Verifikasi sertifikat gagal. Gunakan handler default. completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } } else { completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } } - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain { // Buat kebijakan verifikasi sertifikat. NSMutableArray *policies = [NSMutableArray array]; if (domain) { [policies addObject:(__bridge_transfer id) SecPolicyCreateSSL(true, (__bridge CFStringRef) domain)]; } else { [policies addObject:(__bridge_transfer id) SecPolicyCreateBasicX509()]; } // Ikat kebijakan verifikasi ke sertifikat server. SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef) policies); // Evaluasi apakah serverTrust saat ini dipercaya. Apple merekomendasikan bahwa serverTrust dapat diverifikasi jika hasilnya kSecTrustResultUnspecified atau kSecTrustResultProceed. Untuk informasi lebih lanjut, lihat https://developer.apple.com/library/ios/technotes/tn2232/_index.html. // Untuk informasi lebih lanjut tentang SecTrustResultType, lihat SecTrust.h. SecTrustResultType result; SecTrustEvaluate(serverTrust, &result); return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); }
Kelebihan:
Tidak perlu mengimpor library pihak ketiga tambahan. Anda dapat langsung menggunakan
NSURLSessiondan logika verifikasi sertifikat bawaan sistem.Biaya implementasi relatif terjangkau, cocok untuk skenario yang tidak melibatkan SNI atau hanya memerlukan beberapa sertifikat nama domain.
Kekurangan:
Tidak dapat menangani skenario SNI. Jika beberapa nama domain dideploy pada alamat IP yang sama, seperti dalam skenario CDN, jabat tangan tetap gagal karena server mengembalikan sertifikat yang salah.
4. Solusi integrasi untuk skenario HTTPS (SNI)
Untuk skenario SNI (satu IP dengan beberapa nama domain HTTPS), solusi sederhana berbasis NSURLSession tidak dapat mengirimkan informasi nama domain yang benar selama fase jabat tangan SSL, sehingga menyebabkan jabat tangan gagal. Untuk menyelesaikan masalah ini, Anda perlu memodifikasi atau menentukan bidang SNI pada level Socket yang lebih rendah. Berikut adalah tiga metode umum:
4.1 Implementasi NSURLProtocol kustom
iOS memungkinkan developer untuk mengintersepsi permintaan jaringan yang diinisiasi oleh sistem dengan mewarisi NSURLProtocol. Anda kemudian dapat mengimplementasikan logika permintaan HTTP/HTTPS pada level yang lebih rendah menggunakan antarmuka seperti CFNetwork atau NSInputStream/NSOutputStream:
Mencegat permintaan
Dalam metode
canInitWithRequest:, Anda dapat menentukan apakah akan mengintersepsi permintaan saat ini.Dalam metode
startLoading, Anda dapat mengganti nama domain dalam URL permintaan asli dengan alamat IP dan menyimpan nama domain asli untuk verifikasi sertifikat serta pengaturan SNI selanjutnya.
Tetapkan SNI
Menggunakan API terkait
CFStreamatau antarmukaSecureTransport, Anda dapat menentukankCFStreamSSLPeerNamesebagai nama domain asli. Hal ini memastikan bahwa lapisan dasar menyertakan informasi nama domain yang benar selama fase jabat tangan SSL.
Verifikasi sertifikat
Anda dapat mengeksekusi proses verifikasi sertifikat secara manual untuk memastikan bahwa nama domain dalam sertifikat sesuai dengan nama domain asli.
Kelebihan: Tidak bergantung pada library pihak ketiga. Sepenuhnya berbasis API sistem tingkat rendah dan menawarkan fleksibilitas tinggi.
Kekurangan: Biaya implementasi tinggi. Developer perlu menangani secara manual pengalihan, cookie, caching, encoding, dan statistik trafik. Tidak mendukung reuse koneksi, sehingga performanya rata-rata. Risiko maintenance juga tinggi dan memerlukan adaptasi ekstra saat sistem atau lingkungan jaringan ditingkatkan.
Untuk contoh referensi, lihat implementasi sampel HttpDnsNSURLProtocolImpl.m yang disediakan Alibaba Cloud dalam httpdns_ios_demo. Anda dapat memodifikasi atau menggunakan ulang sesuai kebutuhan.
4.2 Menggunakan libcurl untuk permintaan jaringan
libcurl adalah library jaringan lintas platform yang diimplementasikan dalam C. Library ini mendukung pengaturan manual bidang SNI untuk mengirimkan informasi nama domain yang benar selama jabat tangan SSL, sehingga menyelesaikan verifikasi sertifikat dalam skenario di mana beberapa nama domain berbagi alamat IP yang sama. Proses umumnya sebagai berikut:
Selesaikan nama domain untuk mendapatkan alamat IP yang sesuai.
Sebagai contoh, Anda dapat menggunakan operasi API HTTPDNS seperti
resolveHostSyncNonBlocking:untuk mendapatkan alamat IP dari nama domain target.
Konfigurasikan pemetaan SNI dan IP.
Gunakan
CURLOPT_RESOLVEatau API lain untuk menambahkan pemetaan "domain:port:IP_yang_diselesaikan" ke cache DNS internal curl.Lanjutkan menggunakan nama domain asli untuk
CURLOPT_URL. Hal ini memastikan bahwa nama domain yang benar disertakan dalam jabat tangan TLS.
Verifikasi sertifikat.
libcurlmengaktifkan verifikasi sertifikat secara default. Anda juga dapat menggunakan callback yang sesuai untuk pemeriksaan sertifikat yang lebih detail sesuai kebutuhan.
Bagian kode inti berikut (pseudocode) menunjukkan cara menggunakan hasil resolusi HTTPDNS dengan libcurl untuk menyelesaikan permintaan di iOS:
CURL *curl_handle = curl_easy_init();
if (curl_handle) {
// Misalnya, dapatkan IP = 1.2.3.4 dari HTTPDNS, nama domain target = example.com, port = 443
struct curl_slist *dnsResolve = NULL;
dnsResolve = curl_slist_append(dnsResolve, "example.com:443:1.2.3.4");
// Atur pemetaan domain-ke-IP.
curl_easy_setopt(curl_handle, CURLOPT_RESOLVE, dnsResolve);
// Lanjutkan menggunakan nama domain asli sebagai URL.
curl_easy_setopt(curl_handle, CURLOPT_URL, "https://example.com");
// Aktifkan verifikasi SSL.
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2L);
// Inisiasi permintaan.
CURLcode res = curl_easy_perform(curl_handle);
// Periksa hasilnya.
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() gagal: %s\n", curl_easy_strerror(res));
}
// Bersihkan.
curl_easy_cleanup(curl_handle);
curl_slist_free_all(dnsResolve);
}Kelebihan:
Matang dan stabil, mendukung berbagai protokol, dan dapat beradaptasi dengan lingkungan jaringan kompleks. Memiliki dukungan bawaan untuk skenario SNI.
Kekurangan:
Memerlukan kompilasi
libcurlke dalam proyek iOS dan menggunakan antarmuka C murni, yang memiliki kurva pembelajaran bagi developer Objective-C/Swift.Juga mengharuskan Anda menangani alur permintaan kustom atau mengenkapsulasi logika HTTP, seperti untuk cookie, pengalihan, dan caching.
4.3 Menggunakan EMASCurl
Untuk menurunkan hambatan penggunaan langsung libcurl di iOS, tim EMAS Alibaba Cloud menyediakan library EMASCurl. Library ini mengenkapsulasi libcurl dan mendukung integrasi langsung dengan HTTPDNS.
Instalasi dan intersepsi
Library ini menyediakan dua metode penggunaan utama: 1) Mengintersepsi
NSURLSessionyang dibuat denganNSURLSessionConfigurationtertentu. 2) Mengintersepsi[NSURLSession sharedSession]global sistem.Untuk informasi lebih lanjut tentang antarmuka API, lihat file README di GitHub.
Integrasi dengan HTTPDNS
Anda dapat mengimplementasikan protokol
EMASCurlProtocolDNSResolveruntuk meneruskan hasil resolusi HTTPDNS ke EMASCurl.Dalam metode
resolveDomain:, Anda dapat memanggil[HttpDnsService resolveHostSyncNonBlocking:]untuk mendapatkan alamat IP, lalu mengembalikan alamat IP tersebut ke EMASCurl untuk menyelesaikan pengaturan SNI dan pengiriman permintaan selanjutnya.
Verifikasi sertifikat
EMASCurl bergantung pada mekanisme verifikasi sertifikat
libcurl. Developer juga dapat memperluas atau menyesuaikan verifikasi sertifikat melalui antarmuka yang sesuai untuk memenuhi kebutuhan bisnis.
Dukungan HTTP/3
EMASCurl menyediakan EMASCurl/HTTP3, versi terenkapsulasi berbasis
libcurlyang mendukung QUIC. Developer dapat mengintegrasikannya sesuai kebutuhan untuk menggunakan kemampuan HTTP/3 tanpa adaptasi tambahan.
Kelebihan:
Mengenkapsulasi kemampuan dasar
libcurl, dengan API yang lebih familiar bagi developer iOS.Mudah diintegrasikan dengan HTTPDNS melalui mekanisme DNS Hook.
Menyelesaikan isu transmisi nama domain dan verifikasi sertifikat dalam skenario SNI serta mengurangi biaya integrasi.
Mendukung HTTP/3 secara langsung, tanpa perlu kompilasi dan adaptasi sendiri.
Kekurangan:
Bergantung pada library pihak ketiga (EMASCurl dan libcurl), sehingga Anda perlu memperhatikan kompatibilitas, pembaruan versi, dan faktor lainnya.
Untuk atribut HTTP yang sangat kompleks atau kebutuhan kustom, Anda mungkin tetap perlu membaca dan memahami enkapsulasi internal EMASCurl untuk memastikan ketersediaan bisnis.
Saat mengintegrasikan EMASCurl, Anda harus menguji atribut HTTP/HTTPS umum, seperti pengalihan, cookie, dan permintaan konkuren, untuk memastikan bahwa atribut tersebut memenuhi kebutuhan bisnis Anda.
Jika bisnis Anda memiliki persyaratan keamanan atau performa jaringan yang ketat, Anda harus mengevaluasi performa EMASCurl pada versi sistem iOS saat ini.
Anda harus memastikan bahwa permintaan dan jabat tangan dapat diselesaikan secara normal di berbagai lingkungan jaringan, seperti Wi-Fi, jaringan seluler, dan proxy.
5. Kesimpulan
Anda dapat memilih solusi berdasarkan kebutuhan bisnis Anda, seperti apakah perlu mendukung SNI, beberapa nama domain, dan verifikasi sertifikat. Tabel berikut membandingkan berbagai solusi:
Solusi | Skenario | Kelebihan | Kekurangan |
Hanya atur Host dan Header | Skenario HTTP biasa | - Biaya integrasi terendah | - Hanya untuk protokol HTTP biasa |
NSURLSession + Hook verifikasi sertifikat (Masih memerlukan pengaturan Host dan Header) | Skenario HTTPS (non-SNI) | - Biaya integrasi rendah - Menggunakan API sistem, tidak perlu library tambahan | - Tidak mendukung SNI |
NSURLProtocol Kustom | Semua skenario Memerlukan kontrol tingkat rendah yang lebih fleksibel | - Sepenuhnya berbasis API sistem tingkat rendah - Fleksibilitas tinggi | - Biaya pengembangan dan pemeliharaan tinggi - Tidak ada penggunaan ulang koneksi, kinerja rata-rata - Memerlukan penanganan manual pengalihan, cookie, caching, encoding, dan kasus khusus lainnya |
libcurl | Semua skenario Lintas platform atau alur HTTP kustom | - Matang dan stabil - Mendukung pengaturan bidang SNI dan berbagai protokol - Ekstensi verifikasi sertifikat yang fleksibel | - Antarmuka C memiliki kurva pembelajaran bagi developer Objective-C/Swift - Memerlukan enkapsulasi manual untuk cookie, pengalihan, caching, dll. |
EMASCurl | Semua skenario Untuk integrasi sederhana di iOS | - Enkapsulasi libcurl yang baik - Integrasi sederhana dengan HTTPDNS - Mengimplementasikan SNI dan verifikasi sertifikat - Mendukung HTTP/3 | - Bergantung pada library pihak ketiga, perlu memperhatikan kompatibilitas dan pembaruan - Persyaratan khusus mungkin memerlukan pengembangan kustom dengan membaca kode sumber |
Anda dapat mengevaluasi solusi-solusi ini berdasarkan kebutuhan multi-domain, persyaratan keamanan jaringan, kompatibilitas, biaya maintenance, dan penerimaan terhadap library pihak ketiga dalam bisnis Anda. Pilihlah solusi integrasi yang paling sesuai dan uji secara menyeluruh ketersediaan serta keamanan permintaan jaringan sebelum merilisnya.