Swift'te proxy kullanımı, iOS ve macOS geliştiricilerinin URLSession üzerinden ağ trafiğini bir ara sunucuya yönlendirmesini gerektiren yaygın bir görevdir. İster bölge kilitli bir API'ye erişmek, ister SERP takibi yapmak, ister bir web scraping iş akışı kurmak isteyin, URLSessionConfiguration.connectionProxyDictionary anahtarı doğru yapılandırılmadığında kimlik doğrulama hataları, TLS sorunları ve IP engelleri kaçınılmazdır. Bu rehber, ProxyHat residential proxy'lerini Swift'te sıfırdan üretim seviyesine kadar nasıl kullanacağınızı gösterir.
Apple'ın CFNetwork katmanı proxy kimlik doğrulamasını her zaman tutarlı şekilde ele almaz; kCFProxyUsernameKey ve kCFProxyPasswordKey anahtarları URLSession ile güvenilmezdir. Bu nedenle bu rehber, manuel Proxy-Authorization başlığı ve URLSessionDelegate tabanlı 407 challenge yakalama yaklaşımına odaklanır. Aşağıdaki tüm örnekler gate.proxyhat.com:8080 (HTTP) ve gate.proxyhat.com:1080 (SOCKS5) ağ geçitlerini kullanır.
Swift'te Proxy Kullanımı: Teknik Bağlam
URLSession, proxy yapılandırmasını URLSessionConfiguration.connectionProxyDictionary üzerinden alır. Bu sözlük, Apple'ın dokümantasyonuna göre CFNetworkProxies anahtarlarıyla doldurulur. HTTP için kCFNetworkProxiesHTTPEnable, kCFNetworkProxiesHTTPProxy ve kCFNetworkProxiesHTTPPort; HTTPS için kCFNetworkProxiesHTTPSEnable, kCFNetworkProxiesHTTPSProxy ve kCFNetworkProxiesHTTPSPort kullanılır.
Sorun şu: URLSession, proxy kimlik doğrulamasını URLSessionDelegate'in urlSession(_:didReceive:completionHandler:) yöntemiyle ele alır, ancak connectionProxyDictionary içine yerleştirilen kCFProxyUsernameKey/kCFProxyPasswordKey anahtarları tüm platform sürümlerinde tutarlı çalışmaz. Apple'ın URLSessionDelegate referansı, kimlik doğrulama challenge'larının delegate üzerinden işlenmesini önerir. Pratikte en güvenilir yöntem, istek başına Proxy-Authorization: Basic başlığı eklemek veya 407 yanıtı yakalandığında delegate içinde kimlik bilgisi sağlamaktır.
Residential proxy'ler, gerçek İnternet Servis Sağlayıcı (ISP) IP'lerinden geldiği için veri merkezi IP'lerini engelleyen uç noktalar tarafından daha az tespit edilir. ProxyHat, 100+ lokasyonda residential, mobil ve datacenter proxy'ler sunar; bu rehberde residential tipine odaklanıyoruz.
HTTP/HTTPS Proxy Yapılandırması
Aşağıdaki örnek, gate.proxyhat.com:8080 HTTP proxy'sini URLSessionConfiguration ile yapılandırır ve temel bir GET isteği gönderir. Kimlik doğrulama, Proxy-Authorization başlığı ile manuel yapılır.
import Foundation
func makeProxySession(username: String, password: String) -> URLSession {
let config = URLSessionConfiguration.ephemeral
// HTTP ve HTTPS proxy'sini aynı host:port üzerinden yapılandır
config.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: "gate.proxyhat.com",
kCFNetworkProxiesHTTPPort: 8080,
kCFNetworkProxiesHTTPSEnable: true,
kCFNetworkProxiesHTTPSProxy: "gate.proxyhat.com",
kCFNetworkProxiesHTTPSPort: 8080
]
return URLSession(configuration: config)
}
func proxyAuthorizationHeader(username: String, password: String) -> String {
let credentials = "\(username):\(password)"
let credentialData = credentials.data(using: .utf8)!
let base64 = credentialData.base64EncodedString()
return "Basic \(base64)"
}
func fetchExample() async throws {
// Coğrafi hedefleme ve sticky session kullanıcı adında kodlanır
let username = "user-country-US-city-newyork-session-abc123"
let password = "YOUR_PASSWORD"
let session = makeProxySession(username: username, password: password)
var request = URLRequest(url: URL(string: "https://httpbin.org/ip")!)
request.setValue(
proxyAuthorizationHeader(username: username, password: password),
forHTTPHeaderField: "Proxy-Authorization"
)
request.setValue("Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)",
forHTTPHeaderField: "User-Agent")
let (data, response) = try await session.data(for: request)
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
throw URLError(.badServerResponse)
}
print(String(data: data, encoding: .utf8) ?? "")
}
Task { try await fetchExample() }
Bu örnekte kullanıcı adı user-country-US-city-newyork-session-abc123 biçimindedir. ProxyHat, ülke, şehir ve session parametrelerini kullanıcı adı alanında kodlanmış olarak kabul eder. session-abc123 aynı IP'nin istekler arasında korunmasını sağlar (sticky session); bu, oturum tabanlı uç noktalar için kritiktir.
407 Challenge için URLSessionDelegate
Proxy-Authorization başlığı çoğu durumda yeterlidir, ancak bazı proxy sunucuları önce 407 döndürür. Bu durumda bir URLSessionDelegate implementasyonu gerekir:
import Foundation
final class ProxyAuthDelegate: NSObject, URLSessionDelegate {
let username: String
let password: String
init(username: String, password: String) {
self.username = username
self.password = password
}
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
// Proxy kimlik doğrulama challenge'ını yakala
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPProxy ||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPSProxy {
let credential = URLCredential(
user: username,
password: password,
persistence: .forSession
)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
func fetchWithDelegate() async throws {
let username = "user-country-DE-city-berlin-session-def456"
let password = "YOUR_PASSWORD"
let config = URLSessionConfiguration.ephemeral
config.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: "gate.proxyhat.com",
kCFNetworkProxiesHTTPPort: 8080,
kCFNetworkProxiesHTTPSEnable: true,
kCFNetworkProxiesHTTPSProxy: "gate.proxyhat.com",
kCFNetworkProxiesHTTPSPort: 8080
]
let delegate = ProxyAuthDelegate(username: username, password: password)
let session = URLSession(configuration: config, delegate: delegate, delegateQueue: nil)
let request = URLRequest(url: URL(string: "https://httpbin.org/ip")!)
let (data, _) = try await session.data(for: request)
print(String(data: data, encoding: .utf8) ?? "")
}
Her iki yöntemi birlikte kullanmak en güvenli yaklaşımdır: başlık proaktif kimlik doğrulama sağlar, delegate ise 407 challenge'ı yedek olarak ele alır.
SOCKS5 Proxy Yapılandırması (Port 1080)
ProxyHat ayrıca gate.proxyhat.com:1080 üzerinde SOCKS5 destekler. SOCKS5, HTTP proxy başlıklarını eklemeden TCP düzeyinde tünel sağlar; bu, bazı TLS sıkı uç noktalar için daha temizdir. Swift'te SOCKS5 için kCFStreamPropertySOCKSProxy* anahtarları kullanılır:
import Foundation
func makeSocks5Session(username: String, password: String) -> URLSession {
let config = URLSessionConfiguration.ephemeral
config.connectionProxyDictionary = [
kCFNetworkProxiesSOCKSEnable: 1,
kCFNetworkProxiesSOCKSProxy: "gate.proxyhat.com",
kCFNetworkProxiesSOCKSPort: 1080,
kCFNetworkProxiesSOCKSVersion: kCFStreamSocketSOCKSVersion5 as Any,
// SOCKS5 kullanıcı adı/şifre kimlik doğrulaması
kCFNetworkProxiesSOCKSUser: username,
kCFNetworkProxiesSOCKSPassword: password
]
return URLSession(configuration: config)
}
func fetchViaSocks5() async throws {
let username = "user-country-JP-session-ghi789"
let password = "YOUR_PASSWORD"
let session = makeSocks5Session(username: username, password: password)
let request = URLRequest(url: URL(string: "https://httpbin.org/ip")!)
let (data, _) = try await session.data(for: request)
print(String(data: data, encoding: .utf8) ?? "")
}
SOCKS5 kimlik doğrulamasında da delegate tabanlı yedek önerilir; ancak SOCKS5 genellikle bağlantı aşamasında kimlik doğrulama gerektirdiğinden başlık eklemeye gerek yoktur. SOCKS5 ile TLS, proxy sunucu tarafından sonlandırılmadan uçtan uca kurulur.
Residential Proxy'ler Neden Gerekli?
Birçok modern API ve web uç noktası, veri merkezi IP aralıklarını (AWS, GCP, Azure, DigitalOcean) otomatik engeller. Örneğin, bazı e-ticaret platformları datacenter IP'lerinden gelen isteklere 403 döndürürken residential IP'lere 200 döndürür. Aşağıdaki tablo proxy tiplerini karşılaştırır:
| Özellik | Residential | Mobil | Datacenter |
|---|---|---|---|
| IP kaynağı | Gerçek ISP | Mobil operatör | Veri merkezi |
| Engellenme riski | Düşük | Çok düşük | Yüksek |
| Hız | Orta (~200-500ms) | Değişken | Yüksek (<100ms) |
| Maliyet | Orta | Yüksek | Düşük |
| Uygun senaryo | Web scraping, SERP | Sosyal medya, yüksek güvenlik | Hızlı API çağrıları |
Residential proxy'ler ayrıca bölge kilitli içeriğe erişim sağlar. Örneğin, yalnızca ABD IP'lerine açık bir API'ye erişmek için user-country-US kullanıcı adı yeterlidir. ProxyHat lokasyonlar sayfasında desteklenen ülkeleri listeler.
Async/Await ile Concurrent Fetch Örneği
Aşağıdaki örnek, URLSession.shared.data(for:) yerine özel yapılandırmalı session kullanır, Codable ile JSON decode eder ve TaskGroup ile eşzamanlı istekler gönderir. Bu, Swift web scraping iş akışlarında çoklu URL'yi paralel çekmek için tipik bir desendir:
import Foundation
struct IPResponse: Codable {
let origin: String
}
struct ProxyConfig {
let host: String
let port: Int
let username: String
let password: String
}
func makeResidentialSession(config: ProxyConfig) -> URLSession {
let sessionConfig = URLSessionConfiguration.ephemeral
sessionConfig.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: config.host,
kCFNetworkProxiesHTTPPort: config.port,
kCFNetworkProxiesHTTPSEnable: true,
kCFNetworkProxiesHTTPSProxy: config.host,
kCFNetworkProxiesHTTPSPort: config.port
]
sessionConfig.timeoutIntervalForRequest = 30
sessionConfig.timeoutIntervalForResource = 60
return URLSession(configuration: sessionConfig)
}
func fetchIP(url: URL, session: URLSession, proxyAuth: String) async throws -> IPResponse {
var request = URLRequest(url: url)
request.setValue(proxyAuth, forHTTPHeaderField: "Proxy-Authorization")
request.setValue("Mozilla/5.0", forHTTPHeaderField: "User-Agent")
let (data, response) = try await session.data(for: request)
guard let http = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
guard (200..<300).contains(http.statusCode) else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(IPResponse.self, from: data)
}
func concurrentFetch() async throws {
let proxyConfig = ProxyConfig(
host: "gate.proxyhat.com",
port: 8080,
username: "user-country-US-city-newyork-session-abc123",
password: "YOUR_PASSWORD"
)
let session = makeResidentialSession(config: proxyConfig)
let auth = proxyAuthorizationHeader(
username: proxyConfig.username,
password: proxyConfig.password
)
let urls = [
URL(string: "https://httpbin.org/ip")!,
URL(string: "https://api.ipify.org?format=json")!,
URL(string: "https://ipinfo.io/json")!
]
let results = try await withThrowingTaskGroup(of: IPResponse?.self) { group in
for url in urls {
group.addTask {
do {
return try await fetchIP(url: url, session: session, proxyAuth: auth)
} catch {
print("Hata: \(error)")
return nil
}
}
}
var collected: [IPResponse] = []
for try await result in group {
if let r = result { collected.append(r) }
}
return collected
}
for r in results {
print("IP: \(r.origin)")
}
}
Bu örnekte 3 URL paralel olarak çekilir. TaskGroup, her bir alt task'ın bağımsız hata yönetimine izin verir; bir URL başarısız olsa bile diğerleri tamamlanır. Üretimde session nesnesini yeniden kullanmak bağlantı havuzunu (connection pooling) korur ve latency'i düşürür.
Üretim İpuçları: TLS, Retry, ATS ve Gizlilik
URLSessionDelegate ile TLS Yönetimi
Bazı senaryolarda self-signed sertifikalı test sunucularına veya MITM proxy'lere bağlanmanız gerekebilir. Aşağıdaki delegate, TLS challenge'larını ele alır (yalnızca debug için, üretimde sertifika doğrulamayı kapatmayın):
import Foundation
final class TLSTolerantDelegate: NSObject, URLSessionDelegate {
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if let trust = challenge.protectionSpace.serverTrust {
// YALNIZCA debug: üretimde .performDefaultHandling kullanın
completionHandler(.useCredential, URLCredential(trust: trust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
Üstel Geri Çekilme ile Retry
Proxy tabanlı isteklerde 429 (Too Many Requests) ve 503 yanıtları yaygındır. Aşağıdaki fonksiyon üstel geri çekilme uygular:
import Foundation
func fetchWithRetry(
url: URL,
session: URLSession,
proxyAuth: String,
maxRetries: Int = 3,
baseDelay: UInt64 = 500_000_000 // 0.5 saniye (nanosaniye)
) async throws -> Data {
var attempt = 0
while true {
do {
var request = URLRequest(url: url)
request.setValue(proxyAuth, forHTTPHeaderField: "Proxy-Authorization")
let (data, response) = try await session.data(for: request)
guard let http = response as? HTTPURLResponse else {
throw URLError(.badServerResponse)
}
if http.statusCode == 429 || http.statusCode == 503 {
if attempt >= maxRetries {
throw URLError(.badServerResponse)
}
let delay = baseDelay * UInt64(pow(2.0, Double(attempt)))
try await Task.sleep(nanoseconds: delay)
attempt += 1
continue
}
guard (200..<300).contains(http.statusCode) else {
throw URLError(.badServerResponse)
}
return data
} catch {
if attempt >= maxRetries { throw error }
let delay = baseDelay * UInt64(pow(2.0, Double(attempt)))
try await Task.sleep(nanoseconds: delay)
attempt += 1
}
}
}
Bu desen, 0.5s, 1.0s, 2.0s aralıklarla üç yeniden deneme yapar. Üretimde jitter eklemek (rastgele ±100ms) thundering herd etkisini azaltır.
App Transport Security (ATS)
Apple'ın ATS politikası, HTTPS olmayan bağlantıları varsayılan olarak engeller. Proxy bağlantısı HTTP olsa bile hedef URL HTTPS ise ATS sorun çıkarmaz. Ancak hedef HTTP ise Info.plist içinde NSAppTransportSecurity > NSAllowsArbitraryLoads ayarlamak gerekir. Yalnızca gerekli domain'ler için NSExceptionDomains kullanmak daha güvenlidir.
Cihaz Üzerinde Gizlilik
iOS 14+ ve macOS'ta NSPrivacyTracking ve App Privacy Report, kullanıcıya hangi domain'lere bağlanıldığını gösterir. Proxy kullanımı, trafiği tek bir host'a (gate.proxyhat.com) yoğunlaştırdığı için gizlilik raporunda daha az domain görünür; ancak bu, kullanıcıyı yanıltmak için kullanılmamalıdır. App Store İnceleme Yönergeleri, veri toplama uygulamalarını açıkça beyan etmenizi gerektirir.
Etik ve Yasal Hususlar
Proxy kullanımı tek başına yasa dışı değildir, ancak nasıl kullanıldığı önemlidir:
- ABD'de CFAA: Computer Fraud and Abuse Act, yetkisiz erişimi suç sayar. Herkese açık verilere erişmek genellikle sorun değildir, ancak ToS ihlali veya erişim kontrolünü atlatma iddiaları risk oluşturur.
hiQ v. LinkedIndavasında mahkeme, herkese açık verilerin kazınmasının CFAA ihlali olmadığına hükmetti, ancak bu emsal teşkil etmez. - AB'de GDPR: Kişisel verilerin işlenmesi için yasal dayanak gerekir. Herkese açık veriler bile kişisel veri içerebilir; IP adresleri GDPR kapsamında kişisel veri sayılır. GDPR.eu ve AB Komisyonu veri koruma sayfası ayrıntılı bilgi sağlar.
- App Store Yönergeleri: Apple, uygulamaların kullanıcıyı gizlice izlememesini ve veri toplama amacını şeffafça belirtmesini gerektirir. Proxy üzerinden veri toplayan bir uygulama, App Privacy Etiketleri'nde bunu doğru yansıtmalıdır.
- Resmi API'ler: Mümkün olduğunda resmi API kullanın. Örneğin, bir platformun resmi API'si varsa scraping yerine onu tercih edin; bu hem yasal riski azaltır hem de daha kararlıdır.
- robots.txt: Hedef sitenin
robots.txtdosyasına saygı gösterin; bu etik bir standarttır ve iyi niyet göstergesidir.
ProxyHat Kurulumu ve İç Bağlantılar
ProxyHat, residential, mobil ve datacenter proxy'leri tek bir ağ geçidinde birleştirir. Fiyatlandırma sayfasında planları inceleyebilir, web scraping kullanım senaryosu sayfasında örnek iş akışlarını görebilirsiniz. ProxyHat ayrıca Python ve Node.js için SDK sunar; bu SDK'lar da aynı gate.proxyhat.com ağ geçidini kullanır, böylece backend ve iOS uygulamanız arasında tutarlı IP davranışı sağlanır. Tam API referansı için ProxyHat dokümantasyonuna bakın.
ProxyHat bağlantı detayları özeti:
- HTTP proxy:
http://USERNAME:PASSWORD@gate.proxyhat.com:8080 - SOCKS5 proxy:
socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080 - Coğrafi hedefleme:
user-country-US-city-newyork - Sticky session:
user-session-abc123
Önemli Çıkarımlar
Swift'te proxy kullanımı için
connectionProxyDictionaryanahtarı yapılandırın, kimlik doğrulamayıProxy-Authorizationbaşlığı ve delegate tabanlı 407 yakalama ile çift katmanlı yapın. Residential proxy'ler veri merkezi IP engelleri için en güvenilir seçenektir. Üretimde retry, TLS ve ATS kurallarına dikkat edin ve her zaman resmi API'leri tercih edin.
kCFProxyUsernameKey/kCFProxyPasswordKeyURLSession ile güvenilmezdir;Proxy-Authorizationbaşlığı kullanın.- Coğrafi hedefleme ve sticky session kullanıcı adına kodlanır:
user-country-US-city-newyork-session-abc123. - SOCKS5 için
kCFStreamPropertySOCKSProxy*anahtarları ve port1080kullanın. - Residential proxy'ler, datacenter IP engellemesini aşmak için en düşük riski sunar.
TaskGroupile paralel istekler ve üstel geri çekilme ile retry üretim standartıdır.- Etik ve yasal sınırlara saygı gösterin: CFAA, GDPR, App Store yönergeleri ve robots.txt.
Sıkça Sorulan Sorular
Swift'te proxy kullanımı nedir?
Swift'te proxy kullanımı, URLSessionConfiguration.connectionProxyDictionary üzerinden HTTP/HTTPS veya SOCKS5 proxy sunucularını yapılandırarak ağ trafiğini ara sunucu üzerinden yönlendirmeyi ifade eder. iOS ve macOS uygulamalarında bölge kilitli içeriğe erişmek, veri toplama iş akışlarında IP engellerini aşmak ve test otomasyonunda coğrafi konum simülasyonu yapmak için kullanılır.
Swift'te proxy kullanımı proxy kullanıcıları için neden önemlidir?
Çünkü URLSession'in proxy kimlik doğrulaması CFNetwork düzeyinde güvenilmez davranabilir ve kCFProxyUsernameKey gibi anahtarlar her zaman işe yaramaz. Doğru yapılandırma, 407 Proxy Authentication Required hatalarını önler, residential proxy'lerle veri merkezi IP engellerini aşar ve coğrafi hedefleme ile bölgesel içeriklere erişim sağlar. Üretim uygulamalarında retry, TLS ve ATS kuralları da kritiktir.
Swift'te proxy kullanımı için hangi proxy tipi en iyisidir?
Genel olarak residential proxy'ler en iyi sonucu verir çünkü gerçek ISP IP'lerini kullanır ve veri merkezi IP'lerini engelleyen uç noktalar tarafından daha az tespit edilirler. Mobil proxy'ler en yüksek güvenilirliği sunar ancak maliyeti yüksektir. Datacenter proxy'ler hızlı ve ucuzdur ancak sık engellenir. Kullanım senaryosuna göre ProxyHat ile ülke ve şehir hedeflemesi yapılabilir.
Swift'te proxy kullanımında engellenmekten nasıl kaçınılır?
Sticky session'lar kullanarak IP rotasyonunu kontrol edin, istek hızını sınırlayın, doğru User-Agent ve başlık gönderin, residential proxy'leri tercih edin ve 403/429 yanıtlarında üstel geri çekilme ile yeniden deneyin. Ayrıca robots.txt ve hedef platformun kullanım şartlarına saygı gösterin, resmi API varsa öncelikle onu kullanın.






