Ausgehenden User-Traffic begrenzen

s24!

Registered User
Guten Abend,

es geht um ein Shared Hosting bzw. darum, dass die User fsockopen und url_fopen "genießen" können. Damit lässt sich natürlich sehr viel Mist bauen. Daher ist userspezifischer Traffic limitiert:
Code:
iptables -A OUTPUT -o eth0 -m owner --uid-owner %owner% -j DROP
iptables -I OUTPUT -p tcp -o eth0 -m owner --uid-owner %owner% -m state --state NEW -m recent --update --seconds %limitsec% --hitcount %limitcount% --name LIMIT_%owner% -j DROP"
iptables -I OUTPUT -p tcp -o eth0 -m owner --uid-owner %owner% -m state --state NEW -m recent --set  --name LIMIT_%owner%
Begrenzt wird hierbei auf 30 Requests in 60 Sekunden (diese Werte stehen in einem Array). Scheint für die meisten Anwendungen auszureichen, schützt aber dennoch vor ausgehendem DoS (o.ä.).

Meine eigentliche Frage ist jetzt:
Macht es Sinn, dass nur TCP durchgelassen wird? Schränkt das den Webspace-User ein oder macht man mit z.B. UDP eher Mist? Wie gesagt, das sind Webspaces - mir ist nichts bekannt, wofür man mehr als TCP braucht - aber vielleicht denk ich einfach nicht weit genug.
Oder sollte man doch ganz anders vorgehen? ;)


Danke im Voraus für die Antworten!

Edit:
iptables -L gibt solche Sachen aus:
Code:
tcp  --  anywhere             anywhere            owner UID match <USERNAME> state NEW recent: SET name: LIMIT_<USERID> side: source 
DROP       tcp  --  anywhere             anywhere            owner UID match <USERNAME> state NEW recent: UPDATE seconds: 60 hit_count: 31 name: LIMIT_<USERID> side: source 
ACCEPT     tcp  --  anywhere             anywhere            owner UID match <USERNAME>
- Ist es hierbei "schlimm", dass das ACCEPT am Ende steht? Wird da gar nichts limitiert? :o

Grüße
 
Last edited by a moderator:
Eine UDP Anwendung die mir spontan einfällt, wären diese tollen Gameserver-Scripte, die den Status, aktuelle Spieler, Map usw. abfragen.
Die beziehen ihre Infos je nach Gameserver meistens per UDP.
 
Hm,
da hast du natürlich Recht. Hab ich wohl tatsächlich nicht weit genug gedacht.
Sollte man dann vielleicht UDP und TCP getrennt betrachten (limitieren) oder das in einen Topf werfen und es auch bei max. 30 Requests in einer Minute belassen?

Vielen Dank dafür!
Wenn mir jetzt noch jemand meine letzte Frage (siehe Edit) beantworten kann, mach ich mich an ein neues Script für die Sache. :) Sollten eh noch andere Dinge geändert werden.

Hier auch ein Edit:
-p tcp rausnehmen um "alles" zu beschränken reicht, oder?
Das grundsätzliche "DROP" würde damit natürlich entfallen, wenn eh alles (wenn auch limitiert) durchgelassen wird.
 
So, ich habe mir nun folgendes Script zusammengetrichtert:

PHP:
<?php

$Datenbank = new mysqli("localhost","froxlor","passwort","froxlor");


$Rules = array(
  'limit'=>array(
    "iptables -I OUTPUT -o eth0 -m owner --uid-owner %owner% -m state --state NEW -m recent --update --seconds %limitsec% --hitcount %limitcount% --name LIMIT_%owner% -j DROP",
    "iptables -I OUTPUT -o eth0 -m owner --uid-owner %owner% -m state --state NEW -m recent --set  --name LIMIT_%owner%"
  )
);


function stringPrepare($String,$Owner,$LimitCount=0,$LimitSec=1) {
  $LimitCount++;
  return str_replace(array('%owner%','%limitcount%','%limitsec%'),array(OwnerToUid($Owner),$LimitCount,$LimitSec),$String);
}


function OwnerToUid($Name) {
  $Info = posix_getpwnam($Name);
  if(!$Info) { trigger_error("Finde keine UID zu ".$Name); return '9990'; }
  return $Info['uid'];
}


// Erstmal aufräumen
shell_exec("iptables -F");
echo "iptables-Regeln aufgeräumt... Starte Limitierung von Usertraffic.\n";


// Limitierung von ausgehendem User-Traffic
$Result = $Datenbank->query("SELECT `loginname` FROM `panel_customers` ORDER BY `loginname` ASC");
while($Row = $Result->fetch_array(MYSQLI_ASSOC)) {
  foreach($Rules['limit'] as $Rule) shell_exec(stringPrepare($Rule,$Row['loginname'],30,60));
  echo "".$Row['loginname']." limitiert!\n";
}

?>

Leider kenne ich mich mit iptables noch nicht allzu gut aus und PHP kann ich streng genommen eher gar nicht als schlecht, daher zwei Fragen:
  1. Kann man das PHP-Script performanter gestalten? Das Ding braucht fast vier Minuten für 1500 User.
  2. 3000 iptables-Regeln kommen logischerweise bei der Sache raus. Ist das schon ein Performance-Problem? Kann man das eleganter lösen?
  3. Gelegentlich kommt es zu einem "iptables: Invalid argument. Run `dmesg' for more information." Nicht bei jedem Durchlauf, aber manchmal halt. Warum, wie lösen?
  4. Korrekterweise sagt das Script bescheid, wenn es zu einem User keine UID finden kann. Aber warum spuckt er die Meldung zweimal aus?

Vielen Dank! :)
 
Hallo,

ich finde deine Idee eigentlich gut, aber:
1. Ist php die falsche Sprache dafuer oder ich sehe nicht den Sinn
2. Es gibt fertige (Apache) Module die dir eine solche arbeit zumindetens fuer http abnehmen und dann direkt den richten Fehlercode senden.
3. Was soll dein Programm GENAU machen und wie kommen die Daten in die DB?
4. Wann wird das Script von wem aufgerufen?
 
Hi,
danke für deine Antwort.

1. Da hast du meine 100%-ige Zustimmung. Es ist aber das einzige, was ich mit Mühe und Not gebastelt kriege. :D
2. Das wäre natürlich klasse - wie heißen die Dinger?
3. Das Skript legt halt Regeln an, die die User daran hindern, fsockopen() und fopen() zu missbrauchen, z.B. für Flooding. Ohne ein Apache-Modul ist das (meiner Meinung nach) nicht besser / einfacher zu realisieren. Die Daten sind schon in der Datenbank; das Skript sucht ja nur die User raus.
4. Ein Cronjob ruft das Skript alle drei Stunden auf.


Grüße
 
Es gibt fertige (Apache) Module die dir eine solche arbeit zumindetens fuer http abnehmen und dann direkt den richten Fehlercode senden.
Traffic Shaping von Downloads ist hier nicht Ziel der Sache. (Was uebrigens durch einen zwischengeschalteten Buffer-Proxy eher kontraproduktiv ist),
sondern das Begrenzen von Verbindungen welche durch PHP-Skripte erstellt werden, also nicht an den Besucher gerichtet sind.
Diese kann man nicht durch ein Apache-Modul begrenzen. Die einzige (mir bekannte) Alternative ist im PHP-Quellcode eine Zwischenfunktion ein zu bauen..
.

Man muesste nur die Regeln etwas klueger anlegen

st php die falsche Sprache dafuer oder ich sehe nicht den Sinn
Fuer ein Cronjob welcher nicht zeitrelevant ist und eh auf ionice -c 3 nice -20 lauft ist die Sprache mehr oder weniger egal, warum also nicht PHP? Begrenzender Faktor ist aber nicht PHP sondern iptables (welches seriell abgearbeitet werden will da es sonst zu Problemen kommt)
 
Back
Top