Uncomplicated Firewall (UFW) ไม่ได้บล็อคอะไรเมื่อใช้ Docker


44

นี่เป็นครั้งแรกที่ฉันตั้งค่าเซิร์ฟเวอร์ Ubuntu (14.04 LTS) และฉันมีปัญหาในการกำหนดค่าไฟร์วอลล์ (UFW)

ฉันแค่ต้องการsshและhttpดังนั้นฉันกำลังทำสิ่งนี้:

sudo ufw disable

sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp

sudo ufw enable
sudo reboot

แต่ฉันยังสามารถเชื่อมต่อกับฐานข้อมูลบนพอร์ตอื่นของเครื่องนี้ได้ มีความคิดเกี่ยวกับสิ่งที่ฉันทำผิดหรือเปล่า?

แก้ไข : ฐานข้อมูลเหล่านี้อยู่ในคอนเทนเนอร์ Docker สิ่งนี้เกี่ยวข้องกันไหม มันจะเอาชนะการตั้งค่า ufw ของฉัน?

EDIT2 : ผลลัพธ์ของsudo ufw status verbose

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)

ฐานข้อมูลอะไร พอร์ตไหน คุณแน่ใจหรือว่านี่เป็นเครื่องเดียวกัน ผลลัพธ์ของ ufw status
solsTiCe

@ solsTiCe ใช่ฉันแน่ใจว่าเป็นเครื่องเดียวกัน ฐานข้อมูลเป็น InfluxDB (ในภาชนะนักเทียบท่าก) กับพอร์ตและ8083 8086ฉันเพิ่มufw status verboseผลลัพธ์ในคำถาม ขอบคุณ
ESala

คำตอบ:


63

ปัญหาคือการใช้การ-pตั้งค่าสถานะบนคอนเทนเนอร์

แต่กลับกลายเป็นว่าหางทำให้เกิดการเปลี่ยนแปลงของคุณโดยตรงบนซึ่งไม่ได้แสดงด้วยiptablesufw status

แนวทางแก้ไขที่เป็นไปได้คือ:

  1. หยุดใช้-pธง ใช้การเชื่อมโยงนักเทียบท่าหรือเครือข่ายนักเทียบท่าแทน

  2. ผูกภาชนะในพื้นที่เพื่อไม่ให้ถูกเปิดเผยนอกเครื่องของคุณ:

    docker run -p 127.0.0.1:8080:8080 ...

  3. หากคุณยืนยันที่จะใช้การ-pตั้งค่าสถานะบอกให้นักเทียบท่าไม่แตะต้องคุณiptablesโดยปิดใช้งาน/etc/docker/daemon.jsonและเริ่มต้นใหม่:

    { "iptables" : false }

ฉันแนะนำตัวเลือกที่ 1 หรือ 2 ระวังตัวเลือกที่ 3 มีผลข้างเคียงเช่นตู้คอนเทนเนอร์ไม่สามารถเชื่อมต่ออินเทอร์เน็ต


8
สิ่งนี้มีประโยชน์มาก - ฉันคลั่งไคล้ความสามารถในการเข้าถึงพอร์ตที่ฉันไม่ได้รับอนุญาตใน ufw การใช้ iptables = false จะแบ่งเป็นจำนวนมากเช่นเดียวกับที่คอนเทนเนอร์สามารถเข้าถึงได้บนโลคัลโฮสต์เช่นสำหรับการพร็อกซีย้อนกลับ ดีกว่าเพื่อให้แน่ใจว่าคอนเทนเนอร์ฟังถูกต้องอย่าใช้ -p 80:80 แต่ใช้ -p 127.0.0.1:80:80 หรือพอร์ตอื่นเช่น 127.0.0.1:3000:80 สำหรับการ proxying แบบย้อนกลับด้วย nginx หรือ apache และไม่มีพอร์ต การปะทะกัน
Andreas Reiff

2
@ อันธพาลขอให้คุณพูดถูก แต่เร็ว ๆ นี้ฉันได้พบว่ามันดีที่สุดที่จะหลีกเลี่ยง-pให้มากที่สุด ตัวอย่างเช่นในกรณีของ reverse proxy ฉันจะไม่จับคู่พอร์ตใด ๆ กับคอนเทนเนอร์ของผู้ปฏิบัติงานจากนั้นให้ใส่ nginx ลงในคอนเทนเนอร์ของตัวเอง-p 80:80และ a --linkไปยังที่อื่น ๆ วิธีนี้ไม่สามารถมีพอร์ตใด ๆ ได้และจุดเดียวในการเข้าถึงคือผ่าน nginx
ESala

1
ตรวจสอบโพสต์นี้สำหรับข้อควรระวังที่สามที่คุณต้องใช้! svenv.nl/unixandlinux/dockerufw
Henk

1
สำคัญ : /etc/default/dockerเป็นไฟล์กำหนดค่าที่ใช้โดยการกำหนดค่าเริ่มต้น หากคุณย้ายจาก upstart เป็น systemd ไฟล์นี้จะไม่ถูกใช้งาน
orshachar

@ESala คุณควรคิดถึงการยกเลิกการทำเครื่องหมายคำตอบนี้ว่าถูกต้องตั้งแต่ลงวันที่
ctbrown

8

16.04 นำเสนอความท้าทายใหม่ ฉันทำตามขั้นตอนทั้งหมดตามที่แสดงRunning Docker ด้านหลังไฟร์วอลล์ ufw แต่ฉันไม่สามารถรับ docker และ UFW เพื่อทำงานกับ 16.04 กล่าวอีกนัยหนึ่งไม่ว่าฉันจะทำอะไรที่พอร์ตนักเทียบท่าทุกคนกลายเป็นอินเทอร์เน็ตทั่วโลก จนกว่าฉันจะพบสิ่งนี้: วิธีตั้งค่า Docker 1.12+ ให้ไม่รบกวน IPTABLES / FirewallD

ฉันต้องสร้างไฟล์/etc/docker/daemon.jsonและใส่ต่อไปนี้ใน:

{
    "iptables": false
}

ฉันออกsudo service docker stopแล้วในsudo service docker startที่สุดนักเทียบท่าก็แค่ทำตามกฎที่เหมาะสมใน UFW

ข้อมูลเพิ่มเติม: นักเทียบท่าลบล้าง UFW!


ด้วย Ubuntu 16.04 และ Docker เวอร์ชัน 17.09 โซลูชันนี้จะหยุดการเชื่อมต่อขาออกจากคอนเทนเนอร์ ดูการตอบสนองaskubuntu.com/a/833363/262702และAskubuntu.com/a/954041/262702
ctbrown เมื่อ

4

หากคุณใช้ระบบ init ของ systemd (Ubuntu 15.10 ขึ้นไป) แก้ไข/etc/docker/daemon.json(อาจต้องสร้างถ้าไม่มีอยู่) ตรวจสอบให้แน่ใจว่ามีiptablesคีย์ที่กำหนดค่าไว้:

{   "iptables" : false }

แก้ไข : นี่อาจทำให้คุณขาดการเชื่อมต่อกับอินเทอร์เน็ตจากภายในคอนเทนเนอร์

หากคุณเปิดใช้งาน UFW ให้ตรวจสอบว่าคุณสามารถเข้าถึงอินเทอร์เน็ตได้จากตู้คอนเทนเนอร์ภายใน ถ้าไม่ใช่ - คุณต้องกำหนดDEFAULT_FORWARD_POLICYเป็นACCEPTเปิด/etc/default/ufwและใช้เคล็ดลับที่อธิบายไว้ที่นี่: https://stackoverflow.com/a/17498195/507564


2

วิธีแก้ปัญหาอย่างรวดเร็วคือเมื่อเรียกใช้ Docker และทำการแมปพอร์ต คุณสามารถทำได้

docker run ...-p 127.0.0.1:<ext pot>:<internal port> ...

เพื่อป้องกัน Docker ของคุณไม่ให้เข้าถึงจากภายนอก


2

การใช้/etc/docker/daemon.jsonกับเนื้อหา

{
  "iptables": false
}

อาจฟังดูเหมือนโซลูชันแต่ใช้งานได้จนกว่าการรีบูตครั้งถัดไปเท่านั้น หลังจากนั้นคุณอาจสังเกตเห็นว่าไม่มีคอนเทนเนอร์ใดที่สามารถเข้าถึงอินเทอร์เน็ตดังนั้นคุณจึงไม่สามารถยกตัวอย่างเช่น ping เว็บไซต์ใด ๆ มันอาจเป็นพฤติกรรมที่ไม่พึงประสงค์

เช่นเดียวกับการผูกคอนเทนเนอร์กับ IP เฉพาะ คุณอาจไม่ต้องการทำเช่นนั้น ตัวเลือกที่ดีที่สุดคือการสร้างที่เก็บและเก็บไว้ข้างหลัง UFW ไม่ว่าจะเกิดอะไรขึ้นและวิธีที่คุณสร้างคอนเทนเนอร์นี้ดังนั้นจึงมีวิธีแก้ไข:

หลังจากที่คุณสร้าง/etc/docker/daemon.jsonไฟล์ให้เรียกใช้:

sed -i -e 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/g' /etc/default/ufw
ufw reload

ดังนั้นคุณจึงตั้งค่านโยบายการส่งต่อเริ่มต้นใน UFW เพื่อยอมรับและใช้:

iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE

หากคุณกำลังจะใช้นักเทียบท่า-เขียนแล้ว IP จากคำสั่งดังกล่าวจะถูกแทนที่ด้วย IP docker-compose upของเครือข่ายนักเทียบท่า-เขียนสร้างเมื่อทำงานกับ

ฉันอธิบายปัญหาและแนวทางแก้ไขอย่างละเอียดมากขึ้นในบทความนี้

หวังว่ามันจะช่วย!


1

ในกรณีของฉันฉันได้ทำการแก้ไข iptables เพื่ออนุญาตให้เข้าถึง Docker จาก IP ที่ระบุเท่านั้น

ตามคำตอบของ ESala :

หากคุณใช้-pแฟล็กบนคอนเทนเนอร์ Docker ทำการเปลี่ยนแปลงโดยตรงกับ iptables โดยไม่สนใจ ufw

ตัวอย่างของเร็กคอร์ดที่เพิ่มลงใน iptables โดย Docker

การกำหนดเส้นทางไปยังเชน 'DOCKER':

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

การส่งต่อแพ็กเก็ตจากเชน 'DOCKER' ไปยังคอนเทนเนอร์:

-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6379 -j DNAT --to-destination 172.17.0.3:6379

คุณสามารถแก้ไข iptables เพื่อให้สามารถเข้าถึงเชน DOCKER จาก IP ต้นทางที่ระบุเท่านั้น (เช่น1.1.1.1):

-A PREROUTING -s 1.1.1.1 -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -s 1.1.1.1 ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

คุณอาจต้องการใช้iptables-save > /tmp/iptables.confและiptables-restore < /tmp/iptables.confการถ่ายโอนข้อมูลแก้ไขและกู้คืนกฎ iptables


0

ใช้ --network = โฮสต์เมื่อคุณเริ่มต้นคอนเทนเนอร์ดังนั้นนักเทียบท่าจะจับคู่พอร์ตกับเครือข่ายแยกโฮสต์เท่านั้นแทนเครือข่ายบริดจ์เริ่มต้น ฉันไม่เห็นวิธีทางกฎหมายในการปิดกั้นเครือข่ายบริดจ์ หรือคุณสามารถใช้เครือข่ายที่ผู้ใช้กำหนดเองพร้อมกับแยก


0
  1. ลงชื่อเข้าใช้คอนโซลนักเทียบท่าของคุณ:

    sudo docker exec -i -t docker_image_name / bin / bash

  2. และจากนั้นภายในคอนโซลนักเทียบท่าของคุณ:

    sudo apt-get update
    sudo apt-get install ufw
    sudo ufw allow 22
    
  3. เพิ่มกฎ ufw ของคุณและเปิดใช้งาน ufw

    sudo ufw เปิดใช้งาน

    • ภาพนักเทียบท่าของคุณต้องเริ่มต้นด้วย --cap-add = NET_ADMIN

วิธีเปิดใช้งานตัวเลือก "NET_ADMIN" Docker:

1. ภาชนะด้านบน:

นักเทียบท่าหยุด yourcontainer; 2. รับรหัสภาชนะ:

นักเทียบท่าตรวจสอบภาชนะของคุณ; 3.Modify hostconfig.json (เส้นทางนักเทียบท่าเริ่มต้น: / var / lib / docker คุณสามารถเปลี่ยนของคุณได้)

vim /var/lib/docker/containers/containerid/hostconfig.json

4. ค้นหา "CapAdd" และแก้ไข null เป็น ["NET_ADMIN"];

.... , "VolumesFrom": null, "CapAdd": ["NET_ADMIN"], "CapDrop": null, .... 5. เริ่มต้นตัวเทียบท่าในเครื่องโฮสต์

เริ่มบริการนักเทียบท่า; 6. เริ่มต้นตัวแปลงของคุณ;

นักเทียบท่าเริ่ม yourcontainer;


0

ฉันเคยdocker-composeเริ่มต้นตู้คอนเทนเนอร์หลายแห่งและยังมีปัญหาที่พอร์ตหนึ่งถูกเปิดเผยต่อโลกโดยไม่สนใจกฎของ ufw

การแก้ไขเพื่อทำให้พอร์ตพร้อมใช้งานกับคอนเทนเนอร์ของนักเทียบท่าของฉันคือการเปลี่ยนแปลงในdocker-compose.ymlไฟล์ของฉัน:

ports:
- "1234:1234"

สำหรับสิ่งนี้:

ports:
- "1234"

ตอนนี้คอนเทนเนอร์นักเทียบท่าอื่น ๆ ยังคงสามารถใช้พอร์ตได้ แต่ฉันไม่สามารถเข้าถึงได้จากภายนอก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.