DNS拦截和处理
常见 DNS 拦截方式
拦截方式 | 影响 |
---|---|
ISP 劫持 | 网络运营商强制解析特定域名,返回错误地址(如广告页面) |
DNS 污染 | 某些 DNS 服务器返回错误 IP,导致无法访问目标网站 |
企业防火墙 | 组织内的网络策略屏蔽某些 DNS 请求 |
GFW(防火长城) | 阻止访问特定域名,返回错误 IP 或超时 |
表现:
- APP 网络请求失败(如 API 请求超时、域名解析失败)
- 页面无法加载(WebView 或 Safari 加载特定网站失败)
- DNS 查询时间长(影响 APP 启动速度)
iOS DNS 优化方案
方案 1:使用自定义 DNS 服务器
可以切换至 Google DNS、Cloudflare DNS 或 DoH(DNS over HTTPS) 进行更安全的解析:
let config = URLSessionConfiguration.default config.connectionProxyDictionary = [ kCFNetworkProxiesHTTPEnable: true, kCFNetworkProxiesHTTPProxy: "8.8.8.8", // Google DNS kCFNetworkProxiesHTTPPort: 53 ] let session = URLSession(configuration: config)
推荐 DNS 服务器
- Google DNS:
8.8.8.8
/8.8.4.4
- Cloudflare DNS:
1.1.1.1
/1.0.0.1
- Quad9 DNS:
9.9.9.9
方案 2:使用 DoH(DNS over HTTPS)
iOS 14+ 支持 DoH(加密 DNS 请求),可以有效防止 DNS 劫持:
let dohURL = URL(string: "https://dns.google/dns-query")! var request = URLRequest(url: dohURL) request.setValue("application/dns-json", forHTTPHeaderField: "Accept") let task = URLSession.shared.dataTask(with: request) { data, response, error in if let data = data { print("DoH Response: \(String(data: data, encoding: .utf8) ?? "")") } } task.resume()
优点
- 防止 DNS 劫持(使用 HTTPS 加密请求)
- 提高解析速度(基于 HTTP/3 的 DNS 查询更快)
方案 3:使用 getaddrinfo
预解析 DNS
iOS 默认在 每次请求时解析 DNS,可以使用 getaddrinfo
预解析 域名的 IP 地址,提高网络请求速度:
import Foundation func resolveHost(_ host: String) -> [String] { var results: [String] = [] var hints = addrinfo( ai_flags: AI_DEFAULT, ai_family: AF_INET, ai_socktype: SOCK_STREAM, ai_protocol: IPPROTO_TCP ) var info: UnsafeMutablePointer<addrinfo>? if getaddrinfo(host, nil, &hints, &info) == 0 { var ptr = info while ptr != nil { if let sa = ptr?.pointee.ai_addr { var ipBuffer = [CChar](repeating: 0, count: Int(INET6_ADDRSTRLEN)) inet_ntop(AF_INET, sa, &ipBuffer, socklen_t(INET6_ADDRSTRLEN)) results.append(String(cString: ipBuffer)) } ptr = ptr?.pointee.ai_next } freeaddrinfo(info) } return results } let ipList = resolveHost("example.com") print("Resolved IPs: \(ipList)")
优势
- 减少 DNS 查询时间
- 提升 APP 启动速度
- 避免被劫持时切换备用 IP
方案 4:使用 CFNetwork
API 强制 IP 直连
如果你的 APP 遭遇 DNS 劫持,可以 直接连接 IP,而非域名:
let url = URL(string: "http://93.184.216.34")! // example.com 的 IP let request = URLRequest(url: url) URLSession.shared.dataTask(with: request) { data, response, error in if let data = data { print("Response: \(String(data: data, encoding: .utf8) ?? "")") } }.resume()
优势
- 绕过 DNS 劫持
- 适用于 CDN 加速失败的情况
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架