Szukaj…


Wprowadzenie

W tym temacie opisano, jak ograniczyć dostęp do kontenerów dokerów ze świata zewnętrznego za pomocą iptables.

Dla niecierpliwych możesz sprawdzić przykłady. W przypadku pozostałych zapoznaj się z sekcją uwag, aby dowiedzieć się, jak tworzyć nowe reguły.

Składnia

  • iptables -I DOCKER [ZASADA ...] [AKCEPTUJ | DROP] // Aby dodać regułę do góry tabeli DOCKER
  • iptables -D DOCKER [ZASADA ...] [AKCEPTUJ | DROP] // Aby usunąć regułę ze tabeli DOCKER
  • ipset restore </etc/ipfriends.conf // Aby ponownie skonfigurować ipset ipfriends

Parametry

Parametry Detale
ext_if Twój zewnętrzny interfejs na hoście Docker.
XXX.XXX.XXX.XXX Należy podać konkretny adres IP, do którego mają dostęp pojemniki Docker.
RRRR.RRR.RRR.RRR Należy podać kolejny adres IP, do którego mają dostęp pojemniki Docker.
ipfriends Nazwa ipset definiująca adresy IP pozwalające na dostęp do kontenerów Docker.

Uwagi

Problem

Konfigurowanie reguł iptables dla kontenerów Docker jest nieco trudne. Na początku można by pomyśleć, że „klasyczne” reguły zapory powinny wystarczyć.

Załóżmy na przykład, że skonfigurowałeś kontener nginx-proxy + kilka kontenerów usług, aby udostępniać za pośrednictwem HTTPS niektóre osobiste usługi sieciowe. Wtedy taka reguła powinna zapewniać dostęp do twoich usług sieciowych tylko dla IP XXX.XXX.XXX.XXX.

$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP

To nie zadziała, Twoje pojemniki są nadal dostępne dla wszystkich.

Rzeczywiście, kontenery Docker nie są usługami hosta. Opierają się na wirtualnej sieci w twoim hoście, a host działa jako brama dla tej sieci. Jeśli chodzi o bramy, routowany ruch nie jest obsługiwany przez tabelę INPUT, ale przez tabelę FORWARD, co powoduje, że reguła wysłana przed nieefektywna.

Ale to nie wszystko. W rzeczywistości demon Docker tworzy wiele reguł iptables, kiedy zaczyna robić swoją magię dotyczącą łączności sieciowej kontenerów. W szczególności tworzona jest tabela DOCKER do obsługi reguł dotyczących kontenerów poprzez przekazywanie ruchu z tabeli FORWARD do tej nowej tabeli.

$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:https
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Rozwiązanie

Jeśli sprawdzisz oficjalną dokumentację ( https://docs.docker.com/v1.5/articles/networking/) , otrzymasz pierwsze rozwiązanie w celu ograniczenia dostępu kontenera Docker do jednego konkretnego adresu IP.

$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

Rzeczywiście, dobrym pomysłem jest dodanie reguły u góry tabeli DOCKER. Nie koliduje z regułami automatycznie konfigurowanymi przez Dockera i jest prosty. Ale dwa główne braki:

  • Po pierwsze, jeśli potrzebujesz dostępu z dwóch adresów IP zamiast jednego? Tutaj można zaakceptować tylko jeden adres IP src, inny zostanie usunięty bez żadnego sposobu, aby temu zapobiec.
  • Po drugie, co jeśli twój doker potrzebuje dostępu do Internetu? Praktycznie żadne żądanie nie powiedzie się, ponieważ tylko serwer 8.8.8.8 może na nie odpowiedzieć.
  • Wreszcie, co jeśli chcesz dodać inne logiki? Na przykład daj każdemu użytkownikowi dostęp do swojego serwera WWW obsługującego protokół HTTP, ale ogranicz wszystko inne do określonego adresu IP.

Do pierwszej obserwacji możemy użyć ipset . Zamiast zezwalać na jeden adres IP w powyższej regule, zezwalamy na wszystkie adresy IP ze wstępnie zdefiniowanego zestawu IP. Jako bonus, ipset można aktualizować bez konieczności redefiniowania reguły iptable.

$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP

W przypadku drugiej obserwacji jest to kanoniczny problem w przypadku zapór ogniowych: jeśli możesz skontaktować się z serwerem za pośrednictwem zapory ogniowej, wówczas zapora ogniowa powinna upoważnić serwer do odpowiedzi na żądanie. Można tego dokonać, autoryzując pakiety związane z nawiązanym połączeniem. Dla logiki dokowania daje:

$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Ostatnia obserwacja koncentruje się na jednym punkcie: zasady iptables są niezbędne. Rzeczywiście, dodatkowa logika AKCEPTUJĄ niektóre połączenia (w tym dotyczące ESTABLISHED) musi być umieszczona na górze tabeli DOCKER, przed regułą DROP, która odrzuca wszystkie pozostałe połączenia niezgodne z ipsetem.

Ponieważ używamy opcji -I programu iptable, która wstawia reguły u góry tabeli, poprzednie reguły iptables należy wstawiać w odwrotnej kolejności:

// Drop rule for non matching IPs
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
// Then Accept rules for established connections
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT 
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 3rd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 2nd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 1st custom accept rule

Mając to wszystko na uwadze, możesz teraz sprawdzić przykłady ilustrujące tę konfigurację.

Ogranicz dostęp do kontenerów Docker do zestawu adresów IP

Najpierw zainstaluj ipset, jeśli to konieczne. Sprawdź swoją dystrybucję, aby dowiedzieć się, jak to zrobić. Jako przykład, oto polecenie dla dystrybucji podobnych do Debiana.

$ apt-get update
$ apt-get install ipset

Następnie utwórz plik konfiguracyjny, aby zdefiniować ipset zawierający adresy IP, dla których chcesz otworzyć dostęp do kontenerów Docker.

$ vi /etc/ipfriends.conf
# Recreate the ipset if needed, and flush all entries
create -exist ipfriends hash:ip family inet hashsize 1024 maxelem 65536
flush
# Give access to specific ips
add ipfriends XXX.XXX.XXX.XXX
add ipfriends YYY.YYY.YYY.YYY

Załaduj ten ipset.

$ ipset restore < /etc/ipfriends.conf

Upewnij się, że demon Docker działa: po wprowadzeniu następującego polecenia nie powinien być wyświetlany żaden błąd.

$ docker ps

Jesteś gotowy, aby wstawić swoje reguły iptables. Musisz szanować porządek.

// All requests of src ips not matching the ones from ipset ipfriends will be dropped.
$ iptables -I DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
// Except for requests coming from a connection already established.
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Jeśli chcesz utworzyć nowe reguły, przed wstawieniem nowych musisz usunąć wszystkie niestandardowe reguły, które dodałeś.

$ iptables -D DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
$ iptables -D DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Skonfiguruj dostęp do ograniczeń podczas uruchamiania demona Docker

Praca w toku

Niektóre niestandardowe reguły iptables

Praca w toku



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow