Iptables नियम-सेट ताकि एक डॉक कंटेनर एक होस्ट आईपी पर एक सेवा तक पहुंच सके


18

मुझे एक डॉकटर कंटेनर से एक होस्ट निजी इंटरफ़ेस (आईपी) तक पहुंचने में परेशानी है। मुझे पूरा यकीन है कि यह मेरे Iptables नियमों (या शायद रूटिंग) से संबंधित है। जब मैं --net=hostझंडा जोड़ता हूं docker run, तो सब कुछ उम्मीद के मुताबिक काम करता है। इसी तरह जब मैं निर्दिष्ट करता हूं कि INPUT नीति एक उदारता का पालन कर रही है -P INPUT ACCEPT, तो चीजें भी उसी तरह काम करेंगी जैसी मैं अपेक्षा करता हूं। हालाँकि ये अवांछनीय और असुरक्षित विकल्प हैं जिनसे मैं बचना चाहूँगा।

चूंकि यह मेरी सेवाओं (डीएनएस) के लिए विशिष्ट नहीं है, इसलिए मैंने इस समस्या को छोड़ दिया है, क्योंकि खोज परिणामों के लिए शोर जोड़ते हुए एक अलग (लोकप्रिय) समस्या क्षेत्र में डॉक पैदावार के साथ संयोजन में खोज की जाती है।

इसके अलावा डॉकटर कंटेनरों को जोड़ना एक व्यवहार्य विकल्प नहीं है, क्योंकि कुछ कंटेनरों को --net = होस्ट विकल्प के साथ चलाने की जरूरत है, जिससे लिंकिंग को रोका जा सके और मैं जहां संभव हो एक सुसंगत स्थिति बनाना चाहता हूं।

मेरे पास निम्नलिखित Iptables नियम हैं। कोरओएस, डिजिटल ओशन और डॉकर का एक संयोजन मुझे लगता है।

-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT

मेरे (प्रासंगिक) होस्ट इंटरफेस:

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

और मैं एक डॉकटर कंटेनर चलाता हूं:

$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.

इस बिंदु पर मैं 10.129.112.210:53 पर बंधी एक स्थानीय सेवा का उपयोग करने में सक्षम होना चाहता हूं। ताकि निम्नलिखित को उत्तर मिले:

$ ping google.com
^C
$ ping user.skydns.local
^C

जब मैं अपने मेजबान से एक ही कमांड चलाता हूं:

$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C

मेरा resolv.conf

$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4

यहाँ बात सार्वजनिक होस्ट तक पहुँचने की नहीं है, बल्कि आंतरिक लोगों की है, जो होस्ट पर उपलब्ध स्थानीय DNS सेवा का उपयोग कर रहे हैं (दूसरे डॉकटर उदाहरण के माध्यम से)।

इसे और भी स्पष्ट करने के लिए (मेरी अस्की आर्ट डिज़ाइन स्किल्स मेरे iptables फू को पार करती हैं, ताकि इस बिंदु पर पर्याप्त कहें):

 ______________________________________________
|  __________________________           Host   |
| |   Docker DNS container   |                 |
|  ``````````````````````|```                  |
|                        |                     |
|     ,----------,---( private n. interface )  |
|     |          |                             |
|     |          |   ( public  n. interface )---
|     |          |                             |
|     |          |   ( loopbck n. interface )  |
|     |          |                             |
|     |          |                             |
|     |        __|_______________________      |
|     |       | Docker service container |     |
|     |        ``````````````````````````      |
|     |                                        |
|     |                                        |
| [ Local host service using DNS. ]            |
|                                              |
|______________________________________________|

  private (host) network interface: eth1 (10.129.0.0/16)
  Docker network interface: docker0 (172.17.0.0/16)

मैंने अलग-अलग उदाहरण Iptables कॉन्फ़िगरेशन खोजे, पढ़े और लागू किए हैं, लेकिन मुझे पता है कि अधिक "उन्नत" Iptables नियमों का बहुत कम पता है कि व्हाट्सएप चल रहा है और इस प्रकार वांछित परिणाम प्राप्त करने के लिए।

का आउटपुट iptables -t nat -nL:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0

Chain DOCKER (2 references)
target     prot opt source               destination

का आउटपुट cat /proc/sys/net/ipv4/ip_forward:

1

आप के उत्पादन पोस्ट कर सकते हैं iptables -t nat -nL? क्या आपने कोई पैकेट विश्लेषण किया, कहा कि स्रोत कंटेनर से एक पिंग करें और मेजबान पर पैकेट को पकड़ने के लिए tcpdump का उपयोग करें।
डैनियल टी।

निश्चित रूप से, अब तक मदद करने के लिए धन्यवाद: pastebin.com/TAaT73nk (टिप्पणी फिट नहीं है ..) - संपादित करें -> एक pastebin के लिए लिंक अपडेट करें जो समाप्त नहीं होता है।
डायनाम जूल

शायद मैं आपकी समस्या को ठीक से नहीं समझ पाया, लेकिन मुझे होस्ट पर DNS प्रश्नों की अनुमति देने के लिए कोई नियम नहीं दिखता है। इसके अलावा, ip_forward सक्षम है?
लॉरेंटियू रोस्कु

हाय @LententiuRoescu। $ cat /proc/sys/net/ipv4/ip_forward -> 1और निजी इंटरफ़ेस -A INPUT -i eth1 -j ACCEPTपर सभी कनेक्शन स्वीकार करता है। क्या नियम याद आ रहे हैं?
डायनाम जूल

2
मुझे लगता है कि कंटेनर से पैकेट docker0 इंटरफ़ेस से आते हैं, न कि eth1। कोशिश करें-A INPUT -i docker0 -j ACCEPT
लॉरेंटियू रोस्कु

जवाबों:


14

कंटेनर docker0इंटरफ़ेस का उपयोग करके होस्ट के साथ संचार करता है। कंटेनर जोड़ने से यातायात की अनुमति देने के लिए:

-A INPUT -i docker0 -j ACCEPT

2
डायनम, एक सबक जिसे आप इससे दूर करना चाहते हैं वह यह है कि आपके सभी रीफ़सलों को लॉग करना उपयोगी है, जैसे कि iptables -A INPUT -j LOG। स्टैंप वर्क IN=docker0आउट करने में बहुत उपयोगी होता है कि रूल को किस नियम की आवश्यकता होती है। लॉरेंटियू के काम से दूर नहीं होने के लिए, जो उत्कृष्ट था - मुझ से +1!
मदहैटर

5
UFW का उपयोग करने वाले लोगों के लिए, मैंने डॉकटर कंटेनरों से सभी संचारों को होस्ट करने की अनुमति देने के लिए यहां क्या किया है: ufw docker0 पर अनुमति देता है
अली ओके

0

मैं बहुत ही ऐसी ही स्थिति का सामना कर चुका हूं, लेकिन जोड़ने -A INPUT -i docker0 -j ACCEPTसे कंटेनर तक मेरे do0 होस्ट के eth0 इंटरफ़ेस पर सभी एक्सेस खुल जाएंगे, जो कि मेरा इरादा बिल्कुल नहीं है।

और जब से मैंने देखा कि मेरे कंटेनर में होस्ट नेटवर्क से पूरी तरह से बंद होने के बजाय इंटरफ़ेस तक होस्ट एक्सेस (केवल पोर्ट 22) है, तो मैंने अपने iptables नियमों की समीक्षा की और श्रृंखला IN_public_allow में एक नियम पाया जो इसके लिए जिम्मेदार होना चाहिए। नियम है -A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT। इसलिए मैंने अपने कंटेनर को वांछित अन्य होस्ट पोर्ट तक पहुंचने की अनुमति देने के लिए समान नियम जोड़े, जो मुझे लगता है कि कंटेनरों में मेजबान नेटवर्क एक्सेस को खोलने के लिए थोड़ा और सटीक तरीका हो सकता है।


-i docker0यह सुनिश्चित करना चाहिए कि यह यातायात को प्रभावित नहीं करेगा जो docker0 नेटवर्क के माध्यम से नहीं आता है। आपका व्याकरण हालांकि अस्पष्ट है। शायद आप कह रहे थे कि eth0 के माध्यम से docker होस्ट्स के आउटगोइंग एक्सेस को सक्षम किया गया था, जो सच हो सकता है। मैं इस बात से सहमत हूं कि अधिक लक्षित नियम केवल उतने ही खुलने वाले हैं जितने की जरूरत है।
mc0e
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.