SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-28

วิธีแก้ปัญหา Docker ข้ามการทำงานของ UFW บน Linux

สาเหตุที่ Docker เปิดพอร์ตผ่าน iptables โดยข้ามกฎของ UFW ทำให้พอร์ตที่สั่งปิดไว้ยังคงเข้าถึงได้จากภายนอก เรียนรู้วิธีแก้ไขด้วยการปรับแต่ง DOCKER-USER chain อย่างถูกต้อง

เหตุใด Docker จึงข้ามการทำงานของ UFW

Docker ข้ามการทำงานของ UFW เนื่องจากพอร์ตของคอนเทนเนอร์ที่ถูกเปิดใช้งาน (published ports) ไม่เคยผ่านกฎของไฟร์วอลล์ที่ UFW ดูแลอยู่ เมื่อคุณรันคำสั่ง docker run -p 8080:80 ตัว Docker จะเขียนกฎ DNAT (destination network address translation) ลงใน chain PREROUTING ของตาราง nat ในเคอร์เนล กฎดังกล่าวจะเขียนปลายทางของแพ็กเก็ตใหม่ไปยังที่อยู่ส่วนตัวของคอนเทนเนอร์ก่อนที่เคอร์เนลจะตัดสินใจว่าแพ็กเก็ตนั้นจะไปที่ใด จากนั้นแพ็กเก็ตที่ถูกแก้ไขปลายทางแล้วจะถูกส่งต่อไปยังคอนเทนเนอร์ผ่าน chain FORWARD ซึ่ง Docker เป็นผู้ควบคุม ในขณะที่กฎของ UFW นั้นอยู่ใน chain INPUT ทำให้แพ็กเก็ตไม่เคยผ่านเข้าไปในส่วนนั้น ด้วยเหตุนี้ แม้ ufw status จะแสดงสถานะ default deny และ sudo ufw deny 8080 รายงานว่าสำเร็จ แต่พอร์ต 8080 ก็ยังคงตอบสนองต่ออินเทอร์เน็ตทั้งหมดอยู่ดี

นี่ไม่ใช่บั๊กของ Docker และ UFW ก็ไม่ได้ทำงานผิดพลาด เครื่องมือทั้งสองโปรแกรมไฟร์วอลล์ของเคอร์เนลตัวเดียวกัน กฎของ Docker เพียงแค่ทำงานในจุดที่เร็วกว่าบนเส้นทางของแพ็กเก็ต ทำให้ UFW ไม่ได้รับคำขอตรวจสอบ คู่มือนี้จะสาธิตการข้ามการทำงานดังกล่าว อธิบายกลไกการทำงาน และครอบคลุมวิธีแก้ไข 2 วิธีที่ได้ผล ได้แก่ การเปิดพอร์ตบน 127.0.0.1 และการกรองใน chain DOCKER-USER หากคุณยังใหม่กับ UFW โปรดตั้งค่าพื้นฐานด้วย คู่มือพื้นฐานไฟร์วอลล์ UFW ก่อน เนื่องจากไฟร์วอลล์แบบ default-deny ยังคงเป็นพื้นฐานที่ถูกต้องสำหรับทุกอย่างบนเซิร์ฟเวอร์

การตรวจสอบช่องโหว่การข้ามผ่านบนเซิร์ฟเวอร์ของคุณเอง

เริ่มต้นจาก VPS ที่เปิดใช้งาน UFW โดยตั้งค่านโยบายเริ่มต้นเป็นปฏิเสธ (deny) สำหรับทราฟฟิกขาเข้าทั้งหมด จากนั้นให้รันเว็บคอนเทนเนอร์โดยเปิดพอร์ตไว้:

sudo ufw status verbose
docker run -d --name web -p 8080:80 nginx:1.29-alpine

ufw status verbose จะแสดง Default: deny (incoming), allow (outgoing) และไม่มีกฎสำหรับพอร์ต 8080 ตามรายงานของไฟร์วอลล์ พอร์ตนี้ควรจะถูกปิดอยู่ ตอนนี้ให้ทดสอบจากเครื่องอื่นที่ไม่ใช่ตัวเซิร์ฟเวอร์เอง:

curl -I http://your-vps-ip:8080/
HTTP/1.1 200 OK

คอนเทนเนอร์ตอบสนองการเชื่อมต่อ ให้เพิ่มกฎปฏิเสธ (deny) อย่างชัดเจนแล้วทดสอบอีกครั้ง:

sudo ufw deny 8080/tcp

พอร์ตยังคงตอบสนองการเชื่อมต่อ เนื่องจากกฎการปฏิเสธอยู่ในเชนที่แพ็กเก็ตไม่เคยผ่านไปถึง UFW ไม่ได้ทำงานผิดพลาด แต่ระบบไม่เคยเรียกใช้กฎดังกล่าว นี่คือสาเหตุที่ปัญหาถูกซ่อนไว้อย่างแนบเนียน: ไม่มีการแสดงข้อผิดพลาดใดๆ การปรับใช้บริการทำงานได้ปกติ และสถานะของไฟร์วอลล์ดูเหมือนเซิร์ฟเวอร์ที่ถูกล็อกไว้อย่างปลอดภัยตามปกติทุกประการ

กลไกการทำงาน: PREROUTING ทำงานก่อน INPUT

เคอร์เนลประมวลผลแพ็กเก็ตขาเข้าตามลำดับที่กำหนดไว้ตายตัว และปัญหาทั้งหมดก็เกิดจากลำดับการทำงานนี้เอง

  1. PREROUTING ทำงานเป็นลำดับแรก กฎในส่วนนี้อาจเขียนปลายทางของแพ็กเก็ตใหม่ ซึ่งกฎของ Docker สำหรับพอร์ตที่เปิดใช้งาน (published port) ก็ทำหน้าที่นี้เช่นกัน
  2. การตัดสินใจเรื่องเส้นทาง (routing decision) จะเกิดขึ้นถัดไป แพ็กเก็ตที่ส่งถึงโฮสต์โดยตรงจะถูกส่งไปยังเชน INPUT ส่วนแพ็กเก็ตที่ส่งไปยังเครื่องอื่นจะถูกส่งไปยังเชน FORWARD
  3. กฎของ UFW จะอยู่ใน INPUT ในขณะที่กฎของ Docker จะอยู่ใน FORWARD

ลองพิจารณากฎของ Docker สำหรับคอนเทนเนอร์ที่คุณเพิ่งเริ่มทำงาน:

sudo iptables -t nat -L DOCKER -n
Chain DOCKER (2 references)
target   prot opt source       destination
RETURN   0    --  0.0.0.0/0    0.0.0.0/0
DNAT     6    --  0.0.0.0/0    0.0.0.0/0    tcp dpt:8080 to:172.17.0.2:80

บรรทัด DNAT คือหัวใจสำคัญของเรื่องนี้ แพ็กเก็ตใดก็ตามที่มาถึงพอร์ต 8080 จะถูกเขียนปลายทางใหม่ไปยัง 172.17.0.2:80 ซึ่งเป็นที่อยู่ของคอนเทนเนอร์บนเครือข่าย bridge ส่วนตัวของ Docker หลังจากเขียนใหม่แล้ว แพ็กเก็ตนั้นจะไม่ได้ถูกส่งถึงโฮสต์อีกต่อไป การตัดสินใจเรื่องเส้นทางจึงส่งมันไปยังเส้นทาง FORWARD ซึ่ง Docker ได้เพิ่มกฎที่ยอมรับทราฟฟิกเข้าสู่เครือข่ายของตนเองไว้ก่อนแล้ว กฎ deny 8080/tcp ของคุณจึงรออยู่ใน INPUT เพื่อรอแพ็กเก็ตที่จะไม่มีวันมาถึง

บน Ubuntu 24.04 คำสั่ง iptables เป็นส่วนติดต่อผู้ใช้ที่ครอบอยู่บน nftables แต่ลำดับของเชนและผลลัพธ์นั้นเหมือนกันทุกประการ ทั้ง UFW และ Docker ต่างเขียนกฎลงในไปป์ไลน์การประมวลผลแพ็กเก็ตของเคอร์เนลชุดเดียวกัน และจุดเริ่มต้นของ Docker นั้นมาก่อน ทั้งหมดนี้ไม่ใช่ปัญหาเฉพาะของ UFW เท่านั้น: firewalld บน Rocky หรือ AlmaLinux VPS ก็ทำการกรองที่จุดเดียวกันในไปป์ไลน์นี้และถูกข้ามไปด้วยกฎ DNAT เดียวกัน ดังนั้นวิธีแก้ไขด้านล่างนี้จึงเป็นสิ่งที่คุณควรนำไปใช้ในกรณีดังกล่าวเช่นกัน

การแก้ไขปัญหาในชีวิตประจำวัน: การเผยแพร่พอร์ตบน 127.0.0.1

คอนเทนเนอร์ส่วนใหญ่ไม่จำเป็นต้องเปิดเผยสู่สาธารณะตั้งแต่แรก ไม่ว่าจะเป็นฐานข้อมูล, แอปเซิร์ฟเวอร์ที่อยู่หลัง reverse proxy, แผงควบคุมผู้ดูแลระบบ หรือ metrics endpoint สิ่งเหล่านี้ไม่ควรตอบสนองต่ออินเทอร์เน็ตโดยตรง ให้เผยแพร่บริการเหล่านี้บน loopback address แทน:

docker run -d --name web -p 127.0.0.1:8080:80 nginx:1.29-alpine

หรือในไฟล์ Compose:

services:
  web:
    image: nginx:1.29-alpine
    ports:
      - "127.0.0.1:8080:80"

วิธีนี้ได้ผลเพราะกฎ DNAT ของ Docker จะจับคู่เฉพาะแพ็กเก็ตที่ระบุปลายทางเป็น 127.0.0.1 เท่านั้น และแพ็กเก็ตจากอินเทอร์เน็ตไม่สามารถระบุปลายทางดังกล่าวได้อย่างถูกต้องตามกฎหมาย เคอร์เนลจึงทิ้งแพ็กเก็ตเหล่านั้นก่อนที่กฎ firewall ใดๆ จะทำงาน พอร์ตจะสามารถเข้าถึงได้จากโฮสต์เท่านั้น ไม่สามารถเข้าถึงจากที่อื่นได้ ให้ตรวจสอบการ binding ดังนี้:

sudo ss -tlnp | grep 8080

คุณควรเห็น 127.0.0.1:8080 ในผลลัพธ์ ไม่ใช่ 0.0.0.0:8080 หรือ [::]:8080 จากนั้นให้ยืนยันจากเครื่องอื่นว่า curl http://your-vps-ip:8080/ ถูกปฏิเสธการเชื่อมต่อ

สำหรับบริการที่จำเป็นต้องเปิดเผยสู่อินเทอร์เน็ต ให้รัน reverse proxy เพียงตัวเดียวที่ดูแลพอร์ต 80 และ 443 และทำหน้าที่กำหนดเส้นทางตาม hostname โดยไม่ต้องเผยแพร่พอร์ตอื่นใดอีก นี่คือรูปแบบที่ คู่มือการใช้งาน Traefik reverse proxy สร้างขึ้น และเป็นวิธีที่แอปแบบ self-hosted เช่น Nextcloud บน VPS จะยังคงไม่สามารถเข้าถึงได้จากภายนอกยกเว้นผ่าน proxy ของมันเอง วิธีการประกาศรายการ ports: และขั้นตอนการทำงานของ Compose ส่วนที่เหลือ ครอบคลุมอยู่ใน คู่มือพื้นฐาน Docker Compose

เมื่อคอนเทนเนอร์ภายในทั้งหมดอยู่บน loopback แล้ว UFW จะกลับมาทำหน้าที่ปกติของมัน คือการป้องกันพอร์ตที่โฮสต์ให้บริการโดยตรง ให้สร้างชุดกฎเหล่านั้นที่นี่ แล้วรันคำสั่งตามลำดับ:

ToolUFW rule generator

การกรองจริง: chain ชื่อ DOCKER-USER

บางครั้งพอร์ตของคอนเทนเนอร์จำเป็นต้องเปิดให้เครือข่ายเข้าถึงได้ แต่ต้องมีการจำกัดสิทธิ์ เช่น พอร์ตของฐานข้อมูลแบบ replica ที่อนุญาตให้เข้าถึงได้จากที่อยู่ IP ของสำนักงานแห่งเดียวเท่านั้น สำหรับกรณีนี้ Docker ได้จัดเตรียม chain ชื่อ DOCKER-USER ไว้ให้ แพ็กเก็ตทุกรายการที่มุ่งหน้าไปยังคอนเทนเนอร์ใดก็ตามจะต้องผ่าน DOCKER-USER ก่อนที่จะถึงกฎการยอมรับ (accept rules) ของ Docker เอง และ Docker จะไม่เขียนกฎใดๆ ลงใน chain นี้ chain นี้มีไว้สำหรับผู้ใช้งานโดยเฉพาะ และ Docker จะไม่เปลี่ยนแปลงเนื้อหาภายใน chain นี้แม้จะมีการรีสตาร์ท daemon ก็ตาม

ข้อควรระวังก่อนใช้คำสั่ง: เมื่อแพ็กเก็ตเดินทางมาถึง DOCKER-USER กระบวนการ DNAT rewrite ได้เกิดขึ้นเรียบร้อยแล้ว พอร์ตปลายทางของแพ็กเก็ตจะเป็นพอร์ตของคอนเทนเนอร์ (เช่น 80 ในตัวอย่างของเรา) ไม่ใช่พอร์ตที่เปิดใช้งานจริง (8080) ดังนั้นกฎที่จับคู่กับ --dport 8080 จึงไม่สามารถใช้งานได้ วิธีที่เชื่อถือได้คือการจับคู่กับพอร์ตที่ไคลเอนต์เรียกใช้งานในตอนแรก ซึ่ง kernel connection tracker จะจดจำข้อมูลส่วนนี้ไว้:

sudo iptables -I DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 8080 --ctdir ORIGINAL ! -s 10.0.0.10 -j DROP

อ่านกฎนี้ได้ว่า: สำหรับแพ็กเก็ตที่เข้ามาทาง eth0 และเป็นส่วนหนึ่งของการเชื่อมต่อที่มีพอร์ตปลายทางเดิมคือ 8080 ให้ทิ้ง (drop) ทุกอย่างที่ไม่ได้ส่งมาจาก 10.0.0.10 การจับคู่ด้วย --ctdir ORIGINAL จะจำกัดขอบเขตของกฎให้มีผลเฉพาะทิศทางจากไคลเอนต์ไปยังคอนเทนเนอร์เท่านั้น เพื่อไม่ให้แพ็กเก็ตตอบกลับถูกดักจับโดยไม่ตั้งใจ ให้แทนที่ eth0 ด้วยอินเทอร์เฟซสาธารณะของคุณ และ ip route | grep default คือชื่อของอินเทอร์เฟซนั้น ทดสอบด้วยวิธีเดียวกับก่อนหน้านี้: curl จากที่อยู่ที่ได้รับอนุญาตจะทำงานได้สำเร็จ ส่วนการเชื่อมต่อจากที่อื่นจะหมดเวลา (timeout) อาการค้างดังกล่าวเป็นสัญญาณบ่งบอกว่ากฎ DROP กำลังทำงานอยู่ ไม่ใช่เพราะไม่มีบริการรองรับที่พอร์ตนั้น และ ความแตกต่างระหว่างการปฏิเสธการเชื่อมต่อกับการเชื่อมต่อที่หมดเวลา เป็นวิธีที่เร็วที่สุดในการแยกแยะระหว่างพอร์ตที่ถูกกรองไว้กับบริการที่ไม่ได้เปิดใช้งานอยู่

กฎที่เพิ่มด้วยคำสั่ง iptables จะหายไปเมื่อรีบูตเครื่อง เนื่องจาก UFW จัดการไฟร์วอลล์ส่วนนี้อยู่แล้ว ตำแหน่งที่เหมาะสมที่สุดในการทำให้กฎคงอยู่ถาวรคือ /etc/ufw/after.rules ให้เพิ่มบล็อกคำสั่งไว้ที่ส่วนท้ายของไฟล์:

*filter
:DOCKER-USER - [0:0]
-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 8080 --ctdir ORIGINAL ! -s 10.0.0.10 -j DROP
COMMIT

จากนั้นให้รันคำสั่ง sudo ufw reload ตัว UFW จะโหลดไฟล์นี้ซ้ำทุกครั้งที่มีการ reload หรือบูตเครื่องใหม่ ดังนั้นการกรองคอนเทนเนอร์ของคุณจะถูกรวมไว้ในที่เดียวกับไฟร์วอลล์ส่วนอื่น และจะยังคงอยู่ทั้งหลังการรีบูตและการอัปเกรด Docker

เหตุผลที่คุณไม่ควรปิดการทำงานร่วมกันระหว่าง Docker กับ iptables

คำตอบเก่าๆ สำหรับปัญหานี้มักแนะนำให้ตั้งค่า { "iptables": false } ใน /etc/docker/daemon.json โปรดอย่าทำตาม กฎไฟร์วอลล์ของ Docker ทำหน้าที่มากกว่าแค่การเปิดพอร์ต กฎ masquerade คือสิ่งที่ทำให้คอนเทนเนอร์สามารถเข้าถึงอินเทอร์เน็ตภายนอกผ่านที่อยู่ของโฮสต์ได้ ดังนั้นหากปิดการทำงานส่วนนี้ คอนเทนเนอร์จะไม่สามารถดึง image, เข้าถึง package mirror หรือเรียกใช้ API (application programming interface) ภายนอกใดๆ ได้เลย กฎ DNAT คือสิ่งที่ทำให้ -p ทำงานได้ ดังนั้นหากปิดไป พอร์ตที่เปิดไว้จะหยุดทำงานทั้งหมด นอกจากนี้กฎการแยกเครือข่ายที่ช่วยให้ Compose network แต่ละวงแยกออกจากกันก็จะหายไปด้วย คุณกำลังพยายามแก้ไขปัญหาการข้ามผ่านกฎไฟร์วอลล์ด้วยการทำลายระบบเครือข่ายของคอนเทนเนอร์ และคุณจะต้องเป็นผู้เขียนและดูแลกฎเหล่านั้นทั้งหมดด้วยตนเอง เอกสารของ Docker ระบุชัดเจนว่าการตั้งค่านี้มีไว้สำหรับผู้ที่ตั้งใจจะจัดการกฎเครือข่ายด้วยตนเองเท่านั้น chain DOCKER-USER ถูกสร้างขึ้นมาเพื่อให้ไม่มีใครจำเป็นต้องใช้สวิตช์นี้อีกต่อไป

ปัญหาในส่วนของ IPv6

ขั้นแรกให้ตรวจสอบว่าพอร์ตที่เปิดใช้งานมีสถานะอย่างไรบน IPv6:

sudo ss -tlnp | grep 8080

ตั้งแต่ Docker Engine 27 เป็นต้นมา Docker จะจัดการ ip6tables เป็นค่าเริ่มต้น บนเครือข่าย Docker ที่เปิดใช้งาน IPv6 พอร์ตที่ถูกเปิดใช้งานจะได้รับการจัดการ DNAT ในตาราง IPv6 เช่นเดียวกัน ดังนั้นช่องโหว่ในการข้ามการกรองจึงเกิดขึ้นในลักษณะเดียวกันและใช้วิธีแก้ไขแบบเดียวกัน นั่นคือ chain DOCKER-USER ก็มีอยู่ใน ip6tables เช่นกัน ให้คุณคัดลอกกฎของคุณไปใช้กับ sudo ip6tables -I DOCKER-USER ... แล้วทดสอบจากภายนอกด้วย curl ไปยังที่อยู่ IPv6 สาธารณะของเซิร์ฟเวอร์ เช่น curl -6 http://[2001:db8:2a::1]:8080/

บนเครือข่ายที่ไม่มี IPv6 การเชื่อมต่อจากไคลเอนต์ IPv6 จะถูกจัดการโดย docker-proxy ซึ่งเป็นกระบวนการในระดับ user-space ที่คอยฟังบน [::]:8080 และส่งต่อทราฟฟิกเข้าไปยังคอนเทนเนอร์ผ่าน IPv4 ทราฟฟิกที่ส่งไปยังโฮสต์โพรเซสจะผ่าน INPUT ดังนั้น UFW จึงสามารถกรองเส้นทางนั้นได้ แต่จะทำได้ก็ต่อเมื่อ UFW มีการจัดการ IPv6 อยู่เท่านั้น ว่า UFW กำลังจัดการอยู่หรือไม่ และช่องโหว่ IPv6 อื่นๆ ที่อาจเกิดขึ้นบน VPS มีรายละเอียดอย่างไร สามารถศึกษาได้จาก คู่มือการใช้งาน UFW และ IPv6

การเปิดใช้งานพอร์ตบน loopback จะช่วยหลีกเลี่ยงปัญหาทั้งหมดนี้ได้ เนื่องจาก -p 127.0.0.1:8080:80 จะผูกกับ IPv4 loopback เท่านั้น จึงไม่มี listener บน IPv6 และไม่มีช่องทางให้เข้าถึงจากภายนอกได้ไม่ว่าจะผ่าน stack ใดก็ตาม

รูปแบบที่มั่นคง

  • เผยแพร่ทุกพอร์ตภายในบน 127.0.0.1 เพื่อไม่ให้พอร์ตเหล่านั้นถูกเปิดเผยตั้งแต่แรก
  • กำหนดให้ฝั่งสาธารณะอยู่ภายใต้ reverse proxy เพียงตัวเดียวที่ดูแลพอร์ต 80 และ 443
  • ตั้งค่า UFW ให้ปฏิเสธการเชื่อมต่อขาเข้าทั้งหมดเป็นค่าเริ่มต้น โดยอนุญาตเฉพาะ SSH และพอร์ตของ proxy เท่านั้น
  • กรองพอร์ตของ container ที่ต้องการให้เป็นสาธารณะจริงๆ ใน DOCKER-USER โดยจับคู่กับพอร์ตปลายทางเดิมและบันทึกค่าไว้ใน /etc/ufw/after.rules
  • เปิดใช้งานการทำงานร่วมกันระหว่าง Docker และ iptables ไว้ตามเดิม

เมื่อตั้งค่าเสร็จสิ้นเพียงครั้งเดียว จะช่วยลดปัญหาที่ไม่คาดคิดได้ โดย ufw status จะอธิบายสถานะของโฮสต์ และ DOCKER-USER จะอธิบายสถานะของ container จะไม่มีพอร์ตใดถูกเผยแพร่ออกไปโดยไม่ได้ตั้งใจ และคำสั่ง docker run -p ถัดไปที่คุณพิมพ์จะเผยแพร่เฉพาะสิ่งที่คุณต้องการอย่างแม่นยำ

FAQ

ทำไมฉันถึงเข้าถึง Docker container ได้ทั้งที่ UFW บล็อกพอร์ตนั้นไว้?

เพราะ Docker เผยแพร่พอร์ตด้วยกฎ DNAT ใน chain PREROUTING ซึ่งจะเขียนปลายทางของแพ็กเก็ตใหม่ไปยังที่อยู่ของ container ก่อนที่การกรองใดๆ จะเกิดขึ้น จากนั้นแพ็กเก็ตจะเดินทางผ่านเส้นทาง FORWARD ในขณะที่กฎของ UFW อยู่ใน INPUT ซึ่งเป็น chain ที่แพ็กเก็ตไม่เคยผ่านเข้าไป Firewall จึงไม่ถูกเรียกใช้งาน กฎการปฏิเสธ (deny) ของ UFW จึงไม่มีผลกับพอร์ตของ container ที่ถูกเผยแพร่ออกมา

ฉันจะทำให้ UFW บล็อกพอร์ตที่ Docker เผยแพร่ออกมาได้อย่างไร?

UFW ไม่สามารถทำได้ด้วยตัวเองเพราะกฎของมันอยู่ใน chain ที่ไม่ถูกต้อง คุณควรหยุดเผยแพร่พอร์ตนั้นโดยเปลี่ยนไปใช้ 127.0.0.1:8080:80 เพื่อให้เข้าถึงได้เฉพาะจาก host เท่านั้น หรือทำการกรองใน chain DOCKER-USER ด้วยกฎ iptables ที่จับคู่กับพอร์ตปลายทางเดิมผ่าน conntrack และบันทึกกฎนั้นไว้ใน /etc/ufw/after.rules เพื่อให้คงอยู่หลังการรีบูตและ ufw reload

ฉันควรตั้งค่า "iptables": false ในไฟล์ daemon.json ของ Docker หรือไม่?

ไม่ควร การตั้งค่าดังกล่าวจะลบกฎ firewall และ NAT ทั้งหมดของ Docker ซึ่งจะทำให้ระบบเสียหายมากกว่าแค่การข้ามการกรองของ firewall โดย container จะสูญเสียการเชื่อมต่ออินเทอร์เน็ตขาออกเนื่องจากกฎ masquerade หายไป และพอร์ตที่เผยแพร่ไว้จะใช้งานไม่ได้เนื่องจากกฎ DNAT หายไป ให้ใช้การเผยแพร่ผ่าน loopback และ chain DOCKER-USER แทน วิธีนี้จะแก้ไขปัญหาการเปิดเผยพอร์ตโดยไม่ทำให้ระบบเครือข่ายของ container เสียหาย

Docker ข้ามการทำงานของ UFW บน IPv6 ด้วยหรือไม่?

ใน Docker Engine 27 ขึ้นไป การจัดการ ip6tables จะถูกเปิดใช้งานเป็นค่าเริ่มต้น ดังนั้นพอร์ตที่เผยแพร่บนเครือข่าย Docker ที่รองรับ IPv6 จะถูกเขียนเส้นทางใหม่โดยข้าม UFW เช่นเดียวกับ IPv4 และจำเป็นต้องใช้กฎ DOCKER-USER เดียวกันโดยปรับใช้กับ ip6tables สำหรับเครือข่ายที่ไม่มี IPv6 กระบวนการ docker-proxy จะฟังที่ [::] และทราฟฟิกนั้นจะผ่าน INPUT ซึ่ง UFW สามารถกรองได้หากมีการตั้งค่าให้จัดการ IPv6 การเผยแพร่บน 127.0.0.1 จะช่วยหลีกเลี่ยงปัญหาทั้งสองกรณีได้ เนื่องจากไม่มีการฟังทราฟฟิกบน IPv6 เลย