Vraag Hoe een server op poort 80 als een normale gebruiker op Linux draaien?


Ik heb er al geruime tijd over googled, maar kon het niet vinden.

Ik ben op Ubuntu Linux en wil een server op poort 80 draaien, maar vanwege het beveiligingsmechanisme van Ubuntu krijg ik de volgende foutmelding:

java.net.BindException: machtiging geweigerd: 80

Ik denk dat het eenvoudig genoeg moet zijn om dit beveiligingsmechanisme uit te schakelen, zodat poort 80 beschikbaar is voor alle gebruikers of om de vereiste rechten toe te wijzen aan de huidige gebruiker om toegang te krijgen tot poort 80.


281
2017-11-10 14:31


oorsprong


Wat is het probleem om de server uit te voeren op een andere onbegunstigde poort? U denkt aan iets dat zo hard is als het uitschakelen van het beveiligingsmechanisme zonder op zijn minst een zeer ernstige reden te geven om een ​​server op die poort te laten draaien. Is de server hard gecodeerd om aan poort 80 te binden? Als dat zo is, gooi het weg. - Anonymous
Of een Python-foutbericht: socket.error: [Errno 13] Permission denied - Kazark
mogelijk duplicaat van Gewone gebruiker met poorten onder 1024 - Roman
Dat kan niet. Poorten onder 1024 zijn bevoorrecht en alleen root kan luisterende sockets op hen openen. Het juiste ding om te doen is om rechten te laten vallen na het openen ervan. - Falcon Momot
"Anoniem" - de gebruikers ter wereld zijn getraind om bepaalde diensten in bepaalde havens te zoeken. In sommige gevallen is het gestandaardiseerd. Bijvoorbeeld, HTTP op poort 80 en HTTPS op poort 443. Het is moeilijk om de gebruikers en standaarden van de wereld te veranderen. - jww


antwoorden:


Kort antwoord: dat kan niet. Poorten onder 1024 kunnen alleen door root worden geopend. Als per commentaar - nou ja, je kunt, met behulp van CAP_NET_BIND_SERVICE, maar die aanpak, toegepast op java bin, zorgt ervoor dat elk java-programma met deze instelling wordt uitgevoerd, wat ongewenst is, zo niet een beveiligingsrisico.

Het lange antwoord: je kunt verbindingen op poort 80 doorsturen naar een andere poort die je als normale gebruiker kunt openen.

Uitvoeren als root:

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Omdat loopback-apparaten (zoals localhost) geen gebruik maken van de prerouting-regels, moet je deze regel ook toevoegen als je localhost, enz. Moet gebruiken (bedankt @Francesco):

# iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080

OPMERKING: de bovenstaande oplossing is niet goed geschikt voor systemen met meerdere gebruikers, omdat elke gebruiker poort 8080 (of elke andere hoge poort die u besluit te gebruiken) kan openen, waardoor het verkeer wordt onderschept. (Dank aan CesarB).

EDIT: als per commentaarvraag - om de bovenstaande regel te verwijderen:

# iptables -t nat --line-numbers -n -L

Dit zal iets als:

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 redir ports 8088
2    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 8080

De regel waarin u geïnteresseerd bent, is nr. 2, dus om het te verwijderen:

# iptables -t nat -D PREROUTING 2

330
2017-11-10 14:41



@Sunny: upvotes zijn niet voor het snelste geweer in het westen, maar voor de beste antwoorden. De jouwe is tot nu toe de beste (ik noemde alleen iptables, je hebt de volledige commandolijn geleverd). Het enige dat de mijne van jou heeft is niet het voorbehoud dat andere gebruikers ook kunnen binden aan poort 8080. - CesarB
Merk op dat dit niet werkt met IPv6. - Emmanuel Bourg
Kan iemand uitleggen hoe ik deze regel later kan verwijderen als ik dat wil? Na het uitgevoerd te hebben, werkt het, maar het is blijkbaar geen "regel" omdat het niet verschijnt wanneer ik het doe sudo iptables --list. Ik weet wat iptables is en doet, maar ik heb het nog nooit eerder gebruikt. - Encoderer
Bedankt voor je antwoord ... als ik Ubuntu reboot, verdwijnt deze regel en moet ik hem opnieuw uitvoeren. Is er een manier om het voor altijd te bewaren? - Coderji
@Coderji: controleer het gedeelte "opslaan" in de communautaire documentatie: help.ubuntu.com/community/IptablesHowTo - Sunny


Gebruik authbind.

Het werkt zelfs met Java als u Java's IPv4-only stack inschakelt. Ik gebruik:

authbind --deep $JAVA_HOME/bin/java -Djava.net.preferIPv4Stack=true …

77
2017-11-14 13:12



Als de server Tomcat is, kunt u authbind automatisch gebruiken door deze in te stellen AUTHBIND=yes in / etc / default / tomcat6 - Emmanuel Bourg
Ik kon dit niet laten werken op de Ubuntu-server met het standaard Java-pakket ... - Ashley Steel
Ik ook geen bekende oplossing? - mark
Merk op dat u moet configureren authbind om dit echt te laten gebeuren. Van de manpagina: "/ etc / authbind / byport / port is getest.Als dit bestand toegankelijk is voor uitvoering aan de bellende gebruiker, volgens toegang (2), is het binden aan de poort toegestaan."b.v. voor poort 80, sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80. De eerste installatie van authbind heeft over het algemeen geen vooraf geconfigureerde autorisaties. - Jason C
Oh nonononononono, nooit nooit chmod 777! - Johannes


Als uw systeem dit ondersteunt, kunt u misschien mogelijkheden gebruiken. Zie man-capaciteiten, degene die je nodig hebt zou CAP_NET_BIND_SERVICE zijn.

Op nieuwere Debian / Ubuntu kunt u het volgende uitvoeren:

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program

45
2018-05-30 20:32



dit werkt voor nodejs: setcap 'cap_net_bind_service = + ep' / usr / bin / nodejs - JasonS
Deze. Ik vraag me af waarom dit antwoord niet meer upvotes heeft. Veel gemakkelijker dan de iptables-optie imho. - Dominik R
dit is het juiste en meest efficiënte antwoord, alle andere antwoorden veroorzaken een uitvoeringsteken of gewoon dubieus / onveilig. - OneOfOne


Een andere oplossing is om uw app setuid zo te maken dat deze met poort 80 kan binden. Doe als root het volgende

chown root ./myapp
chmod +S ./myapp

Houd er rekening mee dat wanneer je dit doet, tenzij het helemaal goed is gedaan, je wordt blootgesteld aan mogelijke beveiligingslekken, omdat je app met het netwerk praat en met volledige rootprivileges draait. Als je deze oplossing neemt, moet je kijken naar de broncode voor Apache of Lighttpd of iets dergelijks, waarbij ze de rootprivileges gebruiken om de poort te openen, maar dan onmiddellijk die privs opgeven en een minder bevoorrechte gebruiker worden, zodat een kaper kan uw hele computer niet overnemen.

Update: zoals te zien in deze vraag, het lijkt erop dat Linux-kernels sinds 2.6.24 een nieuwe mogelijkheid hebben waarmee je een uitvoerbaar bestand (maar niet een script, natuurlijk) kunt markeren als het hebben van de "CAP_NET_BIND_SERVICE"capability. Als u het debian pakket" libcap2-bin "installeert, kunt u dat doen door de opdracht uit te voeren

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

39
2017-11-10 14:44



Dat is hetzelfde als draaien als root, tenzij de app weet hoe je privileges moet verwijderen. - CesarB
Dit is gevaarlijk. Dit betekent dat elk verzoek als root zal worden uitgevoerd. Het is om een ​​reden dat zelfs apache begint als root om te binden, en dan de rechten naar een andere gebruiker laat vallen. - Sunny
Paul: de iptables is niet zo gevaarlijk, want zelfs als de app in gevaar wordt gebracht, zal het systeem niet worden blootgesteld aan aanvallen, althans niet met rootprivileges. De app als root uitvoeren is een ander verhaal. - Sunny
Het gevaar voor iptables is alleen als dit een systeem met meerdere gebruikers is, zoals CesarB zei, omdat iedereen zich kan binden aan 8080 en het verkeer kan onderscheppen. - Sunny
lol, houd van hoe het geaccepteerde antwoord een -15 heeft - Evan Teran


Aanpak voorgesteld door Sunny en CesarB:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

werkt prima, maar het heeft een klein nadeel - het voorkomt niet dat de gebruiker rechtstreeks verbinding maakt met poort 8080 in plaats van 80.

Overweeg het volgende scenario wanneer dit een probleem kan zijn.

Laten we zeggen dat we een server hebben die HTTP-verbindingen op poort 8080 en HTTPS-verbindingen op poort 8181 accepteert.

We gebruiken iptables om de volgende omleidingen vast te stellen:

80  ---> 8080
443 ---> 8181

Laten we aannemen dat onze server beslist om de gebruiker van een HTTP-pagina naar een HTTPS-pagina om te leiden. Tenzij we het antwoord zorgvuldig herschrijven, wordt het omgeleid naar https://host:8181/. Op dit punt zijn we genaaid:

  • Sommige gebruikers zouden een bladwijzer maken voor het https://host:8181/ URL en we zouden deze URL moeten behouden om te voorkomen dat de bladwijzers worden verbroken.
  • Andere gebruikers kunnen geen verbinding maken omdat hun proxyservers geen niet-standaard SSL-poorten ondersteunen.

Ik gebruik de volgende aanpak:

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT

In combinatie met de standaard REJECT-regel op de INPUT-keten voorkomt dit dat gebruikers rechtstreeks verbinding maken met de poorten 8080, 8181


35
2018-02-20 16:19



Dit is goed, maar waarom niet gewoon de daemon binden aan localhost: 8080 in plaats van 0.0.0.0: 8080? Ik wil dat doen, maar daarvoor heb ik de iptables nodig. - Amala
Het werkt, echt cool. - xtian


Ik gebruik gewoon Nginx voorop. Het kan ook op localhost worden uitgevoerd.

  • apt-get install nginx

.. of ..

  • pkg_add -r nginx 

.. of wat ooit bij je besturingssysteem past.

Alles wat u nodig hebt in nginx.conf, als het wordt uitgevoerd op localhost, is:

server {
        luister 80;
        servernaam some.domain.org;
        plaats / {
            proxy_set_header Host $ host;
            proxy_set_header X-Real-IP $ remote_addr;
            proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8081;
        }
}

34
2017-11-20 14:30



Ik hou echt van deze oplossing. - thomasfedb
Dit is (een van) de voorgestelde oplossing van JFrog zelf: jfrog.com/confluence/display/RTF/nginx - stolsvik


Traditioneel op Unix kan alleen root binden aan lage poorten (<1024).

De eenvoudigste manier om hier omheen te werken, is door uw server op a uit te voeren hoog poort (bijvoorbeeld 8080) en gebruik een eenvoudige iptables-regel om de verbindingen van poort 80 naar poort 8080 door te sturen. Houd er rekening mee dat u hiermee de extra bescherming van de lage poorten verliest; elke gebruiker op uw machine kan binden aan poort 8080.


29
2017-11-10 14:36





Als uw systeem dit ondersteunt, kunt u misschien mogelijkheden gebruiken. Zien man capabilities, degene die je nodig hebt zou zijn CAP_NET_BIND_SERVICE. Nee, ik heb ze nooit zelf gebruikt en ik weet niet of ze echt werken :-)


23
2017-11-10 16:27



ze werken, ik gebruik CAP_NET_RAW om tools zoals tcpdump als een normale gebruiker uit te voeren. - Justin


Gebruik een omgekeerde proxy (nginx, apache + mod_proxy) of een caching reverse proxy (Squid, Varnish) voor uw applicatieservers!

Met een omgekeerde proxy kunt u veel interessante dingen bereiken, zoals:

  • Load-balancing
  • Uw toepassingsservers opnieuw starten met gebruikers die een mooie foutpagina ontvangen
  • Versnel dingen met cache
  • Fijnmazige instellingen die u normaal gesproken met een reverse-proxy uitvoert en niet met een toepassingsserver

11
2017-10-18 15:36





Je kunt Redir-programma gebruiken:

sudo redir --lport=80 --laddr=192.168.0.101 --cport 9990 --caddr=127.0.0.1

6
2017-11-27 12:48