رفتن به محتوای اصلی
FA

خانه / وبلاگ / استقرار

رساندن Docker و WSL2 به پروکسی Clash روی میزبان

استقرار2026-06-141401 واژه3 دقیقه مطالعه
رساندن Docker و WSL2 به پروکسی Clash روی میزبان

روی میزبان Clash خوب کار می‌کند و بعد داخل کانتینر همه‌چیز timeout می‌شود. دلیلش ساده است: کانتینر فضای نام شبکهٔ خودش را دارد، پس 127.0.0.1 یعنی خود کانتینر.

پیش‌شرط اصلی: روشن کردن allow-lan

هر رویکردی که بردارید گام اول یکی است — نشانی گوش دادن Clash را از 127.0.0.1 به 0.0.0.0 ببرید:

در Clash Verge گزینهٔ Allow LAN را روشن کنید، یا در پیکربندی بنویسید:

allow-lan: true
bind-address: "*"
mixed-port: 7897

بررسی:

netstat -an | findstr 7897

دیدن 0.0.0.0:7897 یعنی گرفت. دیدن 127.0.0.1:7897 یعنی نگرفت.

Docker: سه سناریوی جداگانه

بیشتر سردرگمی از این می‌آید که مردم نمی‌دانند این سه باید جداگانه تنظیم شوند.

سه سناریو، سه پیکربندی1۱. دستور docker pullدیمون Docker است که به شبکه می‌رود، پس پروکسی دیمون را تنظیم کنید2۲. دستور docker buildکانتینر ساخت است که به شبکه می‌رود، پس build-arg بدهید3۳. دستور docker runفرایندی درون کانتینر به شبکه می‌رود، پس متغیر محیطی بدهید
تنظیم یکی، دو تای دیگر را روشن نمی‌کند — رایج‌ترین منبع سردرگمی همین است

سناریوی ۱: docker pull تصویر نمی‌آورد

اینجا دیمون Docker به شبکه می‌رود؛ کانتینرها دخیل نیستند.

Docker Desktop (ویندوز / مک): Settings ← Resources ← Proxies ← گزینهٔ Manual proxy configuration را روشن کنید و پر کنید:

HTTP:  http://127.0.0.1:7897
HTTPS: http://127.0.0.1:7897
Bypass: localhost,127.0.0.1,*.local

دیمون Docker Desktop در یک ماشین مجازی اجرا می‌شود ولی به loopback میزبان می‌رسد، پس 127.0.0.1 اینجا درست است.

Docker روی لینوکس (systemd):

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/proxy.conf > /dev/null <<'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7897"
Environment="HTTPS_PROXY=http://127.0.0.1:7897"
Environment="NO_PROXY=localhost,127.0.0.1,::1,*.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

بررسی:

sudo systemctl show --property=Environment docker

سناریوی ۲: نصب وابستگی‌ها هنگام docker build timeout می‌شود

ساخت درون یک کانتینر موقت انجام می‌شود، پس باید صریحاً پاسش داد:

docker build \
  --build-arg HTTP_PROXY=http://host.docker.internal:7897 \
  --build-arg HTTPS_PROXY=http://host.docker.internal:7897 \
  --build-arg NO_PROXY=localhost,127.0.0.1 \
  -t myimage .

لازم نیست این ARGها را در Dockerfile اعلام کنید — Docker برای همین نام‌های خاص پشتیبانی توکار دارد.

سناریوی ۳: کانتینر در حال اجرا به شبکه نیاز دارد

docker run -it \
  -e HTTP_PROXY=http://host.docker.internal:7897 \
  -e HTTPS_PROXY=http://host.docker.internal:7897 \
  -e NO_PROXY=localhost,127.0.0.1,::1 \
  --add-host=host.docker.internal:host-gateway \
  ubuntu bash

در docker-compose:

services:
  app:
    image: myimage
    environment:
      - HTTP_PROXY=http://host.docker.internal:7897
      - HTTPS_PROXY=http://host.docker.internal:7897
      - NO_PROXY=localhost,127.0.0.1,::1,app,db
    extra_hosts:
      - "host.docker.internal:host-gateway"

استفاده از IP شبکهٔ محلی میزبان به‌جای host.docker.internal

اگر host.docker.internal در دسترس نیست، مستقیم نشانی محلی میزبان را بردارید:

# روی ویندوز
ipconfig
# روی لینوکس، نشانی پل docker0 (میزبان از دید کانتینر)
ip addr show docker0    # معمولاً 172.17.0.1

بعد آن نشانی را جایگزین host.docker.internal کنید.

راه ساده‌تر: روشن کردن TUN

پیکربندی بالا کم نیست. اگر حوصله ندارید، حالت TUN را روشن کنید — همهٔ ترافیک در لایهٔ شبکه رهگیری می‌شود و نه دیمون Docker و نه هیچ کانتینری نیاز به تنظیم دارد.

دو رویکردتنظیم صریح هر پروکسیدقیق و قابل‌کنترلبه بقیهٔ ترافیک کار نداردسه جا برای تنظیم، راحت یکی جا می‌ماندحالت TUNیک بار تنظیم و تمامDocker اصلاً خبر نداردبه دسترسی کارت مجازی نیاز دارد و می‌تواند با شبکهٔ کانتینر تعارض کند
روی دستگاه توسعه TUN کم‌زحمت‌ترین انتخاب است؛ روی سرور تنظیم تکه‌تکه بهتر است

زیر TUN یادتان باشد زیرشبکه‌های Docker را به قواعد مستقیم اضافه کنید تا ترافیک کانتینر به کانتینر پروکسی نشود:

prepend-rules:
  - IP-CIDR,172.17.0.0/16,DIRECT,no-resolve
  - IP-CIDR,172.18.0.0/16,DIRECT,no-resolve
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve

WSL2: دو حالت شبکه

از نسخه‌ای به بعد WSL2 از شبکهٔ آینه‌ای پشتیبانی می‌کند و این دو حالت کاملاً متفاوت تنظیم می‌شوند. اول مشخص کنید روی کدام هستید.

# داخل WSL2 اجرا کنید
cat /etc/resolv.conf
ip route show default

حالت ۱: NAT (پیش‌فرض، سنتی)

WSL2 کارت مجازی خودش را دارد و میزبان از دید آن یک نشانی دروازه است.

# IP میزبان را بگیرید و پروکسی را بگذارید
export HOST_IP=$(ip route show default | awk '{print $3}')
export HTTP_PROXY="http://$HOST_IP:7897"
export HTTPS_PROXY="http://$HOST_IP:7897"
export ALL_PROXY="socks5://$HOST_IP:7897"
export NO_PROXY="localhost,127.0.0.1,::1,*.local"

آن را در ~/.bashrc یا ~/.zshrc به‌صورت دو کلید بگذارید:

proxyon() {
  local host_ip=$(ip route show default | awk '{print $3}')
  export HTTP_PROXY="http://${host_ip}:7897"
  export HTTPS_PROXY="http://${host_ip}:7897"
  export ALL_PROXY="socks5://${host_ip}:7897"
  export NO_PROXY="localhost,127.0.0.1,::1,*.local"
  echo "proxy on → ${host_ip}:7897"
}
proxyoff() {
  unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY
  echo "proxy off"
}

چرا IP را پویا بگیریم: نشانی کارت مجازی WSL2 با هر بار راه‌اندازی مجدد میزبان می‌تواند عوض شود، پس مقدار سفت‌نوشته از کار می‌افتد.

حالت ۲: شبکهٔ آینه‌ای (ویندوزهای تازه‌تر)

در %USERPROFILE%\.wslconfig روشنش کنید:

[wsl2]
networkingMode=mirrored
dnsTunneling=true
autoProxy=true
firewall=true

بعدش wsl --shutdown بزنید تا WSL دوباره بالا بیاید.

در حالت آینه‌ای، WSL2 فضای نام شبکهٔ میزبان را به اشتراک می‌گذارد، پس 127.0.0.1 مستقیم کار می‌کند:

export HTTP_PROXY="http://127.0.0.1:7897"
export HTTPS_PROXY="http://127.0.0.1:7897"

autoProxy=true علاوه بر این باعث می‌شود WSL تنظیم پروکسی سیستم ویندوز را به ارث ببرد، پس در خیلی از موارد اصلاً به متغیر محیطی نیاز ندارید.

دو حالت شبکهٔ WSL2حالت NATکارت مجازی مخصوصIP میزبان باید پویا گرفته شودبه استثنای فایروال نیاز داردسازگاری گستردهحالت آینه‌ایشبکه را با میزبانشانی 127.0.0.1 مستقیم کار می‌کندمی‌تواند خودکار پروکسی سیستم را به ارث ببردبه ویندوز تازه‌تر نیاز دارد
هرجا می‌شود حالت آینه‌ای بردارید — بخش زیادی از پیکربندی را برمی‌دارد

سنجش کار کردن پروکسی

# متغیرهای محیطی را ببینید
env | grep -i proxy

# امتحان کنید
curl -I https://www.google.com

# IP خروجی را ببینید (باید IP گره باشد)
curl https://api.ipify.org

اگر curl کار می‌کند ولی apt و pip هنوز نه، آن ابزارها پیکربندی پروکسی خودشان را دارند؛ راهنمای سریع پروکسی ابزارهای توسعه را ببینید.

فهرست بررسی تشخیصی

وقتی وصل نمی‌شود، به ترتیب بررسی کنیدآیا allow-lan در Clash روشن است (netstat باید 0.0.0.0 نشان بدهد)آیا فایروال ویندوز باز شدهآیا کانتینر یا WSL می‌تواند IP میزبان را پینگ کندآیا پورت با پورت mixed در Clash می‌خواندآیا NO_PROXY نام سرویس‌های داخلی و بازه‌های خصوصی را مستثنا می‌کندآیا فقط یکی از سه سناریوی Docker را تنظیم کرده‌اید (daemon

یک بررسی سریع، داخل کانتینر یا WSL:

curl -v --connect-timeout 5 http://ip-میزبان:7897

اگر اصلاً وصل شد — حتی با پاسخ ۴۰۰ — یعنی لایهٔ شبکه سالم است؛ Connection refused به allow-lan یا فایروال اشاره می‌کند.

خلاصه

  • گام اول همیشه allow-lan به‌علاوهٔ استثنای فایروال است
  • سه سناریوی Docker هرکدام پیکربندی خودشان را می‌خواهند: daemon و build و run
  • host.docker.internal روی لینوکس به --add-host نیاز دارد
  • برای WSL2 اول حالت شبکه را تشخیص بدهید: NAT به گرفتن پویای IP دروازه نیاز دارد، حالت آینه‌ای 127.0.0.1 می‌گیرد
  • بازه‌های خصوصی و نام سرویس‌ها را از NO_PROXY جا نگذارید
  • اگر همهٔ این‌ها زیادی است، TUN را روشن کنید — ولی زیرشبکه‌های Docker را به قواعد مستقیم اضافه کنید

بیشتر بخوانید: راهنمای سریع پروکسی ابزارهای توسعه و درون TUN.


مستندات مرتبط