Consentire a un utente di consentire l'ascolto di una porta inferiore a 1024


63

Devo consentire a un utente (diverso dal root) di eseguire un server in ascolto sulla porta 80.

C'è un modo per fare questo?


1
Questa domanda è aperta all'interpretazione. Spero che tu intenda "hai creato un nuovo servizio di sistema che tu (come root) vorresti eseguire in un account non privilegiato per motivi di sicurezza" (considerata buona pratica) e non "Ho un utente a cui è stato chiesto se possono eseguire il proprio server Web sul mio sistema, come posso consentire loro l'accesso? " (considerata pratica piuttosto scadente)
Michael Shaw,

3
@Ptolemy, il vero motivo è: la mia macchina è dietro un firewall che blocca qualsiasi porta tranne l'80. Voglio ospitare un server (che non rilascia privilegi!), Quindi devo averlo in ascolto sulla porta 80, ma don non fidarti che funzioni come root (per ovvi motivi di sicurezza). Mi è permesso farlo, se ti interessa.
peoro,

Risposte:


50

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

questo funzionerà per processi specifici. Ma per consentire a un determinato utente di collegarsi alle porte inferiori a 1024 dovrai aggiungerlo ai sudoer.

Dai un'occhiata a questa discussione per saperne di più.


31

(Alcuni di questi metodi sono stati menzionati in altre risposte; sto dando diverse possibili scelte in ordine di preferenza approssimativo.)

È possibile reindirizzare la porta bassa a una porta alta e ascoltare sulla porta alta.

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

Puoi avviare il tuo server come root e rilasciare i privilegi dopo aver iniziato l'ascolto sulla porta privilegiata. Preferibilmente, piuttosto che codificarlo tu stesso, avvia il tuo server da un wrapper che fa il lavoro per te. Se il tuo server avvia un'istanza per connessione, avviarla da inetd(o un programma simile come xinetd). Per inetd, utilizzare una linea come questa in /etc/inetd.conf:

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

Se il server è in ascolto in una singola istanza, avviarlo da un programma come authbind. Creare un file vuoto /etc/authbind/byport/80e renderlo eseguibile per l'utente che esegue il server; oppure creare /etc/authbind/byuid/1234, dove 1234 è l'UID che esegue il server, contenente la linea 0.0.0.0/0:80,80.

Se il file eseguibile del tuo server è archiviato su un filesystem che supporta le funzionalità, puoi dargli la possibilità . Attenzione che le funzionalità sono ancora relativamente nuove e presentano ancora qualche nodo .cap_net_bind_service

setcap cap_net_bind_service=ep /path/to/server/executable

4
In ogni caso con cui ho avuto a che fare, l'eseguibile era uno script che lanciava Java o Python. Come un ragazzo senza 10 ore da spendere per i punti fini, la tua soluzione iptables lo copre indolore.
arrivo il

Per la soluzione iptables, ho dovuto anche aggiungere una regola di filtro come -A INPUT -p tcp --dport 1080 -j ACCEPTaltrimenti non funzionerebbe (ho anche un -j DROPcatch-all.) Quindi sono rimasto con due socket di ascolto.
Thom_nic

4

La risposta breve è che ciò non è possibile in base alla progettazione.

La lunga risposta è che nei mondi open source ci sono molte persone che giocano con il design e escogitano metodi alternativi. In generale, è ampiamente riconosciuto che ciò non dovrebbe essere possibile. Il fatto che stai provando probabilmente significa che hai un altro errore di progettazione nel tuo sistema e dovresti riconsiderare l'intera architettura del tuo sistema alla luce delle migliori pratiche e delle implicazioni di sicurezza di * nix.

Detto questo, un programma per autorizzare l'accesso non root a porte basse è authbind . Sia selinux che grsecurity forniscono anche framework per autenticazioni così ottimizzate.

Infine, se vuoi che determinati utenti eseguano programmi specifici come root e ciò di cui hai veramente bisogno è solo consentire a un utente di riavviare apache o qualcosa del genere, sudoè tuo amico!


8
La "sicurezza" portuale non ti dà davvero molto nel mondo moderno.
pjc50,

3
@ pjc50: Sì, lo fa. Riguarda la fiducia implicita. I numeri di porta bassi implicano un'alta fiducia. SSH, POP, FTP e altri demoni dovrebbero richiedere password a livello di sistema e altre credenziali quando le loro porte vengono aperte. Se gli utenti potessero ascoltare su porte basse su una scatola, potrebbero avviare demoni falsi su porte inutilizzate (o bloccate) e raccogliere password da utenti ignari. Tali password potrebbero quindi essere utilizzate su quella casella per compromettere altri account, incluso root.
Caleb,

8
Questa è una forma piuttosto debole di sicurezza. Se ti sei collegato a qualcosa e non hai effettuato una transazione di certificato, non hai idea di con chi stai parlando, ad esempio gli attacchi MITM.
pjc50,

5
Suppongo che ciò che è necessario sia chown per le porte: quindi potresti "chown mail port25" quindi (a) il tuo demone della posta non deve essere avviato con i privilegi di root e (b) nessun altro può dirottarlo.
pjc50,

7
Anche se questo potrebbe essere stato vero "di progettazione" quando Linux era agli inizi, ha poco senso allora e ora. La sicurezza è tutto ciò che un utente può e non può fare. Consentire solo all'utente root di utilizzare la porta 80, ad esempio, è un enorme rischio per la sicurezza, poiché significa che è necessario fornire l'accesso root a chi deve utilizzare la porta 80 ma non dovrebbe avere accesso root. Se ritieni che l'utente non root X utilizzi la porta 80, dovresti essere in grado di codificare tale attendibilità nel tuo sistema operativo. Fortunatamente, come hai accennato, ci sono dei malcontenti rimedi che lo consentono, come authbind.
BT,

3

È possibile utilizzare il port forwarding netcat o xinetd o iptables oppure utilizzare apache come proxy front-end ed eseguire il processo su una porta non privilegiata.


3

Authbind , @Gilles lo ha già menzionato, ma vorrei ampliarlo un po '.

Ha un comodo controllo degli accessi (dettagli nella pagina man): puoi filtrare l'accesso per porta, indirizzo dell'interfaccia, uid, intervalli di indirizzo o porta e combinazione di questi.

Ha un parametro molto utile --depth:

- livelli di profondità

Fa sì che authbind influisca sui programmi con livelli profondi nel grafico chiamante. L'impostazione predefinita è 1.

"Livelli profondi" significa che quando uno script (o programma), esegue un altro script, scende di livello. Quindi se ce l'hai --depth 5significa dai livelli 1 (o è 0?) Attraverso 5 hai il permesso di legare, mentre al livello 6 e oltre, non lo fai. Utile quando si desidera che uno script abbia accesso, ma non i programmi che viene eseguito con o senza la propria conoscenza.


Per illustrare, potresti avere qualcosa del genere: per motivi di sicurezza, hai un utente javache ha lo scopo di eseguire solo Java e vuoi dargli accesso alla porta 80:

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

Ho creato il ../byport/80 file, dato al javagruppo di utenti (ogni utente ha il proprio gruppo) e l'ho reso eseguibile per gruppo, il che significa che è eseguibile javadall'utente. Se stai dando accesso per porta, il file deve essere eseguibile dall'utente che dovrebbe avere accesso, quindi l'abbiamo fatto.

Questo potrebbe essere sufficiente per il Joe medio, ma poiché sai come usare il --depthparametro, corri (come javautente) a authbind --depth [depth] my_web_app's_start_scriptpartire --depth 1e lavorando fino a trovare la profondità più piccola che funziona e usarlo.

Leggi la pagina man per i dettagli .


1

Ho provato il metodo iptables PREROUTING REDIRECT, ma ho scoperto che influenza anche i pacchetti inoltrati. Cioè, se la macchina inoltra anche pacchetti tra le interfacce (ad es. Se agisce come un punto di accesso Wi-Fi collegato a una rete Ethernet), la regola iptables rileverà anche le connessioni dei client collegati a destinazioni Internet e li reindirizzerà a la macchina. Non è quello che volevo, volevo solo reindirizzare le connessioni dirette alla macchina stessa.

Una possibilità è utilizzare il port forwarding TCP. Ad esempio usando socat:

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

Tuttavia uno svantaggio di questo metodo è che l'applicazione in ascolto sulla porta 8080 non conosce l'indirizzo di origine delle connessioni in entrata (ad es. Per la registrazione o altri scopi di identificazione).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.