在 Swift 中使用代理
Swift 中的代理
Swift 是开发 iOS 和 macOS 应用的主要语言。在 Swift 中使用代理主要通过 URLSession(高层 API)、Network 框架(底层)以及系统设置来实现。
搭配代理的 URLSession
通过 URLSessionConfiguration 配置
import Foundation
let config = URLSessionConfiguration.default
// HTTP 代理配置
config.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: "proxy_ip",
kCFNetworkProxiesHTTPPort: 8080,
kCFNetworkProxiesHTTPSEnable: true,
kCFNetworkProxiesHTTPSProxy: "proxy_ip",
kCFNetworkProxiesHTTPSPort: 8080
]
let session = URLSession(configuration: config)
let url = URL(string: "https://httpbin.org/ip")!
let task = session.dataTask(with: url) { data, response, error in
if let data = data, let body = String(data: data, encoding: .utf8) {
print(body)
}
}
task.resume()
SOCKS 代理
config.connectionProxyDictionary = [
kCFStreamPropertySOCKSProxyHost: "proxy_ip",
kCFStreamPropertySOCKSProxyPort: 1080,
kCFStreamPropertySOCKSVersion: kCFStreamSocketSOCKSVersion5
]
带认证
config.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: "proxy_ip",
kCFNetworkProxiesHTTPPort: 8080,
kCFProxyUsernameKey: "username",
kCFProxyPasswordKey: "password"
]
系统代理设置
自动使用
默认情况下,URLSession 会使用系统代理:
let config = URLSessionConfiguration.default
// 默认使用系统代理
let session = URLSession(configuration: config)
如果用户已在 iOS/macOS 系统设置中配置了代理,URLSession 会自动使用它们。
PAC 文件
config.connectionProxyDictionary = [
kCFNetworkProxiesProxyAutoConfigEnable: true,
kCFNetworkProxiesProxyAutoConfigURLString: "http://example.com/proxy.pac"
]
处理代理认证质询
当代理要求认证时,URLSession 会调用其 delegate:
class ProxyDelegate: NSObject, URLSessionDelegate {
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic
&& challenge.protectionSpace.isProxy {
let credential = URLCredential(
user: "username",
password: "password",
persistence: .forSession
)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
let delegate = ProxyDelegate()
let session = URLSession(configuration: config, delegate: delegate, delegateQueue: nil)
Network 框架(NWConnection)
用于 iOS 12+ / macOS 10.14+ 上的底层网络操作:
import Network
let proxyConfig = NWProtocolTLS.Options()
let params = NWParameters.tls
// 通过 NWEndpoint 配置代理
let proxyEndpoint = NWEndpoint.hostPort(
host: NWEndpoint.Host("proxy_ip"),
port: NWEndpoint.Port(rawValue: 8080)!
)
// 创建连接
let connection = NWConnection(
host: "httpbin.org",
port: 443,
using: params
)
connection.stateUpdateHandler = { state in
switch state {
case .ready:
print("Connected")
case .failed(let error):
print("Failed: \(error)")
default:
break
}
}
connection.start(queue: .global())
搭配代理的 Alamofire
Alamofire 是一个流行的 Swift HTTP 库:
import Alamofire
let config = URLSessionConfiguration.default
config.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: "proxy_ip",
kCFNetworkProxiesHTTPPort: 8080
]
let session = Session(configuration: config)
session.request("https://httpbin.org/ip").response { response in
if let data = response.data, let body = String(data: data, encoding: .utf8) {
print(body)
}
}
iOS 特有事项
iOS 中的 VPN 与代理
iOS 支持通过以下方式配置代理:
1. 系统设置(设置 → Wi-Fi → HTTP 代理)
2. MDM 描述文件
3. NEProxySettings(Network Extension 框架)
Network Extension
要在 iOS 上创建功能完整的代理应用,请使用 NETransparentProxyProvider:
import NetworkExtension
class ProxyProvider: NETransparentProxyProvider {
override func startProxy(options: [String: Any]?, completionHandler: @escaping (Error?) -> Void) {
// 代理配置
completionHandler(nil)
}
override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
// 处理新连接
return true
}
}
这需要 Apple 授予的 entitlement,适合 Enterprise/MDM 方案。
async/await(Swift 5.5+)
func fetchViaProxy() async throws -> String {
let config = URLSessionConfiguration.default
config.connectionProxyDictionary = [
kCFNetworkProxiesHTTPEnable: true,
kCFNetworkProxiesHTTPProxy: "proxy_ip",
kCFNetworkProxiesHTTPPort: 8080
]
let session = URLSession(configuration: config)
let url = URL(string: "https://httpbin.org/ip")!
let (data, _) = try await session.data(from: url)
return String(data: data, encoding: .utf8) ?? ""
}
// 用法
Task {
let ip = try await fetchViaProxy()
print(ip)
}
结论
Swift 提供了灵活的代理使用工具:URLSession 适合高层任务,Network 框架用于底层控制,Network Extension 用于创建代理应用。对于大多数场景,搭配 connectionProxyDictionary 的 URLSession 是最佳选择。
