常见 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
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 加速失败的情况