← بازگشت به وبلاگ

SOCKS5 در مقابل SOCKS5h: رفع نشت درخواست‌های DNS در Python، curl و Selenium

در این مقاله بررسی می‌کنیم که چرا هنگام کار با SOCKS5 درخواست‌های DNS مستقیماً از IP شما ارسال می‌شوند، تفاوت SOCKS5h چیست و چگونه می‌توان این مشکل را در Python، curl، Selenium و مرورگرهای ضد شناسایی برطرف کرد.

📅۸ آبان ۱۴۰۵

شما SOCKS5 پروکسی را تنظیم کرده‌اید، به نظر می‌رسد ترافیک از طریق آن می‌رود، IP در مرورگر به درستی نمایش داده می‌شود — اما وب‌سایت‌ها هنوز هم منطقه واقعی شما را می‌بینند یا ارائه‌دهنده شروع به مشکوک شدن می‌کند. دلیل تقریباً همیشه یکی است: درخواست‌های DNS به طور مستقیم از کامپیوتر شما ارسال می‌شوند و از پروکسی عبور نمی‌کنند. در این مقاله بررسی خواهیم کرد که چرا این اتفاق می‌افتد، SOCKS5 چه تفاوتی با SOCKS5h دارد و چگونه می‌توان این نشت را در کد و ابزارهای آماده بسته کرد.

SOCKS5 چیست و چه تفاوتی با SOCKS5h دارد

SOCKS5 یک پروتکل پروکسی است که در سطح اتصالات TCP/UDP کار می‌کند و محتویات بسته‌ها را تجزیه و تحلیل نمی‌کند، بر خلاف پروکسی‌های HTTP(S). این ویژگی آن را چندمنظوره می‌کند: از طریق SOCKS5 می‌توان تقریباً هر نوع ترافیکی را پروکسی کرد — مرورگر، تلگرام، کلاینت تورنت، اسکریپت در Python. اما در پیاده‌سازی کلاسیک SOCKS5 یک ویژگی مهم وجود دارد: حل نام‌های دامنه (DNS) به طور پیش‌فرض در سمت کلاینت انجام می‌شود، یعنی روی کامپیوتر شما، نه در سمت سرور پروکسی.

SOCKS5h همان پروتکل است، اما با اصلاح‌کننده «h» (hostname) که به برنامه کلاینت می‌گوید که دامنه را به طور مستقل حل نکند، بلکه آن را به همان شکل به سرور پروکسی ارسال کند و سپس پروکسی درخواست DNS را به نام خود انجام دهد. تفاوت در یک حرف است، اما عواقب آن برای ناشناسی و ثبات عملکرد — اصولی است.

مهم است که درک کنید: SOCKS5h یک پروتکل جداگانه نیست، بلکه توافقی در سطح یک کتابخانه یا برنامه خاص است در مورد اینکه چگونه درخواست به پروکسی تشکیل شود. خود سرور پروکسی در هر دو حالت به یک شکل کار می‌کند، تنها تفاوت در این است که چه کسی حل DNS را آغاز می‌کند — کلاینت یا سرور.

چرا درخواست‌های DNS از پروکسی عبور می‌کنند

وقتی به آدرسی مانند https://example.com مراجعه می‌کنید، قبل از برقراری اتصال، برنامه باید IP آدرس این دامنه را بداند. این فرآیند به نام حل DNS شناخته می‌شود. هنگام کار از طریق SOCKS5 معمولی، بسیاری از کتابخانه‌ها و تنظیمات سیستم حل DNS را از طریق سرور DNS سیستم انجام می‌دهند — همان سروری که در تنظیمات شبکه ارائه‌دهنده یا روتر شما قرار دارد.

در نتیجه، یک وضعیت پارادوکسیکال به وجود می‌آید: خود ترافیک HTTP/TCP از طریق پروکسی می‌رود و به نظر می‌رسد که درخواست از IP سرور پروکسی آمده است، در حالی که درخواست DNS «IP example.com چیست؟» به طور مستقیم از IP واقعی شما به سرور DNS ارائه‌دهنده می‌رود. این همان نشت DNS (DNS leak) است. وب‌سایت یا سرویسی که فعالیت شبکه را در سطح عمیق‌تری تجزیه و تحلیل می‌کند (و چنین روش‌های شناسایی به طور فعال توسط سیستم‌های ضد تقلب Facebook، Google، TikTok استفاده می‌شود)، می‌تواند عدم تطابق بین IP اتصال و منبع درخواست DNS را ببیند.

دلیل این است که پروتکل SOCKS5 در ابتدا به عنوان یک سطح حمل و نقل برای اتصالات IP آماده طراحی شده است، نه برای حل نام‌ها. توسعه‌دهندگان کتابخانه‌ها و ابزارها مجبور شدند به طور جداگانه عملکرد انتقال درخواست DNS از طریق تونل را پیاده‌سازی کنند — از این رو SOCKS5h به عنوان یک اشاره واضح «دامنه را خودت حل کن، نه من» به وجود آمد.

خطر نشت DNS در عمل چیست

برای توسعه‌دهنده پارسر یا اسکریپت اتوماسیون، نشت DNS یک نظریه انتزاعی نیست، بلکه یک دلیل خاص برای مسدود شدن‌ها و بن شدن حساب‌ها است. بیایید چند سناریو را بررسی کنیم.

پارسی کردن بازارها و وب‌سایت‌ها. اگر شما Wildberries، Ozon یا منبع دیگری را از طریق پروکسی از منطقه مورد نظر پارسی می‌کنید، اما درخواست‌های DNS از طریق ارائه‌دهنده می‌روند، سیستم ضد ربات می‌تواند عدم تطابق جغرافیایی را ثبت کند و سطح مشکوک بودن جلسه را افزایش دهد — تا حدی که به CAPTCHA یا مسدودیت موقتی 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])

برای عملکرد صحیح طرح socks5h از طریق requests نیاز به نصب وابستگی دارید:

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 وجود دارد و سردرگمی بین آن‌ها — دلیل کلاسیک نشت DNS در اسکریپت‌های bash است.

# بد: حل در ماشین محلی
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 باید به وضوح حل DNS را از طریق پروکسی با استفاده از پرچم راه‌اندازی مرورگر فعال کنید.

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 استفاده می‌کنید — خبر خوب این است که بیشتر آن‌ها به طور خودکار DNS را از طریق سرور پروکسی حل می‌کنند وقتی پروتکل SOCKS5 را انتخاب می‌کنید، بدون نیاز به تعیین «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 و تعیین صریح طرح socks5h در کد، دستورات curl یا تنظیمات اتوماسیون مرورگر این شکاف را در چند دقیقه می‌بندد.

اگر شما فقط زیرساختی برای وظیفه انتخاب می‌کنید — برای پارسی کردن و کار با API، پروکسی‌های مراکز داده بهتر هستند، برای چند حسابه و شبکه‌های اجتماعی — پروکسی‌های مسکونی و برای اثر انگشت شبکه‌ای طبیعی‌تر هنگام کار با برنامه‌های موبایل — پروکسی‌های موبایل. در هر یک از این موارد، تنظیم صحیح حل DNS از طریق SOCKS5h همچنان یک مرحله ضروری قبل از راه‌اندازی پروژه در تولید باقی می‌ماند.