Docker
Iptables med Docker
Sök…
Introduktion
Det här ämnet handlar om hur du begränsar åtkomst till dina dockarcontainrar från omvärlden med iptables.
För otåliga människor kan du kontrollera exemplen. För de andra, läs kommentaravsnittet för att förstå hur du bygger nya regler.
Syntax
- iptables -I DOCKER [RULE ...] [ACCEPT | DROP] // För att lägga till en regel a toppen av DOCKER-tabellen
- iptables -D DOCKER [RULE ...] [ACCEPT | DROP] // Ta bort en regel från DOCKER-tabellen
- ipset-återställning </etc/ipriends.conf // För att konfigurera om ipset- ipvänner
parametrar
parametrar | detaljer |
---|---|
ext_if | Ditt externa gränssnitt på Docker-värden. |
XXX.XXX.XXX.XXX | En särskild IP-adress för vilken Docker behållares åtkomst bör ges. |
yyy.yyy.yyy.yyy | En annan IP-adress som Docker behållar åtkomst bör ges. |
ipfriends | Ipset-namnet som definierar IP: erna som får åtkomst till dina Docker-behållare. |
Anmärkningar
Problemet
Det är lite svårt att konfigurera iptables-regler för Docker-containrar. Till att börja med skulle du tro att "klassiska" brandväggsregler borde göra tricket.
Låt oss till exempel anta att du har konfigurerat en nginx-proxy-behållare + flera servicebehållare för att exponera via HTTPS vissa personliga webbtjänster. Då bör en regel som denna ge åtkomst till dina webbtjänster endast för IP XXX.XXX.XXX.XXX.
$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP
Det fungerar inte, dina containrar är fortfarande tillgängliga för alla.
Faktum är att Docker-containrar inte är värdtjänster. De förlitar sig på ett virtuellt nätverk i din värd, och värden fungerar som en gateway för detta nätverk. Och när det gäller gateways, hanteras inte dirigerad trafik av INPUT-tabellen utan av FORWARD-tabellen, vilket gör att regeln publiceras innan den är ineffektiv.
Men det är inte allt. I själva verket skapar Docker-demonen en hel del iptables-regler när den börjar göra sin magi när det gäller containernätverk. I synnerhet skapas en DOCKER-tabell för att hantera regler om containrar genom att vidarebefordra trafik från FORWARD-tabellen till denna nya tabell.
$ 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
Lösningen
Om du kontrollerar den officiella dokumentationen ( https://docs.docker.com/v1.5/articles/networking/) ges en första lösning för att begränsa Docker-behållarens åtkomst till en viss IP.
$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
Att lägga till en regel överst på DOCKER-bordet är verkligen en bra idé. Det stör inte reglerna som automatiskt konfigurerats av Docker, och det är enkelt. Men två stora brister:
- Först, vad händer om du behöver åtkomst från två IP istället för en? Här kan bara en src IP accepteras, andra kommer att släppas utan något sätt att förhindra det.
- För det andra, vad händer om din dockare behöver tillgång till Internet? Pratiskt kommer ingen begäran att lyckas, eftersom bara servern 8.8.8.8 kan svara på dem.
- Slutligen, om du vill lägga till andra logiker? Ge till exempel åtkomst till alla användare till din webbserver som serverar med HTTP-protokoll, men begränsa allt annat till särskild IP.
För den första observationen kan vi använda ipset . Istället för att tillåta en IP i regeln ovan tillåter vi alla IP: er från den fördefinierade ipset. Som en bonus kan ipset uppdateras utan nödvändighet att omdefiniera iptable-regeln.
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
För den andra observationen är detta ett kanoniskt problem för brandväggar: om du får kontakta en server via en brandvägg, bör brandväggen auktorisera servern att svara på din begäran. Detta kan göras genom att auktorisera paket som är relaterade till en etablerad anslutning. För dockarlogiken ger den:
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT
Den sista observationen fokuserar på en punkt: iptables-regler är viktiga. Faktum är att ytterligare logik för att acceptera vissa anslutningar (inklusive den som gäller ESTABLICERADE anslutningar) måste placeras överst på DOCKER-tabellen, innan DROP-regeln som förnekar alla återstående anslutningar som inte matchar ipset.
Eftersom vi använder -I-alternativet iptable, som infogar regler längst upp i tabellen, måste tidigare iptables-regler införas i omvänd ordning:
// 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
Med allt detta i åtanke kan du nu kontrollera exemplen som illustrerar denna konfiguration.
Begränsa åtkomst på Docker-containrar till en uppsättning IP: er
Installera ipset om det behövs. Se din distribution för att veta hur du gör det. Som exempel är här kommandot för Debian-liknande distributioner.
$ apt-get update
$ apt-get install ipset
Skapa sedan en konfigurationsfil för att definiera en ipset som innehåller IP: erna för vilka du vill öppna åtkomst till dina Docker-behållare.
$ 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
Ladda den här ipset.
$ ipset restore < /etc/ipfriends.conf
Se till att din Docker-demon körs: inget fel bör visas efter att du har angett följande kommando.
$ docker ps
Du är redo att infoga dina iptables-regler. Du måste respektera beställningen.
// 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
Om du vill skapa nya regler måste du ta bort alla anpassade regler som du har lagt till innan du sätter in de nya.
$ 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
Konfigurera begränsningsåtkomst när Docker-demon startar
Pågående arbete
Vissa anpassade iptables-regler
Pågående arbete