To irytujące jest mieć to ograniczenie w moim pudełku programistycznym, kiedy nigdy nie będzie żadnych użytkowników innych niż ja.
Jestem świadomy standardowych obejść , ale żadne z nich nie robi dokładnie tego, co chcę:
- authbind (wersja w testowaniu Debiana, 1.0, obsługuje tylko IPv4)
- Wykorzystanie celu iptables REDIRECT do przekierowania niskiego portu do wysokiego portu (tabela „nat” nie jest jeszcze zaimplementowana dla ip6tables, wersji IPv6 iptables)
- sudo (staram się unikać roota)
- SELinux (lub podobny). (To tylko moje pudełko deweloperów, nie chcę wprowadzać dodatkowej złożoności.)
Czy istnieje jakaś prosta sysctl
zmienna pozwalająca procesom innym niż root na łączenie się z „uprzywilejowanymi” portami (porty mniejsze niż 1024) w Linuksie, czy mam po prostu pecha?
EDYCJA: W niektórych przypadkach możesz użyć do tego możliwości.
Odpowiedzi:
Ok, dzięki ludziom, którzy wskazali system
CAP_NET_BIND_SERVICE
możliwości i możliwości. Jeśli masz najnowsze jądro, rzeczywiście można go użyć do uruchomienia usługi innej niż root, ale powiązania niskich portów. Krótka odpowiedź brzmi:A potem, kiedy tylko
program
zostanie wykonany, będzie miał takąCAP_NET_BIND_SERVICE
możliwość.setcap
jest w pakiecie debianlibcap2-bin
.Teraz ostrzeżenia:
program
który ma podwyższone uprawnienia, takie jaksetcap
lubsuid
. Więc jeśli używaszprogram
własnego.../lib/
, być może będziesz musiał rozważyć inną opcję, taką jak przekierowanie portów.Zasoby:
setcap
.Uwaga: RHEL po raz pierwszy dodał to w wersji 6 .
źródło
/usr/bin/java
a następnie otworzyłby możliwość dowolnej aplikacji Java uruchomionej w systemie. Szkodliwych możliwości nie można również ustawić dla poszczególnych użytkowników./etc/security/capability.conf
na Debianie / Ubuntu jest jakaś pomoc?Możesz wykonać przekierowanie portu. To właśnie robię dla serwera strategii Silverlight działającego w systemie Linux
źródło
/etc/network/if-up.d/firewall
.Standardowym sposobem jest uczynienie ich „setuidami”, aby uruchomili się jako root, a następnie zrzekają się przywileju rootowania, gdy tylko połączą się z portem, ale zanim zaczną akceptować połączenia z nim. Dobre przykłady tego można zobaczyć w kodzie źródłowym Apache i INN. Powiedziano mi, że Lighttpd jest kolejnym dobrym przykładem.
Innym przykładem jest Postfix, który korzysta z wielu demonów komunikujących się przez potoki, a tylko jeden lub dwa z nich (które robią bardzo niewiele oprócz akceptowania lub wysyłania bajtów) działają jako root, a reszta działa z niższymi uprawnieniami.
źródło
binfmt_misc
swoją flagę „C”; nie jestem pewien co do innych).Lub załataj jądro i usuń zaznaczenie.
(Opcja ostateczna, niezalecana).
W
net/ipv4/af_inet.c
usuń dwa czytane wierszea jądro nie będzie już sprawdzać uprzywilejowanych portów.
źródło
Możesz skonfigurować lokalny tunel SSH, np. Jeśli chcesz, aby port 80 trafił do Twojej aplikacji powiązanej z 3000:
Ma to tę zaletę, że współpracuje z serwerami skryptów i jest bardzo proste.
źródło
sudo nc -l 80 | nc localhost 3000
Aktualizacja 2017:
Użyj authbind
Znacznie lepiej niż CAP_NET_BIND_SERVICE lub niestandardowe jądro.
Authbind zapewnia zaufanie użytkownikowi / grupie i zapewnia kontrolę nad dostępem przez port oraz obsługuje zarówno IPv4, jak i IPv6 (obsługa IPv6 została ostatnio dodana).
Zainstalować:
apt-get install authbind
Skonfiguruj dostęp do odpowiednich portów, np. 80 i 443 dla wszystkich użytkowników i grup:
Wykonaj polecenie za pomocą
authbind
(opcjonalnie podając
--deep
lub inne argumenty, patrz strona podręcznika):na przykład
W następstwie fantastycznej (= niezalecanej, jeśli nie wiesz co robisz) rekomendacji Joshua do zhakowania jądra:
Po raz pierwszy opublikowałem to tutaj .
Prosty. Z normalnym lub starym jądrem nie.
Jak zauważyli inni, iptables może przekierować port.
Jak zauważyli także inni, CAP_NET_BIND_SERVICE może również wykonać zadanie.
Oczywiście CAP_NET_BIND_SERVICE nie powiedzie się, jeśli uruchomisz program ze skryptu, chyba że ustawisz ograniczenie interpretera powłoki, co jest bezcelowe, możesz równie dobrze uruchomić swoją usługę jak root ...
np. W przypadku Java, musisz ją zastosować do JVVA JVM
Oczywiście oznacza to, że każdy program Java może powiązać porty systemowe.
Dito dla mono / .NET.
Jestem też całkiem pewien, że xinetd nie jest najlepszym pomysłem.
Ale skoro obie metody to hacki, dlaczego nie po prostu podnieść limit przez zniesienie ograniczenia?
Nikt nie powiedział, że musisz uruchomić normalne jądro, więc możesz po prostu uruchomić własne.
Po prostu pobierasz źródło najnowszego jądra (lub tego samego, co aktualnie posiadasz). Następnie przejdziesz do:
Tam szukasz tej linii
i zmień na
jeśli nie chcesz mieć niepewnej sytuacji ssh, zmień to na: # zdefiniuj PROT_SOCK 24
Zasadniczo użyłbym najniższego ustawienia, którego potrzebujesz, np. 79 dla http lub 24, gdy używasz SMTP na porcie 25.
To już wszystko.
Skompiluj jądro i zainstaluj je.
Restart.
Zakończone - ten głupi limit Zniknął, i działa również w przypadku skryptów.
Oto jak skompilujesz jądro:
https://help.ubuntu.com/community/Kernel/Compile
W skrócie, użyj iptables, jeśli chcesz zachować bezpieczeństwo, skompiluj jądro, jeśli chcesz mieć pewność, że to ograniczenie nigdy więcej nie będzie Ci przeszkadzać.
źródło
Funkcje plików nie są idealne, ponieważ mogą ulec uszkodzeniu po aktualizacji pakietu.
Idealnym rozwiązaniem, IMHO, powinna być zdolność do tworzenia powłoki z
CAP_NET_BIND_SERVICE
zestawem dziedzicznym .Oto nieco skomplikowany sposób:
capsh
narzędzie można znaleźć w pakiecie libcap2-bin w dystrybucjach Debian / Ubuntu. Oto, co się dzieje:sg
zmienia efektywny identyfikator grupy na identyfikator użytkownika demona. Jest to konieczne, ponieważcapsh
pozostawia GID bez zmian i zdecydowanie nie chcemy tego.$DAEMONUSER
--keep=1
), z wyjątkiem dziedzicznychcap_net_bind_service
Wynikiem jest proces z określonym użytkownikiem i grupą oraz
cap_net_bind_service
uprawnieniami.Na przykład wiersz ze
ejabberd
skryptu uruchamiania:źródło
capsh
zrobić nic innego niż „nie mogę wykonać pliku binarnego” podczas korzystania z opcji--
lub==
. Zastanawiam się, czego mi brakuje.--
jest przekazywane do/bin/bash
, więc możesz spróbować-c 'your command'
. Niestety, wydaje mi się, że mam ten sam problem co @Cyberax, ponieważ otrzymuję „odmowę dostępu” przy próbiebind
.--gid
zamiastsg
(lub--user
które zestawy--uid
,--gid
i--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'
Z jakiegoś powodu nikt nie wspomniał o obniżeniu sysctl net.ipv4.ip_unprivileged_port_start do wartości, której potrzebujesz. Przykład: Musimy powiązać naszą aplikację z portem 443.
Niektórzy mogą powiedzieć, że istnieje potencjalny problem z bezpieczeństwem: nieuprzywilejowani użytkownicy mogą teraz łączyć się z innymi uprzywilejowanymi portami (444-1024). Możesz jednak łatwo rozwiązać ten problem za pomocą iptables, blokując inne porty:
Porównanie z innymi metodami. Ta metoda:
W zależności od sytuacji wybrałbym pomiędzy sysctl, CAP, authbind i iptables-redirect. I to świetnie, że mamy tak wiele opcji.
źródło
Dwie inne proste możliwości:
Istnieje stare (niemodne) rozwiązanie „demona, który łączy się z niskim portem i zapewnia kontrolę nad twoim demonem”. Nazywa się to inetd (lub xinetd). Minusy to:
Plusy:
Inna alternatywa: zhakowany serwer proxy (netcat lub nawet coś bardziej niezawodnego ) z uprzywilejowanego portu do dowolnego dowolnego portu o wysokiej liczbie, gdzie można uruchomić docelowego demona. (Netcat oczywiście nie jest rozwiązaniem produkcyjnym, ale „tylko moim urządzeniem deweloperskim”, prawda?). W ten sposób możesz nadal korzystać z sieciowej wersji serwera, potrzebujesz tylko root / sudo, aby uruchomić proxy (podczas rozruchu), nie polegałbyś na złożonych / potencjalnie kruchych możliwościach.
źródło
Moje „standardowe obejście” używa socat jako readresatora przestrzeni użytkownika:
Uważaj, że to się nie skaluje, rozwidlenie jest drogie, ale tak właśnie działa socat.
źródło
Linux obsługuje możliwości obsługi bardziej szczegółowych uprawnień niż tylko „ta aplikacja jest uruchamiana jako root”. Jedną z tych możliwości jest
CAP_NET_BIND_SERVICE
powiązanie z uprzywilejowanym portem (<1024).Niestety nie wiem, jak to wykorzystać, aby uruchomić aplikację jako użytkownik inny niż root, wciąż ją udostępniając
CAP_NET_BIND_SERVICE
(prawdopodobnie używasetcap
, ale na pewno istnieje na to istniejące rozwiązanie).źródło
Wiem, że to stare pytanie, ale teraz przy najnowszych (> = 4.3) jądrach jest na to dobra odpowiedź - możliwości otoczenia.
Szybką odpowiedzią jest pobranie najnowszej (jeszcze nie wydanej) wersji libcap z git i skompilowanie jej. Skopiuj
progs/capsh
gdzieś wynikowy plik binarny (/usr/local/bin
to dobry wybór). Następnie jako root uruchom swój programW porządku jesteśmy
cap_net_bind_service
możliwości do zbiorów odziedziczonych i otoczeniabash -c 'your-command'
(ponieważcapsh
automatycznie rozpoczyna bash z argumentami po--
)Pod maską dużo się dzieje.
Po pierwsze, działamy jako root, więc domyślnie otrzymujemy pełny zestaw możliwości. Obejmuje to możliwość przełączania UID i GID za pomocą
setuid
isetgid
syscalls. Jednak zwykle, gdy program to robi, traci swój zestaw możliwości - jest tak, że stary sposób upuszczania rootasetuid
nadal działa.--keep=1
Flaga mówicapsh
wydaniaprctl(PR_SET_KEEPCAPS)
syscall, który wyłącza możliwości spada przy zmianie użytkownika. Rzeczywista zmiana użytkowników przezcapsh
dzieje z--user
flagą, czylisetuid
asetgid
.Kolejnym problemem, który musimy rozwiązać, jest sposób ustawiania zdolności w sposób, który będzie kontynuowany po
exec
naszych dzieciach. System możliwości zawsze miał „odziedziczony” zestaw możliwości, który jest „zbiorem możliwości zachowanych w execve (2)” [ Możliwości (7) ]. Chociaż wydaje się, że to rozwiązuje nasz problem (wystarczy ustawićcap_net_bind_service
możliwość dziedziczenia, prawda?), Tak naprawdę dotyczy to tylko procesów uprzywilejowanych - a nasz proces nie jest już uprzywilejowany, ponieważ już zmieniliśmy użytkownika (z--user
flagą).Nowy zestaw funkcji otoczenia rozwiązuje ten problem - jest to „zestaw funkcji zachowanych w execve (2) programu, który nie jest uprzywilejowany”. Poprzez umieszczenie
cap_net_bind_service
w zbiorze otoczenia, gdycapsh
exec nasz program serwera, nasz program będzie dziedziczyć tej możliwości i być w stanie związać słuchaczy do niskich portach.Jeśli chcesz dowiedzieć się więcej, strona podręcznika funkcji wyjaśnia to szczegółowo. Uruchomiony
capsh
przezstrace
to również bardzo pouczające!źródło
--addamb
Flaga została wprowadzona libcap 2,26. Mój system miał 2.25 i musiałem budować ze źródła.TLDR: Aby uzyskać „odpowiedź” (tak jak ją widzę), zeskocz do części >> TLDR << w tej odpowiedzi.
OK, wymyśliłem (tym razem naprawdę) odpowiedź na to pytanie, a ta moja odpowiedź jest również sposobem przeprosin za promowanie kolejnej odpowiedzi (zarówno tutaj, jak i na Twitterze), która moim zdaniem była „najlepsza” ", ale po wypróbowaniu odkryłem, że się myliłem. Ucz się od moich błędnych dzieci: nie promuj czegoś, dopóki sam tego nie spróbujesz!
Ponownie przejrzałem wszystkie odpowiedzi tutaj. Próbowałem niektórych z nich (i postanowiłem nie wypróbowywać innych, ponieważ po prostu nie podobały mi się rozwiązania). Myślałem, że rozwiązaniem będzie użycie
systemd
jego ustawieńCapabilities=
iCapabilitiesBindingSet=
ustawień. Po dłuższej walce z tym odkryłem, że to nie jest rozwiązanie, ponieważ:Możliwości mają na celu ograniczenie procesów rootowania!
Jak mądrze stwierdził PO, zawsze najlepiej tego unikać (dla wszystkich demonów, jeśli to możliwe!).
Nie można korzystać z funkcji związanych z opcji
User=
orazGroup=
wsystemd
plikach jednostkowych, bo możliwości są zawsze zresetować kiedyexecev
(lub cokolwiek funkcja jest) jest tzw. Innymi słowy, kiedysystemd
rozwidlenia i upuszczenie perms, możliwości są resetowane. Nie da się tego obejść, a cała logika wiązania w jądrze jest podstawowa wokół uid = 0, a nie możliwości. Oznacza to, że jest mało prawdopodobne, aby Zdolności kiedykolwiek były właściwą odpowiedzią na to pytanie (przynajmniej w najbliższym czasie). Nawiasem mówiąc,setcap
jak wspomnieli inni, nie jest rozwiązaniem. Nie działało to dla mnie, nie działa ładnie ze skryptami, które i tak są resetowane przy każdej zmianie pliku.W mojej skromnej obronie stwierdziłem (w komentarzu, który teraz usunąłem), że sugestia Jamesa iptables (o której wspomina również PO), była „drugim najlepszym rozwiązaniem”. :-P
>> TLDR <<
Rozwiązaniem jest połączenie
systemd
ziptables
komendami „w locie” , takimi jak to ( wzięte z DNSChain ):Tutaj realizujemy następujące czynności:
iptables
systemd
czyści dla nas reguły zapory, usuwając je, gdy demon nie działa.systemd
twierdzi), podobno nawet jeśli demon zostanie przejęty i ustawionyuid=0
.iptables
jest nadal niestety dość brzydkim i trudnym w użyciu narzędziem. Jeśli demon nasłuchujeeth0:0
zamiasteth0
, na przykład, polecenia są nieco inne .źródło
eth0:0
chyba że mają naprawdę starą dystrybucję Linuksa. Są one przestarzałe od lat i ostatecznie odejdą.# Generated by SolusVM
AmbientCapabilities=CAP_NET_BIND_SERVICE
działało dla mnie idealnie w połączeniu zUser=
.systemd to zamiennik sysvinit, który ma opcję uruchomienia demona o określonych możliwościach. Opcje Możliwości =, CapabilityBoundingSet = na stronie systemd.exec (5) .
źródło
systemd
.Przekierowanie portu było dla nas najbardziej sensowne, ale natrafiliśmy na problem polegający na tym, że nasza aplikacja rozwiązała adres URL lokalnie, który również musiał zostać przekierowany; (to znaczy, że jesteś shindig ).
Umożliwi to również przekierowanie podczas uzyskiwania dostępu do adresu URL na komputerze lokalnym.
źródło
Nowoczesne Linux obsługuje
/sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0
.źródło
Z systemd wystarczy nieznacznie zmodyfikować usługę, aby zaakceptować wstępnie aktywowane gniazda.
Możesz później użyć systemd aktywacji gniazda .
Nie są potrzebne żadne zdolności, iptables ani inne sztuczki.
To jest zawartość odpowiednich plików systemowych z tego przykładu prostego serwera http python
Plik
httpd-true.service
Plik
httpd-true.socket
źródło
Podczas uruchamiania:
Następnie możesz połączyć się z portem, do którego przekierowujesz.
źródło
--to-port
istnieje?man iptables
wymienia tylko--to-ports
(liczba mnoga).systemd
.Użyj narzędzia privbind : umożliwia nieuprzywilejowanej aplikacji powiązanie z zarezerwowanymi portami.
źródło
Istnieje również „droga djb”. Możesz użyć tej metody, aby uruchomić proces jako root działający na dowolnym porcie w tcpserver, a następnie przekaże kontrolę nad procesem użytkownikowi określonemu natychmiast po uruchomieniu procesu.
Aby uzyskać więcej informacji, zobacz: http://thedjbway.b0llix.net/daemontools/uidgid.html
źródło
Ponieważ PO to tylko programowanie / testowanie, pomocne mogą być mniej eleganckie rozwiązania:
setcap może być użyty w interpretera skryptu, aby nadać możliwości skryptom. Jeśli setcaps w globalnym pliku binarnym interpretera nie jest akceptowalny, zrób lokalną kopię pliku binarnego (każdy użytkownik może) i uzyskaj root do setcap na tej kopii. Python2 (przynajmniej) działa poprawnie z lokalną kopią interpretera w drzewie rozwoju skryptów. Suid nie jest potrzebny, aby użytkownik root mógł kontrolować, jakie możliwości mają użytkownicy.
Jeśli chcesz śledzić ogólnosystemowe aktualizacje interpretera, użyj skryptu powłoki takiego jak poniżej, aby uruchomić skrypt:
źródło
Wypróbowałem metodę iptables PREROUTING REDIRECT. W starszych jądrach wydaje się, że ten typ reguły nie był obsługiwany dla IPv6 . Ale najwyraźniej jest teraz obsługiwany w ip6tables v1.4.18 i jądrze Linux v3.8.
Odkryłem również, że PREROUTING REDIRECT nie działa dla połączeń inicjowanych w maszynie. Aby pracować dla połączeń z komputera lokalnego, dodaj również regułę WYJŚCIE - patrz przekierowanie portu iptables nie działa dla localhost . Np. Coś takiego:
Odkryłem również, że PREROUTING REDIRECT wpływa również na przesyłane pakiety . Oznacza to, że jeśli urządzenie przesyła również pakiety między interfejsami (np. Działa jako punkt dostępu Wi-Fi podłączony do sieci Ethernet), wówczas reguła iptables przechwytuje połączenia połączonych klientów do miejsc docelowych w Internecie i przekierowuje je do maszyna. Nie tego chciałem - chciałem tylko przekierowywać połączenia skierowane do samej maszyny. Stwierdziłem, że mogę sprawić, że będzie to wpływać tylko na pakiety adresowane do skrzynki, poprzez dodanie
-m addrtype --dst-type LOCAL
. Np. Coś takiego:Inną możliwością jest użycie przekierowania portów TCP. Np. Używając
socat
:Jednak jedną wadą tej metody jest to, że aplikacja nasłuchująca na porcie 8080 nie zna adresu źródłowego połączeń przychodzących (np. Do logowania lub innych celów identyfikacyjnych).
źródło
Odpowiedź na 2015 / wrzesień:
ip6tables obsługuje teraz NAT IPV6: http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.17.txt
Będziesz potrzebował jądra 3.7+
Dowód:
źródło