← 返回博客

SOCKS5与SOCKS5h:在Python、curl和Selenium中修复DNS请求泄漏

我们来探讨为什么通过SOCKS5工作时,DNS请求直接从您的IP发送,SOCKS5h有什么不同,以及如何在Python、curl、Selenium和反检测浏览器中修补这个漏洞。

📅2026年10月30日

您已设置 SOCKS5 代理,流量似乎通过它,浏览器中显示的 IP 地址是正确的——但网站仍然可以看到您的真实地区,或者您的提供商开始怀疑。原因几乎总是相同的:DNS 请求直接从您的计算机发送,绕过代理。在本文中,我们将讨论为什么会这样,SOCKS5 与 SOCKS5h 有何不同,以及如何在代码和现成工具中修复此泄漏。

什么是 SOCKS5 及其与 SOCKS5h 的区别

SOCKS5 是一种代理协议,工作在 TCP/UDP 连接层,不会解析数据包内容,这与 HTTP(S) 代理不同。这使得它非常通用:通过 SOCKS5 可以代理几乎任何流量——浏览器、Telegram、BT 客户端、Python 脚本。但经典的 SOCKS5 实现有一个重要的特性:域名解析 (DNS) 默认在客户端执行,也就是在您的计算机上,而不是在代理服务器上。

SOCKS5h 是相同的协议,但带有“h”(主机名)修饰符,指示客户端应用程序不要自行解析域名,而是将其原样发送到代理服务器,代理将代表其执行 DNS 请求。差别在于一个字母,但对匿名性和稳定性的影响是根本性的。

重要的是要理解:SOCKS5h 不是一个单独的协议,而是特定库或应用程序之间关于如何向代理发起请求的约定。代理服务器在这两种情况下的工作方式是相同的,区别仅在于谁发起 DNS 解析——客户端还是服务器。

为什么 DNS 请求绕过代理

当您访问 https://example.com 这样的地址时,在建立连接之前,应用程序必须知道该域名的 IP 地址。这个过程称为 DNS 解析。在通过普通 SOCKS5 工作时,许多库和系统设置通过系统 DNS 服务器执行解析——即您提供商或路由器网络设置中指定的服务器。

结果是一个矛盾的情况:HTTP/TCP 流量通过代理发送,看起来请求来自代理服务器的 IP,而 DNS 请求“example.com 的 IP 是多少?”则直接从您的真实 IP 发送到提供商的 DNS 服务器。这就是 DNS 泄漏。分析网络活动的站点或服务(例如 Facebook、Google、TikTok 的反欺诈系统积极使用这些检测方法)可能会看到连接的 IP 和 DNS 请求来源之间的不一致。

原因在于 SOCKS5 协议最初是作为现成 IP 连接的传输层开发的,而不是用于名称解析。库和工具的开发者不得不单独实现通过隧道传递 DNS 请求的功能——因此 SOCKS5h 出现,明确指示“自己解析域名,而不是我”。

DNS 泄漏在实践中的危险

对于解析器或自动化脚本的开发者来说,DNS 泄漏不是抽象理论,而是导致账户被封锁和禁用的具体原因。我们来分析几个场景。

解析市场和网站。 如果您通过来自所需地区的代理解析 Wildberries、Ozon 或其他资源,但 DNS 请求通过提供商发送,反机器人系统可能会记录地理位置的不一致,并提高会话的可疑性——直到出现验证码或临时封锁代理 IP。

多账户和流量套利。 在使用 Facebook Ads、TikTok Ads 或 Google Ads 处理多个账户时,反欺诈系统会分析多个参数,包括 DNS 指纹。如果几个“不同”账户的 DNS 请求突然通过同一个提供商的 DNS 服务器发送,这会发出将账户合并为一个集群的信号——因此导致链式封禁 (chain-ban)。

在 Selenium/Playwright 中的自动化。 模拟用户在浏览器中操作的脚本尤其脆弱:浏览器本身可能通过操作系统的系统设置解析 DNS,忽略仅为 HTTP 流量指定的代理。最终,所有其他网络指纹都会显示真实位置。

对于大多数这些任务,使用 住宅代理 并在服务器端正确设置 DNS 解析至关重要——这大大降低了通过网络特征被检测的风险。

如何检查是否存在 DNS 泄漏

在修复问题之前,您应该确保它确实存在。以下是一些快速检查的方法。

  1. 通过您的代理连接打开网站 dnsleaktest.com 或 ipleak.net 并运行扩展测试 (Extended test)。
  2. 将结果中的 DNS 服务器列表与您实际的互联网服务提供商进行比较。如果看到提供商而不是代理的数据中心——则确认存在泄漏。
  3. 对于命令行,使用 tcpdump 或 Wireshark,过滤端口 53 (DNS) 的流量——如果数据包直接发送到提供商的服务器,而不是通过代理隧道,则问题在于您这边。
  4. 在 Python 中,可以通过 socket.getaddrinfo() 快速手动检查解析,在启用代理之前和之后——如果 IP 与没有代理的结果相同,则解析在本地进行。

在 Python 中修复 (requests, PySocks, urllib3)

Python 脚本中最常见的错误是将 requests 库与 PySocks 一起使用,而没有明确指定 socks5h 方案。差别在于一个字符,但正是这个字符决定了谁解析域名。

import requests

# 不好:DNS 在本地解析,绕过代理
proxies_leak = {
    "http": "socks5://user:pass@proxy_host:1080",
    "https": "socks5://user:pass@proxy_host:1080",
}

# 好:DNS 在代理服务器上解析
proxies_safe = {
    "http": "socks5h://user:pass@proxy_host:1080",
    "https": "socks5h://user:pass@proxy_host:1080",
}

response = requests.get("https://example.com", proxies=proxies_safe, timeout=10)
print(response.status_code)
print(response.text[:200])

要通过 requests 正确使用 socks5h 方案,需要安装依赖:

pip install "requests[socks]" PySocks

如果您直接使用低级别的 urllib3,示例将如下所示:

from urllib3.contrib.socks import SOCKSProxyManager

proxy = SOCKSProxyManager(
    "socks5h://user:pass@proxy_host:1080",
    num_pools=10
)

response = proxy.request("GET", "https://example.com")
print(response.status)

对于在 aiohttp 上的异步脚本,使用 aiohttp-socks 库,方案的指定方式完全相同:

import aiohttp
from aiohttp_socks import ProxyConnector

connector = ProxyConnector.from_url("socks5h://user:pass@proxy_host:1080")

async def fetch():
    async with aiohttp.ClientSession(connector=connector) as session:
        async with session.get("https://example.com") as resp:
            print(await resp.text())

在 curl 中修复

在 curl 中也有两个不同的标志用于 SOCKS5 代理,二者之间的混淆是 bash 脚本中 DNS 泄漏的经典原因。

# 不好:在本地机器上解析
curl --socks5 proxy_host:1080 https://example.com

# 好:在代理服务器上解析
curl --socks5-hostname proxy_host:1080 https://example.com

# 带授权
curl --socks5-hostname user:pass@proxy_host:1080 https://example.com

--socks5-hostname 标志是其他工具中 socks5h 的直接对应。它告诉 curl:“不要处理 DNS,只需将域名原样传递给代理服务器”。

在 Selenium 和 Playwright 中修复

浏览器自动化的情况更复杂:Chrome 或 Firefox 默认可能通过系统设置解析 DNS,忽略仅在网络请求级别指定的代理。对于 Selenium 和 Chrome,需要明确启用通过代理解析的启动标志。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--proxy-server=socks5://proxy_host:1080")
# 关键标志:通过代理解析 DNS
options.add_argument("--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE proxy_host")

driver = webdriver.Chrome(options=options)
driver.get("https://example.com")

在 Playwright 中情况更简单:如果在浏览器上下文配置中指定了代理,库默认会通过代理解析 DNS。

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={"server": "socks5://proxy_host:1080"}
    )
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()

然而,建议在设置后始终通过 dnsleaktest.com 检查实际行为——不同版本的 Chromium 之间的行为可能会有所不同。

在反检测浏览器中的设置

如果您不是编写代码,而是通过反检测浏览器(如 Dolphin Anty、AdsPower、Multilogin 或 GoLogin)工作——好消息是,大多数浏览器在选择 SOCKS5 协议时已经自动通过代理服务器解析 DNS,而无需手动指定“h”。这是它们相对于自定义脚本的关键优势之一。

然而,值得在实践中检查这一点:在反检测浏览器中打开配置文件,访问 dnsleaktest.com 并在配置文件内运行扩展测试。如果您看到与代理地区相符的 DNS 服务器,而不是您真实的提供商——则设置正确。如果没有,请联系特定反检测浏览器的支持或将代理类型更改为 HTTP(S),因为在这种情况下,DNS 解析的问题并不会那么严重,因为 HTTP 代理始终处理完整的 URL。

对于在 Instagram、TikTok 上创建账户和管理 Facebook Ads 广告账户,移动代理 表现良好——由于移动运营商的动态 IP 轮换,即使在某个链条中发生了小的 DNS 泄漏,它们也不太容易受到反欺诈系统的怀疑。

代理协议比较表

协议 谁解析 DNS 泄漏风险 适用场景
SOCKS5 客户端(您的计算机) 高 仅当 DNS 不重要时(本地测试)
SOCKS5h 代理服务器 低 解析、多个账户、自动化
HTTP/HTTPS 代理 代理服务器(默认) 低 网页流量、浏览器、API 请求

如果您的任务是高速数据收集而不依赖于特定用户地区,请考虑使用 数据中心代理——它们在流量量上更便宜,并且与 SOCKS5h 结合使用时表现良好,适合对速度要求高而非伪装成普通用户的场景。

项目启动前的检查清单

  • 在所有库和配置中使用 socks5h:// 而不是 socks5://。
  • 对于 curl,使用 --socks5-hostname 标志,而不是 --socks5。
  • 在 Selenium 中添加 --host-resolver-rules 标志,或使用带有内置代理解析的 Playwright。
  • 在设置后检查 dnsleaktest.com 或 ipleak.net 的结果,而不是之前。
  • 在反检测浏览器中测试 DNS 指纹时,确保在配置文件内部进行,而不仅仅是外部 IP。
  • 对于对匿名性要求高的任务,考虑使用住宅或移动代理,而不是数据中心代理。

结论

SOCKS5 和 SOCKS5h 之间的差异仅仅是一个字母,但它决定了谁解析 DNS 请求:您的计算机还是代理服务器。DNS 泄漏是解析、多个账户和广告自动化中最不显眼但最常见的检测原因之一。通过 dnsleaktest.com 进行检查并在代码、curl 命令或浏览器自动化设置中明确指定 socks5h 方案,可以在几分钟内修复此漏洞。

如果您正在选择基础设施来完成任务——对于解析和 API 工作,数据中心代理 更合适,对于多个账户和社交媒体——住宅代理,而对于在移动应用中工作的自然网络指纹——移动代理。在这些情况下,通过 SOCKS5h 正确设置 DNS 解析仍然是项目投入生产前的必要步骤。