در این آموزش ابتدا بدون ایجاد تغییر خطرناک بررسی میکنیم Docker و UFW دقیقاً چه قوانینی روی سرور ساختهاند، سپس روشهای امن کنترل دسترسی به کانتینرها را بررسی میکنیم.
چرا Docker و UFW با یکدیگر تداخل پیدا میکنند؟
UFW یک رابط ساده برای مدیریت Firewall لینوکس است. Docker نیز برای راهاندازی شبکههای Bridge، انجام NAT، Masquerading و Port Forwarding مجبور است قوانین Netfilter ایجاد کند.
مشکل اصلی زمانی دیده میشود که پورتی از کانتینر روی Host منتشر میکنید. برای مثال:
docker run -d -p 8080:80 nginx
در این مثال Docker پورت 8080 سرور را به پورت 80 کانتینر متصل میکند. Docker برای انجام این کار فقط منتظر UFW نمیماند؛ خودش قوانین لازم برای NAT و Forwarding را ایجاد میکند.
به همین دلیل ممکن است دستور زیر را اجرا کنید:
sudo ufw deny 8080/tcp
اما پورت Publishشده Docker همچنان از بیرون قابل دسترسی باشد. این رفتار به این دلیل است که Docker ترافیک کانتینر را در مسیر NAT تغییر میدهد و ترافیک لزوماً مانند یک اتصال عادی به سرویس Host از زنجیرههای UFW عبور نمیکند.
قبل از هر تغییری از Firewall نسخه پشتیبان بگیرید
برای ثبت وضعیت فعلی UFW اجرا کنید:
sudo ufw status verbose
sudo ufw status numbered
سپس قوانین iptables را ذخیره کنید:
sudo iptables-save > ~/iptables-backup.rules
sudo ip6tables-save > ~/ip6tables-backup.rules
این فایلها شامل اطلاعات شبکه و قوانین امنیتی سرور هستند؛ آنها را عمومی منتشر نکنید.
مرحله ۱: وضعیت UFW را بررسی کنید
sudo ufw status verbose
اگر UFW فعال باشد، عبارت Status: active را خواهید دید. همچنین Default Policyها را بررسی کنید.
برای مشاهده قوانین همراه شماره:
sudo ufw status numbered
نکته مهم این است که خروجی ufw status تمام قوانین Netfilter سرور را نشان نمیدهد. بنابراین مشاهده یک پورت بسته در این خروجی بهتنهایی ثابت نمیکند که Docker نیز دسترسی به آن را مسدود کرده است.
مرحله ۲: پورتهای Publishشده Docker را پیدا کنید
حالا باید مشخص شود Docker واقعاً چه پورتهایی را روی Host منتشر کرده است:
docker ps --format "table {{.Names}}\t{{.Ports}}"
اگر چیزی شبیه نمونه زیر مشاهده کردید:
0.0.0.0:8080->80/tcp
یعنی پورت 8080 روی تمام IPv4 Addressهای Host منتشر شده است. اگر IPv6 نیز فعال باشد، وضعیت IPv6 را هم جداگانه بررسی کنید.
برای سرویسهایی که فقط باید روی خود سرور قابل استفاده باشند، انتشار روی Loopback بسیار امنتر است:
docker run -d -p 127.0.0.1:8080:80 nginx
این روش برای سرویسهایی که قرار است پشت Nginx، Caddy یا Reverse Proxy دیگری باشند معمولاً انتخاب بهتری از Publish کردن مستقیم آنها روی 0.0.0.0 است.
مرحله ۳: مشخص کنید Docker از چه Firewall Backend استفاده میکند
در نسخههای جدید Docker نباید از روی نسخه Ubuntu یا وجود دستور nft حدس بزنید Docker دقیقاً از چه backendی استفاده میکند.
ابتدا نسخه Docker را ببینید:
docker version
docker info
سپس پیکربندی Daemon را در صورت وجود بررسی کنید:
sudo cat /etc/docker/daemon.json
در Docker Engine 29 امکان انتخاب backend آزمایشی nftables با گزینه firewall-backend وجود دارد. اگر چنین تنظیمی ندارید، بدون دلیل آن را تغییر ندهید.
همچنین وضعیت iptables سیستم را بررسی کنید:
iptables --version
sudo update-alternatives --display iptables
وجود عبارت nf_tables در خروجی iptables به این معنی است که ابزار iptables از لایه سازگاری nftables استفاده میکند؛ این موضوع با فعالکردن backend بومی nftables در Docker Engine 29 یکسان نیست.
مرحله ۴: قوانین ساختهشده توسط Docker را ببینید
اگر Docker از مسیر iptables استفاده میکند، ابتدا زنجیرههای Filter را بدون تغییر مشاهده کنید:
sudo iptables -L -n -v --line-numbers
برای مشاهده قوانین NAT:
sudo iptables -t nat -L -n -v --line-numbers
و برای بررسی زنجیره مهم DOCKER-USER:
sudo iptables -L DOCKER-USER -n -v --line-numbers
در backend مبتنی بر iptables، Docker زنجیره DOCKER-USER را برای قوانین سفارشی مدیر سرور در نظر گرفته است. ترافیک Docker پیش از ورود به بخشهای بعدی قوانین Docker از این زنجیره عبور میکند.
مرحله ۵: آیا واقعاً UFW توسط Docker دور زده میشود؟
برای آزمایش، فرض کنیم کانتینری روی پورت 8080 منتشر شده است.
وضعیت Docker:
docker ps
وضعیت UFW:
sudo ufw status numbered
سپس از یک دستگاه دیگر خارج از VPS دسترسی به پورت را آزمایش کنید. تست از localhost برای بررسی دسترسی خارجی کافی نیست.
در Linux یا macOS میتوانید اجرا کنید:
curl -I http://192.0.2.10:8080
آدرس 192.0.2.10 در این مقاله فقط نمونه است و باید با IP واقعی سرور خود جایگزین شود.
اگر UFW دسترسی را Deny نشان میدهد ولی سرویس از اینترنت باز است، احتمال زیادی وجود دارد که با مسیر Port Publishing خود Docker روبهرو باشید.
برای اجرای Docker، کانتینرها، Reverse Proxy و سرویسهای Self-hosted میتوانید از سرور مجازی استفاده کنید. اگر محل میزبانی داخل کشور برای پروژه شما مناسب است، پلنهای VPS ایران ایرانیکاسرور نیز قابل بررسی هستند.
روش امن اول: پورت غیرعمومی را روی 127.0.0.1 منتشر کنید
اگر سرویس Docker قرار نیست مستقیماً از اینترنت در دسترس باشد، سادهترین راه این است که اصلاً آن را روی تمام Interfaceهای Host منتشر نکنید.
بهجای:
docker run -d -p 8080:80 nginx
از این ساختار استفاده کنید:
docker run -d -p 127.0.0.1:8080:80 nginx
در Docker Compose نیز میتوانید بهجای:
ports:
- "8080:80"
بنویسید:
ports:
- "127.0.0.1:8080:80"
این روش سطح حمله را کاهش میدهد و برای سرویسهای داخلی، Databaseها و Backendهایی که پشت Reverse Proxy هستند بسیار مفید است.
روش امن دوم: استفاده از DOCKER-USER در backend مبتنی بر iptables
اگر لازم است کانتینر روی IP عمومی Publish شود اما فقط IPهای مشخصی اجازه اتصال داشته باشند، در Docker مبتنی بر iptables میتوان از DOCKER-USER استفاده کرد.
برای مثال:
ip route
اگر Interface اینترنت سرور eth0 باشد و فقط IP نمونه 192.0.2.25 باید اجازه دسترسی به ترافیک Docker را داشته باشد، منطق کلی میتواند ابتدا اجازه Connectionهای برقرارشده و سپس محدودسازی منبع باشد.
sudo iptables -I DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -I DOCKER-USER -i eth0 ! -s 192.0.2.25 -j DROP
این فقط یک الگوی آموزشی است و در سروری که چند سرویس، چند Interface یا چند شبکه Docker دارد باید Rule دقیقتری طراحی شود.
نکته مهمتر اینکه هنگام ورود Packet به DOCKER-USER عملیات DNAT ممکن است قبلاً انجام شده باشد. بنابراین اگر قصد Match کردن IP یا Port مقصد اصلی قبل از DNAT را دارید، ممکن است به قابلیتهای conntrack نیاز داشته باشید.
آیا باید iptables=false را در Docker فعال کنیم؟
معمولاً خیر.
گاهی برای حل تداخل UFW و Docker پیشنهاد میشود این تنظیم در /etc/docker/daemon.json قرار بگیرد:
{
"iptables": false
}
این راهحل عمومی و مناسبی نیست. Docker برای Bridge Networking، NAT و Masquerading به قوانین Firewall نیاز دارد. جلوگیری از ساخت این قوانین بدون جایگزینکردن کامل آنها میتواند ارتباط شبکه کانتینرها را خراب کند.
بنابراین iptables=false را صرفاً برای اینکه UFW «کنترل کامل» پیدا کند فعال نکنید، مگر اینکه دقیقاً بدانید قرار است قوانین شبکه Docker را چگونه جایگزین کنید.
تفاوت iptables-nft با backend بومی nftables در Docker 29
این قسمت یکی از مواردی است که در عیبیابیهای جدید Docker اهمیت زیادی دارد.
ممکن است دستور زیر:
iptables --version
خروجی حاوی nf_tables بدهد. این موضوع لزوماً به معنی استفاده Docker از backend جدید nftables نیست.
iptables-nft رابط سازگاری iptables روی زیرساخت nftables است؛ در مقابل Docker Engine 29 یک backend بومی nftables نیز دارد که با گزینهای مانند زیر انتخاب میشود:
{
"firewall-backend": "nftables"
}
طبق مستندات Docker، پشتیبانی بومی nftables که از Docker Engine 29 معرفی شده هنوز Experimental است. همچنین مدل قوانین سفارشی آن با مسیر کلاسیک DOCKER-USER یکسان نیست. بنابراین آموزشهای قدیمی مبتنی بر DOCKER-USER را نباید بدون بررسی روی backend بومی nftables اجرا کرد.
UFW و nftables را همزمان و مستقل مدیریت نکنید
یک مشکل دیگر زمانی ایجاد میشود که مدیر سرور UFW را فعال کرده، Docker نیز قوانین خودش را دارد و همزمان فایل /etc/nftables.conf با مجموعه قوانین مستقل دیگری در حال Load شدن است.
ابتدا وضعیت سرویس nftables را ببینید:
sudo systemctl status nftables
سپس Ruleset را فقط برای بررسی مشاهده کنید:
sudo nft list ruleset
اگر UFW، Docker و یک Ruleset دستی nftables همزمان در حال مدیریت Netfilter هستند، قبل از هر اصلاح باید مشخص کنید مالک هر بخش از قوانین کدام سرویس است. پاککردن کورکورانه Ruleset میتواند هم امنیت Host و هم شبکه Docker را مختل کند.
بررسی IP Forwarding
شبکه Bridge در Docker به Forwarding وابسته است. وضعیت IPv4 را با دستور زیر ببینید:
sysctl net.ipv4.ip_forward
مقدار 1 یعنی IPv4 Forwarding فعال است.
Policy زنجیره FORWARD را نیز بررسی کنید:
sudo iptables -L FORWARD -n -v
وجود Policy برابر DROP بهتنهایی نشاندهنده خرابی Docker نیست. Docker میتواند زنجیرهها و Ruleهای مشخصی برای اجازه ترافیک مورد نیاز شبکه خودش ایجاد کند.
چرا بعد از ufw reload شبکه Docker خراب میشود؟
اگر مشکل دقیقاً بعد از Reload یا Reset کردن Firewall ظاهر شده، ترتیب و وضعیت قوانین را دوباره بررسی کنید:
sudo ufw status verbose
sudo iptables -L FORWARD -n -v
sudo iptables -L DOCKER-USER -n -v
sudo iptables -t nat -L DOCKER -n -v
docker network ls
اگر Docker از backend بومی nftables استفاده میکند، بررسی iptables بهتنهایی کافی نیست و باید Ruleset nftables و پیکربندی Docker را نیز بررسی کنید.
جدول عیبیابی سریع Docker و UFW
| نشانه | بررسی | علت محتمل |
|---|---|---|
| UFW پورت را بسته ولی Docker باز است | docker ps و قوانین NAT | Port Publishing و DNAT Docker |
| کانتینر اینترنت ندارد | FORWARD، NAT و IP Forwarding | قوانین Forwarding یا Masquerading |
| مشکل بعد از ufw reload | iptables و زنجیرههای Docker | تغییر یا بازآرایی قوانین Firewall |
| بعد از reboot مشکل برمیگردد | سرویسهای UFW، Docker و nftables | Rulesetهای دائمی یا ترتیب Load شدن سرویسها |
| DOCKER-USER وجود ندارد | Docker backend و نسخه Engine | استفاده از backend متفاوت یا وضعیت غیرعادی Daemon |
چه کارهایی را برای رفع مشکل انجام ندهیم؟
🔹 برای رفع سریع مشکل، UFW را برای همیشه خاموش نکنید.
🔹 بدون داشتن Console یا مسیر بازیابی، زنجیرههای Firewall را Flush نکنید.
🔹 گزینه iptables=false را بدون طراحی قوانین جایگزین فعال نکنید.
🔹 فایل /etc/nftables.conf را فقط به دلیل مشاهده nftables پاک نکنید.
🔹 تصور نکنید ufw status تمام قوانین Firewall ساختهشده توسط Docker را نمایش میدهد.
🔹 وجود عبارت nf_tables در خروجی iptables را با backend بومی nftables در Docker 29 یکی ندانید.
🔹 Database، Redis، PostgreSQL و پنلهای مدیریتی را بدون نیاز روی 0.0.0.0 Publish نکنید.
چکلیست نهایی بررسی تداخل UFW و Docker
برای عیبیابی اولیه معمولاً همین مجموعه دستورها اطلاعات زیادی در اختیار شما قرار میدهد:
sudo ufw status verbose
docker version
docker info
docker ps --format "table {{.Names}}\t{{.Ports}}"
iptables --version
sudo iptables -L -n -v
sudo iptables -L FORWARD -n -v
sudo iptables -L DOCKER-USER -n -v
sudo iptables -t nat -L -n -v
sysctl net.ipv4.ip_forward
sudo systemctl status nftables
sudo nft list ruleset
اگر یکی از دستورهای مربوط به DOCKER-USER یا nftables خطا داد، همان خطا خودش بخشی از اطلاعات تشخیصی است؛ فوراً زنجیره یا Ruleset جدید نسازید تا backend واقعی Docker مشخص شود.
سؤالات متداول
آیا Docker واقعاً UFW را دور میزند؟
در Port Publishing معمول Docker، بله؛ ترافیک کانتینر میتواند به دلیل NAT و مسیری که Docker در Netfilter ایجاد میکند قبل از اعمال قواعد معمول Host Firewall تغییر مسیر پیدا کند. به همین دلیل یک ufw deny ساده الزاماً پورت Publishشده Docker را مسدود نمیکند.
آیا باید UFW را هنگام استفاده از Docker خاموش کنیم؟
خیر. UFW همچنان میتواند از سرویسهای خود Host مانند SSH محافظت کند. مسئله این است که برای ترافیک کانتینرهای Publishشده نباید فرض کنید تمام سیاستهای UFW دقیقاً مانند سرویسهای Host اعمال میشوند.
DOCKER-USER چیست؟
در backend مبتنی بر iptables، DOCKER-USER زنجیرهای برای قرار دادن قوانین سفارشی مدیر سیستم پیش از بخش مهمی از پردازش قوانین Forwarding خود Docker است. این زنجیره برای محدودکردن ترافیک Docker کاربرد دارد.
چرا ufw deny پورت Docker را نمیبندد؟
چون پورت منتشرشده Docker مانند یک سرویس عادی که مستقیماً روی Host گوش میدهد پردازش نمیشود. Docker برای Port Mapping از NAT و Forwarding استفاده میکند و همین موضوع مسیر Packet را تغییر میدهد.
آیا iptables-nft همان nftables backend جدید Docker است؟
خیر. iptables-nft رابط سازگاری iptables روی زیرساخت nftables است، در حالی که Docker Engine 29 امکان استفاده از backend بومی nftables را نیز اضافه کرده است. روش مدیریت قوانین سفارشی این دو حالت یکسان نیست.
برای سرویس Docker داخلی بهترین روش چیست؟
اگر سرویس نباید مستقیماً از اینترنت دیده شود، تا جای ممکن آن را روی 127.0.0.1 Publish کنید یا فقط داخل Docker Network نگه دارید و دسترسی خارجی را از طریق Reverse Proxy کنترل کنید.
آیا خاموشکردن ساخت قوانین iptables توسط Docker امن است؟
برای بیشتر سرورها خیر. مستندات Docker هشدار میدهند که جلوگیری از ایجاد قوانین Firewall توسط Docker میتواند Networking کانتینرها را مختل کند. این کار فقط زمانی منطقی است که مدیر سیستم قوانین جایگزین را کامل طراحی و مدیریت کند.
منابع رسمی
مبنای فنی این آموزش مستندات رسمی Docker درباره Packet Filtering، زنجیرههای iptables و محدودیت UFW و همچنین مستندات Firewall اوبونتو است.
Docker Docs — Packet filtering and firewalls
Docker Docs — Docker with iptables
Docker Docs — Docker with nftables
Ubuntu Server — Firewall documentation
UFW و Docker هر دو با Netfilter کار میکنند، اما Port Publishing در Docker باعث میشود ترافیک کانتینر دقیقاً مانند یک سرویس معمولی Host از قوانین UFW عبور نکند. قبل از تغییر Firewall ابتدا پورتهای Publishشده، backend واقعی Docker، زنجیرههای DOCKER-USER و FORWARD، قوانین NAT و وضعیت IP Forwarding را بررسی کنید. برای سرویسهای غیرعمومی نیز محدودکردن Bind به 127.0.0.1 معمولاً از بازکردن پورت روی تمام Interfaceها امنتر و سادهتر است.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467






دیدگاهها (۰)