Iptables: Abgleich des ausgehenden Datenverkehrs mit Conntrack und Eigentümer. Arbeitet mit seltsamen Tropfen

11

In meinem iptables-Skript habe ich versucht, so feinkörnige Regeln wie möglich zu schreiben. Ich beschränke mich darauf, welche Benutzer welche Dienste nutzen dürfen, teils aus Sicherheitsgründen, teils als Lernübung.

Verwenden von iptables v1.4.16.2 unter Debian 6.0.6 unter Ausführen des 3.6.2-Kernels.

Ich bin jedoch auf ein Problem gestoßen, das ich noch nicht ganz verstehe.

ausgehende Ports für alle Benutzer

Das funktioniert einwandfrei. Ich habe keine allgemeinen Statusverfolgungsregeln.

## Ausgehender Port 81
$ IPTABLES -A OUTPUT -p tcp --dport 81 -m conntrack --ctstate NEU, GEGRÜNDET -j AKZEPTIEREN
$ IPTABLES -A INPUT -p tcp --sport 81 -s $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT

ausgehende Ports mit Benutzeranpassung

## ausgehender Port 80 für Benutzerkonto
$ IPTABLES -A OUTPUT - Match-Besitzer - UID-Besitzer Benutzerkonto -p TCP --dport 80 -m Conntrack --ctstate NEU, GEGRÜNDET --sport 1024: 65535 -j AKZEPTIEREN
$ IPTABLES -A INPUT -p tcp --sport 80 --dport 1024: 65535 -d $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT

Dadurch kann Port 80 nur für das Konto "Benutzerkonto" ausgegeben werden, aber Regeln wie diese für den TCP-Verkehr haben Probleme.

## Standardregeln für ausgehende Protokolle + Blockierungen
$ IPTABLES -A OUTPUT -j LOG --log-Präfix "BAD OUTGOING" --log-ip-options --log-tcp-options --log-uid
$ IPTABLES -A OUTPUT -j DROP

Die Angelegenheit

Das obige funktioniert, der Benutzer "Benutzerkonto" kann Dateien einwandfrei erhalten. Kein anderer Benutzer im System kann ausgehende Verbindungen zu Port 80 herstellen.

Benutzerkonto @ Host: $ wget http://cachefly.cachefly.net/10mb.test

Aber das obige Wget hinterlässt x7 abgelegte Einträge in meinem Syslog:

18. Oktober 02:00:35 xxxx Kernel: BAD OUTGOING IN = OUT = eth0 SRC = xx.xx.xx.xx DST = 205.234.175.175 LEN = 40 TOS = 0x00 PREC = 0x00 TTL = 64 ID = 12170 DF PROTO = TCP SPT = 37792 DPT = 80 SEQ = 164520678 ACK = 3997126942 WINDOW = 979 RES = 0x00 ACK URGP = 0  

Ich bekomme diese Drops nicht für ähnliche Regeln mit UDP-Verkehr. Ich habe bereits Regeln festgelegt, die einschränken, welche Benutzer DNS-Anfragen stellen können.

Die verworfenen ausgehenden ACK-Pakete scheinen vom Root-Konto (URGP = 0) zu stammen, was ich nicht verstehe. Auch wenn ich das Benutzerkonto gegen root tausche.

Ich glaube, dass ACK-Pakete als neu eingestuft werden, da conntrack nach dem dritten Schritt des 3-Wege-Handshakes beginnt, Verbindungen zu verfolgen, aber warum werden die Pakete verworfen?

Können diese Tropfen ignoriert werden?

Bearbeiten

Daher sehe ich oft Regeln wie diese, die für mich gut funktionieren:

$ IPTABLES -A OUTPUT -s $ MYIP -p tcp -m tcp --dport 80 -m state --state NEW, ESTABLISHED -j ACCEPT
$ IPTABLES -A INPUT -p tcp -m tcp --sport 80 -d $ MYIP -m state --state ESTABLISHED -j ACCEPT

Ich habe "-m state --state" gegen "-m conntrack --ctstate" getauscht, da die Statusübereinstimmung anscheinend veraltet ist.

Ist es eine bewährte Methode, allgemeine Regeln für die Statusverfolgung zu haben? Werden die oben genannten Regeln nicht als korrekt angesehen?

Wäre so etwas für eine strenge Kontrolle über ausgehende Benutzerverbindungen besser?

$ IPTABLES -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
$ IPTABLES -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

$ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m Eigentümer --uid-Eigentümer Benutzerkonto -j AKZEPTIEREN

$ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m Eigentümer --uid-Eigentümer otheraccount -j ACCEPT
arcX
quelle
Könnten Sie bitte alle Regeln einschließlich FORWARD-Kette und Nat-Tabelle posten, wenn dieser Host auch den Datenverkehr vom LAN weiterleitet?
Serge
Dieser Host führt kein Routing durch. Der Datenverkehr stammt mit diesen Regeln vom Computer. Ich habe nur die relevanten Regeln für bestimmten ausgehenden Verkehr veröffentlicht.
arcX

Antworten:

16

Um es kurz zu machen, diese ACK wurde gesendet, als die Steckdose niemandem gehörte. Anstatt Pakete zuzulassen, die sich auf einen Socket beziehen, der dem Benutzer gehört x, lassen Sie Pakete zu, die sich auf eine Verbindung beziehen, die von einem Socket vom Benutzer initiiert wurde x.

Die längere Geschichte.

Um das Problem zu verstehen, ist es hilfreich zu verstehen, wie wgetund HTTP-Anforderungen im Allgemeinen funktionieren.

Im

wget http://cachefly.cachefly.net/10mb.test

wgetstellt eine TCP-Verbindung zu her cachefly.cachefly.netund sendet nach dem Herstellen eine Anfrage im HTTP-Protokoll, die besagt: "Bitte senden Sie mir den Inhalt von /10mb.test( GET /10mb.test HTTP/1.1). Übrigens, können Sie die Verbindung bitte nicht schließen, nachdem Sie fertig sind ( Connection: Keep-alive). Der Grund Dies liegt daran, dass der Server die Verbindung wiederverwenden kann, falls er mit einer Umleitung für eine URL mit derselben IP-Adresse antwortet.

Jetzt kann der Server entweder antworten: "Hier kommen die von Ihnen angeforderten Daten, achten Sie darauf, dass sie 10 MB groß sind ( Content-Length: 10485760), und ja, OK, ich lasse die Verbindung offen." Oder wenn die Größe der Daten nicht bekannt ist: "Hier sind die Daten. Leider kann ich die Verbindung nicht offen lassen, aber ich werde Ihnen mitteilen, wann Sie den Download der Daten beenden können, indem Sie mein Verbindungsende schließen."

In der obigen URL sind wir im ersten Fall.

Sobald wgeter die Header für die Antwort erhalten hat, weiß er, dass seine Arbeit erledigt ist, sobald er 10 MB Daten heruntergeladen hat.

Grundsätzlich werden wgetdie Daten gelesen, bis 10 MB empfangen wurden, und beendet. Aber an diesem Punkt gibt es noch mehr zu tun. Was ist mit dem Server? Es wurde gesagt, die Verbindung offen zu lassen.

wgetSchließt vor dem Beenden ( closeSystemaufruf) den Dateideskriptor für den Socket. Anschließend closebeendet das System die Bestätigung der vom Server gesendeten Daten und sendet eine FINMeldung: "Ich werde keine weiteren Daten senden". An diesem Punkt closekehrt zurück und wird beendet wget. Der TCP-Verbindung ist kein Socket mehr zugeordnet (mindestens keiner, der einem Benutzer gehört). Es ist jedoch noch nicht fertig. Nach dem Empfang FINsieht der HTTP-Server das Dateiende, wenn er die nächste Anforderung vom Client liest. In HTTP bedeutet das "keine Anfrage mehr, ich werde mein Ende schließen". Also sendet es auch seine FIN, um zu sagen: "Ich werde auch nichts senden, diese Verbindung wird unterbrochen."

Nach Erhalt dieser FIN sendet der Client eine "ACK". Aber zu diesem Zeitpunkt wgetist es längst vorbei, so dass ACK nicht von einem Benutzer stammt. Aus diesem Grund wird es von Ihrer Firewall blockiert. Da der Server die ACK nicht empfängt, wird die FIN immer wieder gesendet, bis sie aufgibt und Sie mehr abgelegte ACKs sehen. Das bedeutet auch, dass Sie durch das Löschen dieser ACKs für einige Zeit unnötig Ressourcen des Servers verwenden (der einen Socket im Status LAST-ACK halten muss).

Das Verhalten wäre anders gewesen, wenn der Client nicht "Keep-Alive" angefordert hätte oder der Server nicht mit "Keep-Alive" geantwortet hätte.

Wie bereits erwähnt, möchten Sie bei Verwendung des Verbindungs-Trackers jedes Paket im Status ESTABLISHED und RELATED durchlassen und sich nur um NEWPakete kümmern .

Wenn Sie NEWPakete vom Benutzer zulassen, xaber keine Pakete vom Benutzer y, werden andere Pakete für vom Benutzer hergestellte Verbindungen xdurchlaufen, und weil vom Benutzer keine Verbindungen hergestellt werden können y(da wir die NEWPakete blockieren , die die Verbindung herstellen würden). Es wird kein Paket für Benutzerverbindungen ydurchlaufen.

Stéphane Chazelas
quelle
3

Dadurch kann Port 80 nur für das Konto "Benutzerkonto" ausgegeben werden.

- Nun, zumindest implizieren die Regeln, die Sie gezeigt haben, dies nicht.

Es gibt auch einen Raum für Ratschläge - überprüfen Sie die Benutzer nicht auf ESTABLISHED-Streams, sondern nur auf NEW. Ich sehe auch keinen Grund darin, den Quellport zu überprüfen, wenn ich Incoming ESTABLISHED überprüfe. Was ist der Unterschied, welcher Port es war? Es befindet sich bereits im Status ESTABLISHED gegenüber dem PoV von conntrack. Die Firewall sollte so einfach wie möglich, aber dennoch effizient sein, sodass der Rasiermesser- Ansatz von Occam am besten passt.

poige
quelle
1
Danke für den Hinweis. Normalerweise bin ich der Einfachheit halber, aber das ist nicht der Punkt dieser speziellen Übung.
arcX
1
@arcX, diese Übung kann fehlschlagen, weil sie zu komplex und inkonsistent ist. IOW, das angezeigte Verhalten kann nicht auf Netfilter-Interna (Fehler, Macken) zurückzuführen sein, sondern auf die Art und Weise, wie Sie es verwenden. Versuchen Sie zuerst, den Regelsatz zu vereinfachen ...
Poige