Zulassen, dass ein Benutzer einen Port unter 1024 abhört

63

Ich muss einem Benutzer (anders als root) erlauben, einen Server auszuführen, der auf Port 80 lauscht.

Gibt es eine Möglichkeit, dies zu tun?

peoro
quelle
1
Diese Frage kann interpretiert werden. Ich hoffe, Sie meinen "Sie haben einen neuen Systemdienst erstellt, den Sie (als Root) aus Sicherheitsgründen in einem nicht privilegierten Konto ausführen möchten" (als bewährte Vorgehensweise) und nicht "Ich habe einen Benutzer, der gefragt wird, ob er dies kann Führen Sie auf meinem System einen eigenen Webserver aus. Wie kann ich ihnen Zugriff gewähren? " (als eher schlechte Praxis)
Michael Shaw
3
@Ptolemy, der eigentliche Grund ist: Mein Computer befindet sich hinter einer Firewall, die jeden Port außer dem 80 blockiert. Ich möchte einen Server hosten (der keine Berechtigungen verwirft!), Muss ihn also auf Port 80 überwachen, aber nicht Ich vertraue nicht darauf, dass es als root ausgeführt wird (aus offensichtlichen Sicherheitsgründen). Ich darf das tun, wenn es dich interessiert.
Peoro

Antworten:

50

setcap 'cap_net_bind_service=+ep' /path/to/program

Dies funktioniert für bestimmte Prozesse. Damit sich ein bestimmter Benutzer an Ports unter 1024 binden kann, muss er Sudoern hinzugefügt werden.

Schauen Sie sich diese Diskussion an, um mehr zu erfahren.

Rohan Monga
quelle
31

(Einige dieser Methoden wurden bereits in anderen Antworten erwähnt. Ich gebe verschiedene Auswahlmöglichkeiten in groben Rangfolgen an.)

Sie können den Low-Port auf einen High-Port umleiten und den High-Port überwachen.

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080

Sie können Ihren Server als Root starten und Berechtigungen löschen, nachdem er den privilegierten Port abgehört hat. Starten Sie Ihren Server vorzugsweise von einem Wrapper aus, der die Aufgabe für Sie erledigt, anstatt ihn selbst zu codieren. Wenn Ihr Server eine Instanz pro Verbindung startet, starten Sie diese von inetd(oder einem ähnlichen Programm wie xinetd). Für inetdeine Zeile wie diese in Verwendung /etc/inetd.conf:

http  stream  tcp  nowait  username:groupname  /path/to/server/executable  argv[0] argv[1]…

Wenn Ihr Server in einer einzelnen Instanz lauscht, starten Sie ihn mit einem Programm wie authbind. Erstellen Sie entweder eine leere Datei /etc/authbind/byport/80und machen Sie sie für den Benutzer, der den Server ausführt, ausführbar. oder create /etc/authbind/byuid/1234, wobei 1234 die UID ist, unter der der Server ausgeführt wird und die die Zeile enthält 0.0.0.0/0:80,80.

Wenn die ausführbare Datei Ihres Servers in einem Dateisystem gespeichert ist, das Funktionen unterstützt, können Sie ihr diese Funktionen zuweisen . Beachten Sie, dass die Funktionen noch relativ neu sind und noch einige Knicke aufweisen .cap_net_bind_service

setcap cap_net_bind_service=ep /path/to/server/executable
Gilles 'SO - hör auf böse zu sein'
quelle
4
In jedem Fall war die ausführbare Datei ein Skript, das Java oder Python startete. Als Mann, der keine 10 Stunden für die Feinheiten aufwenden muss, deckt Ihre iptables-Lösung dies schmerzlos ab.
Srking
Für die iptables-Lösung musste ich auch eine Filterregel hinzufügen, -A INPUT -p tcp --dport 1080 -j ACCEPTda dies sonst nicht funktionieren würde (ich habe auch ein -j DROPCatch-All). Ich habe also zwei Listening-Sockets.
thom_nic
4

Die kurze Antwort lautet, dass dies nicht beabsichtigt ist.

Die lange Antwort ist, dass in den Open Source-Welten viele Leute mit dem Design spielen und alternative Methoden finden. Es ist allgemein anerkannt, dass dies nicht möglich sein sollte. Die Tatsache, dass Sie es versuchen, bedeutet wahrscheinlich, dass Sie einen weiteren Konstruktionsfehler in Ihrem System haben und Ihre gesamte Systemarchitektur unter Berücksichtigung von * nix-Best Practices und Sicherheitsaspekten überdenken sollten.

Das heißt, ein Programm zum Autorisieren des Nicht-Root-Zugriffs auf niedrige Ports ist authbind . Sowohl selinux und grsecurity bieten auch Rahmenbedingungen für solche Feinabstimmung Authentifizierungen.

Wenn Sie möchten, dass bestimmte Benutzer bestimmte Programme als root ausführen, und Sie wirklich nur einem Benutzer erlauben möchten, Apache oder ähnliches neu zu starten, sudoist dies Ihr Freund!

Caleb
quelle
8
Port "Sicherheit" gibt Ihnen in der modernen Welt nicht wirklich viel.
pjc50
3
@ pjc50: Ja das tut es. Es geht um implizites Vertrauen. Niedrige Portnummern bedeuten hohes Vertrauen. Von SSH, POP, FTP und anderen Daemons wird erwartet, dass sie beim Öffnen ihrer Ports nach Kennwörtern und anderen Anmeldeinformationen auf Systemebene fragen. Wenn Benutzer niedrige Ports auf einer Box überwachen könnten, könnten sie gefälschte Dämonen auf nicht verwendeten (oder abgestürzten) Ports starten und Passwörter von ahnungslosen Benutzern abrufen. Diese Passwörter könnten dann für dieses Feld verwendet werden, um andere Konten, einschließlich root, zu gefährden.
Caleb
8
Das ist eine ziemlich schwache Form der Sicherheit. Wenn Sie eine Verbindung zu etwas hergestellt haben und keine Zertifikatstransaktion durchgeführt haben, wissen Sie nicht, mit wem Sie sprechen, z. B. MITM-Angriffe.
pjc50
5
Ich nehme an, was für Ports benötigt wird: Dann könnten Sie "mail port25" "chown", dann muss (a) Ihr Mail-Daemon nicht mit root-Privs gestartet werden und (b) niemand anderes kann ihn hijacken.
pjc50
7
Während dies "von Natur aus" zutraf, als Linux noch in den Kinderschuhen steckte, ergibt es damals und heute wenig Sinn. Bei Sicherheit geht es darum, was ein Benutzer kann und was nicht. Das Zulassen, dass beispielsweise nur der Root-Benutzer Port 80 verwendet, ist ein großes Sicherheitsrisiko, da Sie Benutzern, die Port 80 verwenden müssen, jedoch keinen Root-Zugriff gewähren müssen. Wenn Sie dem Nicht-Root-Benutzer X vertrauen, um Port 80 zu verwenden, sollten Sie in der Lage sein, diese Vertrauenswürdigkeit in Ihrem Betriebssystem zu codieren. Glücklicherweise gibt es, wie Sie bereits erwähnt haben, beschissene Workarounds, die dies ermöglichen, wie z. B. die Authentifizierung.
BT
3

Sie können die Portweiterleitung netcat oder xinetd oder iptables verwenden oder Apache als Front-End-Proxy verwenden und den Prozess auf einem nicht privilegierten Port ausführen.

jamespo
quelle
3

Authbind , @Gilles hat es bereits erwähnt, aber ich würde es gerne etwas erweitern.

Es verfügt über eine komfortable Zugriffskontrolle (Details in der Manpage): Sie können den Zugriff nach Port, Schnittstellenadresse, UID, Adressbereichen oder Port und deren Kombination filtern.

Es hat sehr nützliche Parameter --depth:

--depth Ebenen

Bewirkt, dass die Authentifizierung Programme beeinflusst, die sich tief im aufrufenden Diagramm befinden. Der Standardwert ist 1.

"Ebenen tief" bedeutet, wenn ein Skript (oder Programm) ein anderes Skript ausführt, das eine Ebene tiefer geht. Wenn Sie es haben --depth 5, bedeutet dies, dass Sie auf den Ebenen 1 (oder 0?) Bis 5 die Berechtigung zum Binden haben, während Sie dies auf Ebene 6 und höher nicht tun. Nützlich, wenn Sie möchten, dass ein Skript Zugriff hat, aber keine Programme, die mit oder ohne Ihr Wissen ausgeführt werden.


Zur Veranschaulichung könnten Sie so etwas haben: Aus Sicherheitsgründen haben Sie einen Benutzer java, der nur Java ausführen soll, und Sie möchten ihm Zugriff auf Port 80 gewähren:

echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80

Ich habe die erstellt ../byport/80 file, sie der javaBenutzergruppe gegeben (jeder Benutzer hat seine eigene Gruppe) und sie für jede Gruppe ausführbar gemacht, was bedeutet, dass sie für jeden Benutzer ausführbar ist java. Wenn Sie Zugriff über den Port gewähren, muss die Datei von dem Benutzer ausgeführt werden können, der Zugriff haben soll.

Dies mag für den durchschnittlichen Joe ausreichen, aber da Sie wissen, wie man den --depthParameter verwendet, führen Sie (als javaBenutzer) authbind --depth [depth] my_web_app's_start_scriptbeginnend mit --depth 1und arbeiten sich nach oben, bis Sie die kleinste Tiefe finden, die funktioniert, und verwenden Sie diese.

Lesen Sie die Manpage für Details .

Dominykas Mostauskis
quelle
1

Ich habe die iptables PREROUTING REDIRECT-Methode ausprobiert, aber festgestellt, dass sie auch weitergeleitete Pakete betrifft. Wenn das Gerät also auch Pakete zwischen Schnittstellen weiterleitet (z. B. wenn es als Wi-Fi-Zugriffspunkt fungiert, der mit einem Ethernet-Netzwerk verbunden ist), erfasst die iptables-Regel auch die Verbindungen der verbundenen Clients zu Internetzielen und leitet sie an diese weiter Die Maschine. Das wollte ich nicht - ich wollte nur Verbindungen umleiten, die auf die Maschine selbst gerichtet waren.

Eine Möglichkeit ist die Verwendung der TCP-Portweiterleitung. ZB mit socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

Ein Nachteil dieser Methode ist jedoch, dass die Anwendung, die Port 8080 abhört, die Quelladresse eingehender Verbindungen nicht kennt (z. B. für Protokollierungs- oder andere Identifikationszwecke).

Craig McQueen
quelle