Zezwalanie użytkownikowi na słuchanie portu poniżej 1024

63

Muszę zezwolić użytkownikowi (innemu niż root) na uruchomienie serwera nasłuchującego na porcie 80.

Czy jest na to jakiś sposób?

peoro
źródło
1
To pytanie jest otwarte na interpretację. Mam nadzieję, że masz na myśli „utworzyłeś nową usługę systemową, którą ze względów bezpieczeństwa chciałbyś uruchomić na nieuprzywilejowanym koncie” (uważane za dobrą praktykę), a nie „Mam użytkownika, który pyta, czy może uruchomić własny serwer WWW w moim systemie, jak mogę pozwolić im na dostęp? ” (uważany za raczej kiepską praktykę)
Michael Shaw,
3
@Ptolemy, faktyczny powód jest taki: moja maszyna znajduje się za zaporą ogniową, która blokuje dowolny port oprócz 80. Chcę hostować serwer (który nie traci uprawnień!), Dlatego muszę go słuchać na porcie 80, ale nie nie ufaj, że będzie działał jako root (z oczywistych względów bezpieczeństwa). Mogę to zrobić, jeśli cię to obchodzi.
Peoro,
serverfault.com/questions/112795/…
Ciro Santilli 24 改造 中心 法轮功 六四 事件

Odpowiedzi:

50

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

zadziała to w przypadku określonych procesów. Ale aby umożliwić użytkownikowi powiązanie z portami poniżej 1024, musisz dodać go do sudoers.

Więcej informacji znajdziesz w tej dyskusji .

Rohan Monga
źródło
31

(Niektóre z tych metod zostały wymienione w innych odpowiedziach; Daję kilka możliwych wyborów w przybliżonej kolejności preferencji).

Możesz przekierować dolny port do wysokiego portu i nasłuchiwać na wysokim porcie.

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

Możesz uruchomić serwer jako uprawnienia root i upuszczać po tym, jak zaczął nasłuchiwać na uprzywilejowanym porcie. Najlepiej, niż samemu kodować, uruchom serwer z opakowania, które wykona zadanie za Ciebie. Jeśli serwer uruchamia jedną instancję na połączenie, uruchom ją z inetd(lub podobnego programu, takiego jak xinetd). Do inetdużyj takiej linii w /etc/inetd.conf:

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

Jeśli serwer nasłuchuje w jednym wystąpieniu, uruchom go z programu takiego jak authbind. Utwórz pusty plik /etc/authbind/byport/80i ustaw go jako wykonywalny dla użytkownika uruchamiającego serwer; lub utwórz /etc/authbind/byuid/1234, gdzie 1234 to UID działający na serwerze, zawierający wiersz 0.0.0.0/0:80,80.

Jeśli plik wykonywalny serwera jest przechowywany w systemie plików, który obsługuje możliwości, możesz dać mu taką możliwość . Uważaj, że możliwości są wciąż stosunkowo nowe i wciąż mają kilka problemów .cap_net_bind_service

setcap cap_net_bind_service=ep /path/to/server/executable
Gilles
źródło
4
W każdym przypadku, z którym miałem do czynienia, plikiem wykonywalnym był skrypt uruchamiający java lub python. Jako facet bez 10 godzin na drobiazgi, twoje rozwiązanie iptables pokrywa je bezboleśnie.
srking
W przypadku rozwiązania iptables musiałem również dodać regułę filtrowania, -A INPUT -p tcp --dport 1080 -j ACCEPTponieważ inaczej by to nie zadziałało (mam też -j DROPopcję catch-all). Mam więc dwa gniazda odsłuchowe.
thom_nic 10.01.2018
4

Krótka odpowiedź brzmi: z założenia nie jest to możliwe.

Długa odpowiedź brzmi: w światach open source jest wiele osób bawiących się projektowaniem i wymyślających alternatywne metody. Zasadniczo powszechnie przyjmuje się, że nie powinno to być możliwe. Fakt, że próbujesz, prawdopodobnie oznacza, że ​​masz kolejną wadę projektową w twoim systemie i powinieneś ponownie rozważyć całą architekturę systemu w świetle najlepszych praktyk * nix i implikacji bezpieczeństwa.

To powiedziawszy, jednym z programów autoryzujących dostęp użytkownika innego niż root do niskich portów jest authbind . Zarówno selinux, jak i grsecurity zapewniają również ramy dla takich drobiazgowych uwierzytelnień.

Na koniec, jeśli chcesz, aby niektórzy użytkownicy uruchamiali określone programy jako root, a tak naprawdę potrzebujesz tylko pozwolić użytkownikowi na ponowne uruchomienie apache lub coś takiego, sudoto twój przyjaciel!

Caleb
źródło
8
„Bezpieczeństwo” portu nie daje zbyt wiele we współczesnym świecie.
pjc50
3
@ pjc50: Tak. Chodzi o domniemane zaufanie. Niska liczba portów oznacza duże zaufanie. Oczekuje się, że SSH, POP, FTP i inne demony będą pytać o hasła na poziomie systemu i inne poświadczenia, gdy ich porty zostaną otwarte. Gdyby użytkownicy mogli nasłuchiwać na niskich portach na urządzeniu, mogliby uruchomić fałszywe demony na nieużywanych (lub ulegających awarii) portach i zbierać hasła od niczego niepodejrzewających użytkowników. Hasła te mogą być następnie wykorzystane w tym polu do złamania zabezpieczeń innych kont, w tym root.
Caleb,
8
To dość słaba forma bezpieczeństwa. Jeśli połączyłeś się z czymś i nie wykonałeś transakcji certyfikatem, nie masz pojęcia, z kim rozmawiasz - tj. Ataki MITM.
pjc50
5
Przypuszczam, że to, co jest potrzebne, to chown dla portów: wtedy możesz „chown mail port25”, a następnie (a) demona poczty nie trzeba uruchamiać przy pomocy roota i (b) nikt inny nie może go przejąć.
pjc50
7
Chociaż mogło to być prawdą „z założenia”, gdy Linux był w powijakach, nie ma to zbyt wiele sensu. Bezpieczeństwo polega na tym, co użytkownik może, a czego nie może zrobić. Na przykład zezwolenie tylko użytkownikowi root na korzystanie z portu 80 stanowi ogromne zagrożenie bezpieczeństwa, ponieważ oznacza, że ​​musisz dać dostęp do konta root osobom, które muszą korzystać z portu 80, ale nie powinny mieć dostępu do konta root. Jeśli ufasz, że użytkownik X inny niż root użyje portu 80, powinieneś być w stanie zakodować to zaufanie w swoim systemie operacyjnym. Na szczęście, jak wspomniałeś, istnieją okropne obejścia, które na to pozwalają, na przykład authbind.
BT
3

Możesz użyć przekierowania portów netcat, xinetd lub iptables, albo użyć apache jako serwera proxy frontonu i uruchomić proces na nieuprzywilejowanym porcie.

jamespo
źródło
3

Authbind , @Gilles już o tym wspominał, ale chciałbym trochę rozwinąć.

Ma wygodną kontrolę dostępu (szczegóły na stronie podręcznika): możesz filtrować dostęp według portu, adresu interfejsu, identyfikatora użytkownika, zakresów adresów lub portów oraz ich kombinacji.

Ma bardzo przydatny parametr --depth:

- poziomy głębokości

Powoduje, że authbind wpływa na programy znajdujące się głęboko na grafie wywołującym. Wartość domyślna to 1.

„Głębokie poziomy” oznacza, że ​​kiedy skrypt (lub program) uruchamia inny skrypt, schodzi z poziomu. Więc jeśli masz, --depth 5to znaczy na poziomach 1 (czy to 0?) Do 5, masz pozwolenie na wiązanie, podczas gdy na poziomie 6 i dalej nie. Przydatne, gdy chcesz, aby skrypt miał dostęp, ale nie programy, które uruchamia się z Twoją wiedzą lub bez niej.


Aby to zilustrować, możesz mieć coś takiego: ze względów bezpieczeństwa masz użytkownika, javaktóry ma tylko uruchamiać Javę i chcesz dać mu dostęp do portu 80:

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

Stworzyłem ../byport/80 file, podając go javagrupie użytkowników (każdy użytkownik ma swoją własną grupę), i sprawiłem, że jest wykonywalna według grupy, co oznacza, że ​​może być wykonywana przez javaużytkownika. Jeśli dajesz dostęp według portu, plik musi być wykonywalny przez użytkownika, który powinien mieć dostęp, więc to zrobiliśmy.

Może to wystarczyć dla przeciętnego Joe, ale ponieważ wiesz, jak używać tego --depthparametru, biegniesz (jako javaużytkownik) authbind --depth [depth] my_web_app's_start_scriptzaczynając od --depth 1i pracując w górę, aż znajdziesz najmniejszą głębokość, która działa i używa tego.

Przeczytaj stronę podręcznika, aby uzyskać szczegółowe informacje .

Dominykas Mostauskis
źródło
1

Próbowałem metody iptables PREROUTING REDIRECT, ale okazało się, że wpływa ona również na przesyłane pakiety. Oznacza to, że jeśli maszyna 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.

Jedną z możliwości jest użycie przekierowania portów TCP. Np. Używając socat:

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

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).

Craig McQueen
źródło