IPTABLES - Stawka graniczna określonego przychodzącego adresu IP

103

Nie chcę ograniczać stawki określonej usługi. Moim celem jest ograniczenie stawki wyłącznie na podstawie przychodzącego adresu IP. Na przykład za pomocą pseudo-reguły:

john.domain.local (192.168.1.100) can only download from our httpd/ftp servers at "10KB/s" (instead of 1MB/s)

Jak mogę ograniczyć stawkę za pomocą IPTables opartych na przychodzących adresach IP?

James
źródło

Odpowiedzi:

165

IPTables nie jest przeznaczony do tego rodzaju pracy, w której wiele pakietów musi być analizowanych w celu podjęcia takich decyzji. IPTables jest jednak częściowo odpowiedzią!

Prawdziwą odpowiedzią na to są niesamowite i niedostatecznie wykorzystywane narzędzia kontroli ruchu w Linuksie. Pamiętaj, że robienie tego bez wiedzy o tym, co się dzieje, może doprowadzić do utraty połączenia sieciowego z maszyną! Zostałeś ostrzeżony!

Zakładając, że eth0 jest urządzeniem wychodzącym, będziesz musiał utworzyć opartą na klasach kolejkę kontroli ruchu, która domyślnie generuje większość ruchu przez kolejkę „szybką” i umieści określoną listę osób w kolejce „wolnej”.

Piękno tego polega na tym, że możesz stworzyć sytuację, w której zezwalasz na duży ruch wychodzący dla powolnego użytkownika, chyba że nadrzędna klasa chce przepustowości, ale ten przykład tego nie robi (zawsze zapewni 10 kb / s powolnym użytkownikom). System kolejkowania będzie wyglądał mniej więcej tak:

                         Inbound traffic
                              +
                              |
                              |
                              v
                     +------------------+
                     |   Class 1:1      |
                     |------------------|
                     |  Root (all flows)|
                     |       100mbit    |
                     +-----+-----+------+
                           |     |
                           |     |
                           |     |
                           |     |
                           |     |
          +----------+     |     |     +----------+
          |    1:11  +-----+     +-----+    1:12  |
          |----------|                 |----------|
          | Default  |                 | Slow     |
          |100mb-80kb|                 |   80kb   |
          +----------+                 +----------+

Aby to zrobić, najpierw musisz ustawić dyscyplinę kolejkowania w jądrze. Następujące czynności zrobią to za Ciebie. Musisz uruchomić jako jeden skrypt

#!/bin/bash
tc qdisc add dev eth0 parent root handle 1: hfsc default 11
tc class add dev eth0 parent 1: classid 1:1 hfsc sc rate 100mbit ul rate 100mbit
tc class add dev eth0 parent 1:1 classid 1:11 hfsc sc rate 99920kbit ul rate 100000kbit
tc class add dev eth0 parent 1:1 classid 1:12 hfsc sc rate 80kbit ul rate 80kbit

tc qdisc add dev eth0 parent 1:11 handle 11:1 pfifo
tc qdisc add dev eth0 parent 1:12 handle 12:1 pfifo

„Domyślna 11” jest ważna, ponieważ informuje jądro, co zrobić z ruchem niesklasyfikowanym.

Po wykonaniu tej czynności możesz skonfigurować regułę iptables, aby klasyfikować pakiety spełniające określone kryteria. Jeśli planujesz wsadzić wiele osób w tę wolną regułę, bardziej odpowiednia jest reguła ipset (uważam, że powinna być dostępna na rhel6).

Utwórz bazę danych ipset, aby dopasować ...

ipset create slowips hash:ip,port

Następnie utwórz regułę iptables, aby dopasować.

iptables -t mangle -I OUTPUT -m set --match-set slowips dst,src -j CLASSIFY --set-class 1:12

To instruuje jądro, że jeśli dopasujesz docelowy adres IP do portu źródłowego z zestawu, sklasyfikuj go w wolnej kolejce, którą ustawiasz z kontrolą ruchu.

Teraz, w końcu, kiedy chcesz spowolnić adres IP, możesz użyć polecenia ipset, aby dodać adres IP do zestawu, na przykład:

ipset add slowips 192.168.1.1,80
ipset add slowips 192.168.1.1,21
...

Możesz przetestować, czy działa, używając polecenia „tc -s class show dev eth0”, a zobaczysz tam statystyki wskazujące przekierowanie pakietów do wolnej kolejki.

Zauważ, że jedynym prawdziwym minusem tego jest przetrwanie restartów. Nie sądzę, aby były dostępne skrypty inicjujące do tworzenia ipsetów ze zrzutów przy ponownym uruchomieniu (i one również muszą zostać utworzone przed regułami iptables) i jestem pewien, że nie ma skryptów inicjujących do ponownego uruchomienia reguł kontroli ruchu przy ponownym uruchomieniu. Jeśli nie przejmujesz się tym, możesz po prostu odtworzyć całość z wywołania skryptu w rc.local.

Matthew Ife
źródło
3
Nie mogę ci wystarczająco podziękować. Jest to bardzo opisowe i bardzo pouczające. Później zdałem sobie sprawę, że znajomość TC będzie wymagana i od tego czasu zacząłem się tym zajmować. Dzięki jeszcze raz!
James
Aha, a co do utraty połączenia. Przed przejściem z VPS na komputer hosta upewniam się, że mam wyłączoną konfigurację. Ponadto mam dostęp VPN do prywatnej sieci na ETH0. Będę pracował tylko nad ETH1, więc teoretycznie nie będę miał problemu. Ale słyszałem ostrzeżenie!
James
2
Nie mogę ci powiedzieć, ile razy czytałem podobne samouczki, jest to pierwszy, który miał sens
RC1140
5
Na marginesie, zazwyczaj bardziej odpowiednie jest ograniczenie zasobów w ten sposób w grupach kontrolnych (znowu możliwe i również niewykorzystane i niesamowite), ponieważ można zdefiniować limity na procesor, pamięć, IO i sieć w scentralizowanym magazynie polityk „. Ale jeszcze nie widzieliśmy takiego pytania, aby udzielić odpowiedzi.
Matthew Ife
2
Jeśli nie podoba ci się tcskładnia, możesz spróbować tcng, który dodaje nieco bardziej przyjazny dla użytkownika język, który generuje tcpolecenia. Użyłem do tego jak w skryptach: echo '... multi line tcng configuration ...' | tcng | sh.
Mattias Wadman
5

To tak proste, jak przyjęcie reguły ograniczania prędkości i dodanie -sprzełącznika. -sPrzełącznik pasuje przychodzące IP. Na przykład, iptables -A INPUT -s 1.1.1.1a następnie kończąc na preferowanej metodzie ograniczania prędkości dla tej reguły.

Wesley
źródło
Dziękuję za szybką odpowiedź. Niestety moim głównym problemem jest druga połowa. Zajrzałem do --limit i nie widziałem niczego, co pozwala mi na ograniczenie na podstawie KB / s - w jakim kierunku możesz mnie wskazać?
James
1
@James Wróciłbym do ciebie, ale musiałem wyjść do domu przyjaciela. Właśnie wróciłem i widzę, że MIfe wykonał kawał dobrej roboty. =)
Wesley