2012-05-11 5 views
5

Ich habe meinen eigenen Webserver in C geschrieben. Wie kann ich ihn an Port 80 binden, ohne root zu sein, damit die Sicherheit nicht beeinträchtigt wird (Pufferüberläufe usw.)?Binden Sie einen Webserver an Port 80, ohne root zu sein

Sollte ich einfach Verkehr von einem anderen "stabilen" Server weiterleiten, der auf Port 80 läuft?

Antwort

5

Die Verwendung eines Forward Proxy ist in der Tat die einfachste und am meisten empfohlene Lösung. Es hat auch den Vorteil, schrecklich ungültige Anfragen zu filtern, bevor sie Ihren selbstgeschriebenen Server erreichen.
Falls Ihre Anwendung die IP-Adresse des Benutzers für etwas verwendet, denken Sie daran, es aus der von Ihrem Webserver verwendeten Kopfzeile abzurufen (X-Client-IP usw.). Allerdings nur für Anfragen, die wirklich von Ihrem Webserver kommen, sonst können Nutzer ihre IP spoofen. Sie können dies tun, indem Sie prüfen, ob die Anfrage von Ihrer IP-Adresse stammt, und in diesem Fall nur die Kopfzeile überprüfen oder Ihre Anwendung an localhost binden.

Eine andere Lösung würde dem Programm die CAP_NET_BIND_SERVICE Fähigkeit geben. Dazu muss root setcap cap_net_bind_service=ep /path/to/the/executable verwenden. Da das Flag in einem Dateisystemattribut gespeichert wird, geht es verloren, wenn die Datei auf ein anderes System kopiert oder die Anwendung neu kompiliert wird.

Natürlich könnten Sie auch Ihr Programm setuid root machen und dann direkt nach dem Aufruf bind() zu einem unprivilegierten Benutzer wechseln. Abhängig davon, wie Ihr Programm funktioniert und was es tut, ist dies möglicherweise keine gute Idee. Wenn es zum Beispiel den abhörenden Socket aus irgendeinem Grund schließen und wieder öffnen muss, würde es einen vollständigen Neustart des Prozesses erfordern.

+0

+1 für Fähigkeiten, obwohl sie nicht zu einem anderen Unix tragbar sind. – dwalter

+0

Die meisten Leute benutzen sowieso Linux. Und ich denke * BSD hat etwas ähnliches. – ThiefMaster

2

Wenn Sie Ihren Server an Port 80 binden möchten, müssen Sie dies als root tun und anschließend die Privilegien löschen.

bind(sockfd, addr, addrlen); 
/* process is running as root, drop privileges after bind*/ 
if (setgid(groupid) != 0) 
    errx(1, "setgid: Unable to drop group privileges: %s", strerror(errno)); 
if (setuid(userid) != 0) 
    errx(1, "setuid: Unable to drop user privileges: %S", strerror(errno)); 

Wie kann ich binden Sie es an Port 80 ohne root zu sein, so dass die Sicherheit nicht beeinträchtigt wird (Pufferüberlauf usw.)

nicht läuft als root tut nicht machen Ihre System sicherer, es fügt nur eine weitere Ebene hinzu, die ausgenutzt werden kann. Anstatt darüber nachzudenken, wie man es nicht als root ausführen, stellen Sie sicher, dass Sie wie strcpy() alle bekannten Unsicherheit Funktionen nicht verwenden, sprintf() usw., sondern strncpy(), snprintf() verwenden usw.

+0

Es sollte erwähnt werden, dass "errx" eine Nichtstandardfunktion ist, die auf vielen BSD-abgeleiteten oder -kompatiblen Systemen verfügbar ist. Wenn Sie seine Funktionalität benötigen (was eine triviale 2-3-Zeilen-Funktion ist), sollten Sie Ihre eigenen schreiben, um die Portabilität Ihres Programms nicht zu verletzen. –

3

Eine alternative bind() zu nennen Als root und dann zum Löschen von Berechtigungen muss ein Root-Prozess vorhanden sein, der den Socket erstellt und bindet, und dann den abhörenden Socket über eine UNIX-Domänen-Socket-Verbindung mithilfe einer SCM_RIGHTS Nachricht an den nicht privilegierten Prozess übergibt.

2

Nun, Sie wissen, dass alle Ports unter 1024 in Unix Root-Berechtigungen zum Öffnen benötigen. Auf einem Unix-System wollen Sie nicht so wenige Anwendungen wie möglich mit root-Rechten ausführen. Es ist und wird immer ein großes Sicherheitsrisiko sein.

Eine Alternative besteht darin, iptables zu verwenden, um den Verkehr von Port 80 zu einem harmloseren Port wie 8080 umzuleiten. Hier ist ein description, wie man es einrichtet.

Iptables ist nicht das einfachste Tool zum Einrichten, aber sobald Sie es gemeistert haben, ist es sehr nützlich und leistungsstark (und sicher).

+0

Für mich funktionierte das nur an der NAT-Tabelle in der OUTPUT-Kette. Aber es ist die einfachste Antwort auf die Frage. – nus

0

ich an diesem Problem gearbeitet seit geraumer Zeit und kam zu dem Schluss, dass systemd + iptables die Lösung, und nicht Fähigkeiten, wie elaborated in great detail here.

Verwandte Themen