Es ist sehr ärgerlich, diese Einschränkung auf meiner Entwicklungsbox zu haben, wenn es nie andere Benutzer als mich geben wird.
Ich kenne die Standardumgehungen , aber keine von ihnen macht genau das, was ich will:
- authbind (Die Version in Debian-Test 1.0 unterstützt nur IPv4)
- Verwenden des Ziels iptables REDIRECT zum Umleiten eines Low-Ports zu einem High-Port (die Tabelle "nat" ist für ip6tables, die IPv6-Version von iptables, noch nicht implementiert).
- sudo (Laufen als root ist das, was ich zu vermeiden versuche)
- SELinux (oder ähnlich). (Dies ist nur meine Entwicklungsbox, ich möchte nicht viel zusätzliche Komplexität einführen.)
Gibt es eine einfache sysctl
Variable, mit der Nicht-Root-Prozesse unter Linux an "privilegierte" Ports (Ports unter 1024) gebunden werden können, oder habe ich einfach Pech?
BEARBEITEN: In einigen Fällen können Sie dazu Funktionen verwenden.
Antworten:
Okay, danke an die Leute, die auf das System und die
CAP_NET_BIND_SERVICE
Fähigkeiten der Fähigkeiten hingewiesen haben. Wenn Sie einen aktuellen Kernel haben, können Sie damit tatsächlich einen Dienst als Nicht-Root starten, aber niedrige Ports binden. Die kurze Antwort lautet:Und dann wird es jederzeit
program
ausgeführt, wenn es danach ausgeführt wirdCAP_NET_BIND_SERVICE
.setcap
ist im Debian-Paketlibcap2-bin
.Nun zu den Vorbehalten:
program
mit erhöhten Berechtigungen wiesetcap
odersuid
. Wenn Sie alsoprogram
eine eigene verwenden.../lib/
, müssen Sie möglicherweise eine andere Option wie die Portweiterleitung prüfen.Ressourcen:
setcap
.Hinweis: RHEL hat dies zuerst in Version 6 hinzugefügt .
quelle
/usr/bin/java
müsste und dann die Funktion für jede auf dem System ausgeführte Java-App öffnen würde. Schade, dass Funktionen nicht auch pro Benutzer festgelegt werden können./etc/security/capability.conf
auf Debian / Ubuntu Hilfe?Sie können eine Portumleitung durchführen. Dies ist, was ich für einen Silverlight-Richtlinienserver mache, der auf einer Linux-Box ausgeführt wird
quelle
/etc/network/if-up.d/firewall
.Die Standardmethode besteht darin, sie "setuid" zu machen, damit sie als Root starten, und dann dieses Root-Privileg wegzuwerfen, sobald sie an den Port gebunden sind, aber bevor sie Verbindungen zu ihm annehmen. Gute Beispiele dafür finden Sie im Quellcode für Apache und INN. Mir wurde gesagt, dass Lighttpd ein weiteres gutes Beispiel ist.
Ein weiteres Beispiel ist Postfix, bei dem mehrere Daemons verwendet werden, die über Pipes kommunizieren, und nur ein oder zwei von ihnen (die nur Akzeptieren oder Ausgeben von Bytes ausführen) als Root ausgeführt werden und der Rest mit einem niedrigeren Privileg ausgeführt wird.
quelle
binfmt_misc
und seine 'C'-Flagge getan ; ich bin mir bei anderen nicht sicher.)Oder patchen Sie Ihren Kernel und entfernen Sie die Prüfung.
(Option des letzten Auswegs, nicht empfohlen).
In
net/ipv4/af_inet.c
, entfernen Sie die beiden Linien , die gelesenund der Kernel überprüft keine privilegierten Ports mehr.
quelle
Sie können einen lokalen SSH-Tunnel einrichten, z. B. wenn Port 80 Ihre an 3000 gebundene App treffen soll:
Dies hat den Vorteil, mit Skriptservern zu arbeiten und sehr einfach zu sein.
quelle
sudo nc -l 80 | nc localhost 3000
Update 2017:
Verwenden Sie authbind
Viel besser als CAP_NET_BIND_SERVICE oder ein benutzerdefinierter Kernel.
Authbind gewährt dem Benutzer / der Gruppe Vertrauen, bietet Kontrolle über den Zugriff pro Port und unterstützt sowohl IPv4 als auch IPv6 (IPv6-Unterstützung wurde kürzlich hinzugefügt).
Installieren:
apt-get install authbind
Konfigurieren Sie den Zugriff auf relevante Ports, z. B. 80 und 443, für alle Benutzer und Gruppen:
Führen Sie Ihren Befehl aus über
authbind
(optional Angabe
--deep
oder andere Argumente, siehe Manpage):z.B
Als Folge von Joshuas fabelhafter Empfehlung (= nicht empfohlen, es sei denn, Sie wissen, was Sie tun), den Kernel zu hacken:
Ich habe es zuerst geschrieben hier .
Einfach. Mit einem normalen oder alten Kernel tun Sie das nicht.
Wie von anderen hervorgehoben, können iptables einen Port weiterleiten.
Wie auch von anderen hervorgehoben, kann CAP_NET_BIND_SERVICE die Aufgabe ebenfalls erledigen.
Natürlich schlägt CAP_NET_BIND_SERVICE fehl, wenn Sie Ihr Programm über ein Skript starten. Wenn Sie die Obergrenze für den Shell-Interpreter nicht festlegen, was sinnlos ist, können Sie Ihren Dienst genauso gut wie root ausführen. ZB
für Java müssen Sie ihn anwenden an die JAVA JVM
Das bedeutet natürlich, dass jedes Java-Programm Systemports binden kann.
Dito für Mono / .NET.
Ich bin mir auch ziemlich sicher, dass xinetd nicht die beste Idee ist.
Aber da beide Methoden Hacks sind, warum nicht einfach das Limit durch Aufheben der Restriktion aufheben?
Niemand hat gesagt, dass Sie einen normalen Kernel ausführen müssen, damit Sie einfach Ihren eigenen ausführen können.
Sie laden einfach die Quelle für den neuesten Kernel herunter (oder den gleichen, den Sie derzeit haben). Danach gehen Sie zu:
Dort suchen Sie nach dieser Linie
und ändern Sie es in
Wenn Sie keine unsichere SSH-Situation haben möchten, ändern Sie diese wie folgt: #define PROT_SOCK 24
Im Allgemeinen würde ich die niedrigste Einstellung verwenden, die Sie benötigen, z. B. 79 für http oder 24, wenn Sie SMTP an Port 25 verwenden.
Das ist schon alles.
Kompilieren Sie den Kernel und installieren Sie ihn.
Starten Sie neu.
Fertig - diese dumme Grenze ist GEGANGEN und das funktioniert auch für Skripte.
So kompilieren Sie einen Kernel:
https://help.ubuntu.com/community/Kernel/Compile
Kurz gesagt, verwenden Sie iptables, wenn Sie sicher bleiben möchten, kompilieren Sie den Kernel, wenn Sie sicher sein möchten, dass Sie diese Einschränkung nie wieder stört.
quelle
Dateifunktionen sind nicht ideal, da sie nach einer Paketaktualisierung unterbrochen werden können.
Die ideale Lösung, IMHO, sollte die Fähigkeit sein, eine Shell mit vererbbarem
CAP_NET_BIND_SERVICE
Satz zu erstellen .Hier ist ein etwas komplizierter Weg, dies zu tun:
capsh
Das Dienstprogramm finden Sie im libcap2-bin-Paket in Debian / Ubuntu-Distributionen. Folgendes geht vor:sg
Ändert die effektive Gruppen-ID in die des Daemon-Benutzers. Dies ist notwendig, dacapsh
GID unverändert bleibt und wir es definitiv nicht wollen.$DAEMONUSER
--keep=1
), außer vererbbarcap_net_bind_service
Das Ergebnis ist ein Prozess mit angegebenen Benutzer- und Gruppen- und
cap_net_bind_service
Berechtigungen.Als Beispiel eine Zeile aus dem
ejabberd
Startskript:quelle
capsh
ich nichts anderes tun als "Binärdatei kann nicht ausgeführt werden", wenn ich die Optionen--
oder verwende==
. Ich frage mich, was ich vermisse.--
wird an weitergeleitet/bin/bash
, also möchten Sie es vielleicht versuchen-c 'your command'
. Leider habe ich anscheinend das gleiche Problem wie @Cyberax, da mir beim Versuch "Erlaubnis verweigert" wirdbind
.--gid
anstattsg
(oder--user
die Sätze--uid
,--gid
und--groups
):sudo capsh --caps='cap_net_bind_service+eip cap_setpcap,cap_setuid,cap_setgid+ep' --keep=1 --user="$service_user" --addamb=cap_net_bind_service -- -c 'exec $service $service_args'
Aus irgendeinem Grund erwähnt niemand, dass sysctl net.ipv4.ip_unprivileged_port_start auf den Wert gesenkt werden soll, den Sie benötigen. Beispiel: Wir müssen unsere App an den 443-Port binden.
Einige mögen sagen, dass es ein potenzielles Sicherheitsproblem gibt: Nicht privilegierte Benutzer können sich jetzt an die anderen privilegierten Ports binden (444-1024). Sie können dieses Problem jedoch einfach mit iptables lösen, indem Sie andere Ports blockieren:
Vergleich mit anderen Methoden. Diese Methode:
Je nach Situation würde ich zwischen sysctl, CAP, authbind und iptables-redirect wählen. Und das ist toll, dass wir so viele Möglichkeiten haben.
quelle
Zwei weitere einfache Möglichkeiten:
Es gibt eine alte (unmoderne) Lösung für den "Daemon, der an einen niedrigen Port bindet und die Kontrolle an Ihren Daemon übergibt". Es heißt inetd (oder xinetd). Die Nachteile sind:
Vorteile:
Eine andere Alternative: ein gehackter Proxy (Netcat oder etwas Robusteres ) vom privilegierten Port zu einem beliebigen Port mit hoher Nummer, an dem Sie Ihren Zieldämon ausführen können. (Netcat ist offensichtlich keine Produktionslösung, sondern "nur meine Entwicklungsbox", oder?) Auf diese Weise könnten Sie weiterhin eine netzwerkfähige Version Ihres Servers verwenden, benötigen nur root / sudo, um den Proxy (beim Booten) zu starten, und würden sich nicht auf komplexe / potenziell fragile Funktionen verlassen.
quelle
Meine "Standard-Problemumgehung" verwendet socat als User-Space-Redirector:
Beachten Sie, dass dies nicht skalierbar ist. Gabeln ist teuer, aber so funktioniert socat.
quelle
Linux unterstützt Funktionen zur Unterstützung detaillierterer Berechtigungen als nur "Diese Anwendung wird als Root ausgeführt". Eine dieser Funktionen besteht darin
CAP_NET_BIND_SERVICE
, sich an einen privilegierten Port zu binden (<1024).Leider weiß ich nicht, wie ich das ausnutzen soll, um eine Anwendung als Nicht-Root auszuführen, während ich sie noch gebe
CAP_NET_BIND_SERVICE
(wahrscheinlich mitsetcap
, aber dafür gibt es bestimmt eine Lösung).quelle
Ich weiß, dass dies eine alte Frage ist, aber jetzt mit den neuesten (> = 4,3) Kerneln gibt es endlich eine gute Antwort darauf - Umgebungsfähigkeiten.
Die schnelle Antwort besteht darin, eine Kopie der neuesten (noch nicht veröffentlichten) Version von libcap von git zu holen und zu kompilieren. Kopieren Sie die resultierende
progs/capsh
Binärdatei irgendwo (/usr/local/bin
ist eine gute Wahl). Starten Sie dann als root Ihr Programm mitIn Ordnung sind wir
cap_net_bind_service
Funktion zu den geerbten und Umgebungssätzenbash -c 'your-command'
(dacapsh
Bash automatisch mit den Argumenten danach startet--
)Hier ist viel unter der Haube los.
Erstens werden wir als root ausgeführt, sodass wir standardmäßig alle Funktionen erhalten. Darin enthalten ist die Möglichkeit, uid & gid mit
setuid
undsetgid
syscalls zu wechseln . Wenn ein Programm dies tut, verliert es normalerweise seine Funktionen - dies ist so, dass die alte Methode, root mit zu löschen,setuid
immer noch funktioniert. Das--keep=1
Flag weistcapsh
darauf hin, dass derprctl(PR_SET_KEEPCAPS)
Systemaufruf ausgegeben werden soll, wodurch das Löschen von Funktionen beim Benutzerwechsel deaktiviert wird. Der eigentliche Benutzerwechsel durchcapsh
erfolgt mit dem--user
Flag, das ausgeführt wirdsetuid
undsetgid
.Das nächste Problem, das wir lösen müssen, ist, wie wir Fähigkeiten so einstellen können, dass sie nach
exec
unseren Kindern weiter bestehen. Das Fähigkeitssystem hatte immer einen "geerbten" Satz von Fähigkeiten, dh "einen Satz von Fähigkeiten, die über eine Ausführung hinweg erhalten bleiben (2)" [ Fähigkeiten (7) ]. Während dies so klingt, als ob es unser Problem löst (setzen Sie einfach diecap_net_bind_service
Fähigkeit auf geerbt, oder?), Gilt dies tatsächlich nur für privilegierte Prozesse - und unser Prozess ist nicht mehr privilegiert, da wir bereits den Benutzer gewechselt haben (mit dem--user
Flag).Der neue Umgebungsfunktionssatz umgeht dieses Problem - er ist "ein Satz von Funktionen, die in einem Execve (2) eines Programms erhalten bleiben, das nicht privilegiert ist". Durch das Einfügen
cap_net_bind_service
des Umgebungssatzescapsh
erbt unser Programm beim Ausführen unseres Serverprogramms diese Fähigkeit und kann Listener an niedrige Ports binden.Wenn Sie mehr erfahren möchten, wird dies auf der Seite mit den Funktionshandbüchern ausführlich erläutert. Laufen
capsh
durchstrace
ist auch sehr informativ!quelle
--addamb
Flag wurde mit libcap 2.26 eingeführt. Mein System hatte 2.25 und ich musste aus dem Quellcode bauen.TLDR: Für "die Antwort" (wie ich es sehe) springen Sie zum >> TLDR << Teil in dieser Antwort.
OK, ich habe es herausgefunden (diesmal wirklich), die Antwort auf diese Frage, und diese Antwort von mir ist auch eine Möglichkeit, sich dafür zu entschuldigen, dass ich eine andere Antwort (sowohl hier als auch auf Twitter) beworben habe, die ich für "die beste" hielt ", aber nachdem ich es versucht hatte, stellte ich fest, dass ich mich geirrt hatte. Lernen Sie aus meinen Fehlerkindern: Bewerben Sie etwas erst, wenn Sie es selbst ausprobiert haben!
Auch hier habe ich alle Antworten überprüft. Ich habe einige davon ausprobiert (und andere nicht ausprobiert, weil mir die Lösungen einfach nicht gefallen haben). Ich dachte, dass die Lösung
systemd
mit seinenCapabilities=
undCapabilitiesBindingSet=
Einstellungen verwendet werden sollte. Nachdem ich einige Zeit damit gerungen hatte, stellte ich fest, dass dies nicht die Lösung ist, weil:Funktionen sollen Root-Prozesse einschränken!
Wie das OP mit Bedacht feststellte, ist es immer am besten, dies zu vermeiden (wenn möglich für alle Ihre Dämonen!).
Sie können die Optionen für Funktionen nicht mit
User=
undGroup=
insystemd
Einheitendateien verwenden, da Funktionen IMMER zurückgesetzt werden, wennexecev
(oder was auch immer die Funktion ist) aufgerufen wird. Mit anderen Worten, wennsystemd
die Dauerwellen gegabelt und fallen gelassen werden, werden die Funktionen zurückgesetzt. Daran führt kein Weg vorbei, und die gesamte Bindungslogik im Kernel basiert auf uid = 0 und nicht auf Funktionen. Dies bedeutet, dass es unwahrscheinlich ist, dass Capabilities jemals die richtige Antwort auf diese Frage sein wird (zumindest in Kürze). Übrigens istsetcap
, wie andere bereits erwähnt haben, keine Lösung. Es hat bei mir nicht funktioniert, es funktioniert nicht gut mit Skripten, und diese werden sowieso zurückgesetzt, wenn sich die Datei ändert.In meiner mageren Verteidigung habe ich (in dem Kommentar, den ich jetzt gelöscht habe) festgestellt , dass James ' Vorschlag für iptables (den das OP auch erwähnt) die "zweitbeste Lösung" war. :-P
>> TLDR <<
Die Lösung besteht darin, sie
systemd
mit On-the-Fly-iptables
Befehlen wie diesen zu kombinieren ( aus DNSChain ):Hier erreichen wir Folgendes:
iptables
systemd
Bereinigt die Firewall-Regeln für uns und stellt sicher, dass sie entfernt werden, wenn der Dämon nicht ausgeführt wird.systemd
behauptet dies), angeblich selbst dann, wenn der Dämon kompromittiert und festgelegt istuid=0
.iptables
ist leider immer noch ein ziemlich hässliches und schwer zu bedienendes Dienstprogramm. Wenn der Daemon auf zuhörteth0:0
statteth0
, zum Beispiel sind die Befehle etwas anders .quelle
eth0:0
sei denn, er hat eine wirklich alte Linux-Distribution. Sie sind seit Jahren veraltet und werden irgendwann verschwinden.# Generated by SolusVM
AmbientCapabilities=CAP_NET_BIND_SERVICE
hat für mich in Kombination mit perfekt funktioniertUser=
.systemd ist ein sysvinit-Ersatz, mit dem ein Daemon mit bestimmten Funktionen gestartet werden kann. Optionen Capabilities =, CapabilityBoundingSet = in der Manpage systemd.exec (5) .
quelle
systemd
.Die Portumleitung war für uns am sinnvollsten, aber wir stießen auf ein Problem, bei dem unsere Anwendung eine URL lokal auflöste, die ebenfalls umgeleitet werden musste. (das heißt du shindig ).
Auf diese Weise können Sie auch umgeleitet werden, wenn Sie auf die URL auf dem lokalen Computer zugreifen.
quelle
Moderne Linux-Unterstützung
/sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0
.quelle
Mit systemd müssen Sie Ihren Dienst nur geringfügig ändern, um voraktivierte Sockets zu akzeptieren.
Sie können später den systemd-Socket aktivieren .
Es werden keine Funktionen, Iptables oder andere Tricks benötigt.
Dies ist der Inhalt relevanter systemd-Dateien aus diesem Beispiel eines einfachen Python-http-Servers
Datei
httpd-true.service
Datei
httpd-true.socket
quelle
Am Anfang:
Dann können Sie an den Port binden, an den Sie weiterleiten.
quelle
--to-port
existieren?man iptables
nur Erwähnungen--to-ports
(Plural).systemd
.Verwenden Sie das Dienstprogramm privbind : Es ermöglicht einer nicht privilegierten Anwendung, an reservierte Ports zu binden.
quelle
Es gibt auch den 'DJB-Weg'. Mit dieser Methode können Sie Ihren Prozess als Root starten, der auf einem beliebigen Port unter tcpserver ausgeführt wird. Anschließend wird die Steuerung des Prozesses unmittelbar nach dem Start des Prozesses an den von Ihnen angegebenen Benutzer übergeben.
Weitere Informationen finden Sie unter: http://thedjbway.b0llix.net/daemontools/uidgid.html
quelle
Da es sich bei dem OP nur um Entwicklung / Test handelt, können weniger als schlanke Lösungen hilfreich sein:
setcap kann auf dem Interpreter eines Skripts verwendet werden, um Skripten Funktionen zu gewähren. Wenn setcaps für die globale Interpreter-Binärdatei nicht akzeptabel ist, erstellen Sie eine lokale Kopie der Binärdatei (jeder Benutzer kann dies) und veranlassen Sie root, setcap für diese Kopie festzulegen. Python2 funktioniert (zumindest) ordnungsgemäß mit einer lokalen Kopie des Interpreters in Ihrem Skriptentwicklungsbaum. Es wird kein Suid benötigt, damit der Root-Benutzer steuern kann, auf welche Funktionen Benutzer Zugriff haben.
Wenn Sie systemweite Aktualisierungen des Interpreters nachverfolgen müssen, verwenden Sie ein Shell-Skript wie das folgende, um Ihr Skript auszuführen:
quelle
Ich habe die Methode iptables PREROUTING REDIRECT ausprobiert. In älteren Kerneln scheint diese Art von Regel für IPv6 nicht unterstützt zu werden . Aber anscheinend wird es jetzt in ip6tables v1.4.18 und Linux Kernel v3.8 unterstützt.
Ich habe auch festgestellt, dass PREROUTING REDIRECT nicht für Verbindungen funktioniert, die innerhalb des Computers initiiert wurden. Um für Verbindungen vom lokalen Computer zu arbeiten, fügen Sie auch eine OUTPUT-Regel hinzu - siehe iptables- Portumleitung funktioniert nicht für localhost . ZB so etwas wie:
Ich habe auch festgestellt, dass PREROUTING REDIRECT auch weitergeleitete Pakete betrifft . Das heißt, wenn der Computer auch Pakete zwischen Schnittstellen weiterleitet (z. B. wenn er als Wi-Fi-Zugangspunkt fungiert, der mit einem Ethernet-Netzwerk verbunden ist), erkennt die iptables-Regel auch die Verbindungen verbundener Clients zu Internetzielen und leitet sie an diese weiter Die Maschine. Das wollte ich nicht - ich wollte nur Verbindungen umleiten, die an die Maschine selbst gerichtet waren. Ich habe festgestellt, dass ich durch Hinzufügen nur die an die Box adressierten Pakete beeinflussen kann
-m addrtype --dst-type LOCAL
. ZB so etwas wie:Eine andere Möglichkeit ist die Verwendung der TCP-Portweiterleitung. ZB mit
socat
:Ein Nachteil dieser Methode ist jedoch, dass die Anwendung, die Port 8080 überwacht, die Quelladresse eingehender Verbindungen nicht kennt (z. B. zur Protokollierung oder für andere Identifikationszwecke).
quelle
Antwort am 2015 / Sep:
ip6tables unterstützt jetzt IPV6 NAT: http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt
Sie benötigen Kernel 3.7+
Beweis:
quelle