GNU/Linux >> Linux Esercitazione >  >> Linux

Consentire al processo non root di collegarsi alla porta 80 e 443?

Non sono sicuro a cosa si riferiscano le altre risposte e commenti qui. Questo è possibile piuttosto facilmente. Ci sono due opzioni, entrambe che consentono l'accesso a porte con un numero basso senza dover elevare il processo a root:

Opzione 1:utilizza CAP_NET_BIND_SERVICE per concedere a un processo l'accesso a una porta con un numero basso:

Con questo puoi concedere l'accesso permanente a un binario specifico da associare a porte con un numero basso tramite setcap comando:

sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary

Per maggiori dettagli sulla parte e/i/p, vedi cap_from_text .

Dopo aver fatto ciò, /path/to/binary sarà in grado di collegarsi a porte con un numero basso. Nota che devi usare setcap sul file binario stesso piuttosto che su un collegamento simbolico.

Opzione 2:utilizza authbind per concedere l'accesso una tantum, con un controllo utente/gruppo/porta più accurato:

Il authbind (man page) esiste proprio per questo.

  1. Installa authbind utilizzando il tuo gestore di pacchetti preferito.

  2. Configuralo per concedere l'accesso alle porte pertinenti, ad es. per consentire 80 e 443 da tutti gli utenti e gruppi:

    sudo touch /etc/authbind/byport/80
    sudo touch /etc/authbind/byport/443
    sudo chmod 777 /etc/authbind/byport/80
    sudo chmod 777 /etc/authbind/byport/443
    
  3. Ora esegui il tuo comando tramite authbind (facoltativamente specificando --deep o altri argomenti, vedere la pagina man):

    authbind --deep /path/to/binary command line args
    

    Ad esempio

    authbind --deep java -jar SomeServer.jar
    

Ci sono lati positivi e negativi in ​​​​entrambi i precedenti. L'opzione 1 concede fiducia al binario ma non fornisce alcun controllo sull'accesso per porta. L'opzione 2 concede fiducia all'utente/gruppo e fornisce il controllo sull'accesso per porta, ma le versioni precedenti supportavano solo IPv4 (da quando l'ho scritto originariamente, sono state rilasciate versioni più recenti con supporto IPv6).


Dale Hagglund è perfetto. Quindi dirò la stessa cosa ma in modo diverso, con alcuni dettagli ed esempi. ☺

La cosa giusta da fare nei mondi Unix e Linux è:

  • avere un programma piccolo, semplice, facilmente controllabile, che viene eseguito come superutente e collega il socket di ascolto;
  • avere un altro programma piccolo, semplice, facilmente controllabile, che elimina i privilegi, generato dal primo programma;
  • per avere la carne del servizio, in un terzo separato programma, eseguito con un account non superutente e catena caricata dal secondo programma, aspettandosi di ereditare semplicemente un descrittore di file aperto per il socket.

Hai un'idea sbagliata di dove sia l'alto rischio. Il rischio elevato è leggere dalla rete e agire in base a ciò che viene letto non nei semplici atti di aprire un socket, associarlo a una porta e chiamare listen() . È la parte di un servizio che fa la comunicazione effettiva che è ad alto rischio. Le parti che si aprono, bind() e listen() , e anche (in una certa misura) la parte che accepts() , non sono ad alto rischio e possono essere eseguiti sotto l'egida del superutente. Non usano e non agiscono su (con l'eccezione degli indirizzi IP di origine nel accept() caso) dati che sono sotto il controllo di estranei non fidati sulla rete.

Ci sono molti modi per farlo.

inetd

Come dice Dale Hagglund, il vecchio "superserver di rete" inetd fa questo. L'account con cui viene eseguito il processo di servizio è una delle colonne in inetd.conf . Non separa la parte di ascolto e la parte di eliminazione dei privilegi in due programmi separati, piccoli e facilmente verificabili, ma separa il codice di servizio principale in un programma separato, exec() ed in un processo di servizio che genera con un descrittore di file aperto per il socket.

La difficoltà dell'auditing non è un gran problema, dato che si deve audire solo un programma. inetd Il problema principale di non è tanto l'auditing, quanto piuttosto il fatto che non fornisce un semplice controllo granulare del servizio di runtime, rispetto agli strumenti più recenti.

UCSPI-TCP e daemontools

I pacchetti UCSPI-TCP e daemontools di Daniel J. Bernstein sono stati progettati per fare questo insieme. In alternativa, è possibile utilizzare il set di strumenti daemontools-encore ampiamente equivalente di Bruce Guenter.

Il programma per aprire il descrittore di file socket e collegarsi alla porta locale privilegiata è tcpserver , da UCSPI-TCP. Fa entrambi i listen() e il accept() .

tcpserver quindi genera un programma di servizio che elimina i privilegi di root (poiché il protocollo servito prevede l'avvio come superutente e quindi il "accesso", come nel caso, ad esempio, di un demone FTP o SSH) o setuidgid che è un piccolo programma autonomo e facilmente verificabile che elimina esclusivamente i privilegi e quindi concatena i carichi al programma di servizio vero e proprio (nessuna parte del quale quindi viene mai eseguita con privilegi di superutente, come nel caso, ad esempio, di qmail-smtpd ).

Un servizio run script sarebbe quindi ad esempio (questo per dummyidentd per fornire un servizio IDENT nullo):

#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl

nosh

Il mio pacchetto nosh è progettato per fare questo. Ha un piccolo setuidgid utilità, proprio come gli altri. Una piccola differenza è che è utilizzabile con systemd in stile "LISTEN_FDS" così come con i servizi UCSPI-TCP, quindi il tradizionale tcpserver program è sostituito da due programmi separati:tcp-socket-listen e tcp-socket-accept .

Ancora una volta, le utilità monouso si generano e si caricano a catena l'una con l'altra. Una stranezza interessante del design è che si possono eliminare i privilegi di superutente dopo listen() ma prima ancora di accept() . Ecco un run script per qmail-smtpd che in effetti fa esattamente questo:

#!/bin/nosh
fdmove -c 2 1
clearenv --keep-path --keep-locale
envdir env/
softlimit -m 70000000
tcp-socket-listen --combine4and6 --backlog 2 ::0 smtp
setuidgid qmaild
sh -c 'exec \
tcp-socket-accept -v -l "${LOCAL:-0}" -c "${MAXSMTPD:-1}" \
ucspi-socket-rules-check \
qmail-smtpd \
'

I programmi che vengono eseguiti sotto l'egida del superutente sono i piccoli strumenti di caricamento a catena indipendenti dai servizi fdmove , clearenv , envdir , softlimit , tcp-socket-listen e setuidgid . Al punto che sh viene avviato, il socket è aperto e associato al smtp port e il processo non ha più privilegi di superutente.

s6, s6-networking ed execline

I pacchetti di rete s6 e s6 di Laurent Bercot sono stati progettati per fare questo insieme. I comandi sono strutturalmente molto simili a quelli di daemontools e UCSPI-TCP.

run gli script sarebbero più o meno gli stessi, eccetto per la sostituzione di s6-tcpserver per tcpserver e s6-setuidgid per setuidgid . Tuttavia, si potrebbe anche scegliere di utilizzare contemporaneamente il set di strumenti execline di M. Bercot.

Ecco un esempio di un servizio FTP, leggermente modificato rispetto all'originale di Wayne Marshall, che utilizza execline, s6, s6-networking e il programma del server FTP da publicfile:

#!/command/execlineb -PW
multisubstitute {
    define CONLIMIT 41
    define FTP_ARCHIVE "/var/public/ftp"
}
fdmove -c 2 1
s6-envuidgid pubftp 
s6-softlimit -o25 -d250000 
s6-tcpserver -vDRH -l0 -b50 -c ${CONLIMIT} -B '220 Features: a p .' 0 21 
ftpd ${FTP_ARCHIVE}

ipsvd

Ipsvd di Gerrit Pape è un altro set di strumenti che funziona sulla stessa linea di ucspi-tcp e s6-networking. Gli strumenti sono chpst e tcpsvd questa volta, ma fanno la stessa cosa e il codice ad alto rischio che esegue la lettura, l'elaborazione e la scrittura di cose inviate in rete da client non fidati è ancora in un programma separato.

Ecco l'esempio di M. Pape sull'esecuzione di fnord in un run script:

#!/bin/sh
exec 2>&1
cd /public/10.0.5.4
exec \
chpst -m300000 -Uwwwuser \
tcpsvd -v 10.0.5.4 443 sslio -v -unobody -//etc/fnord/jail -C./cert.pem \
fnord

systemd

systemd , il nuovo sistema di supervisione dei servizi e init che si trova in alcune distribuzioni Linux, ha lo scopo di fare ciò che inetd può fare. Tuttavia, non utilizza una suite di piccoli programmi autonomi. Bisogna audire systemd nella sua interezza, purtroppo.

Con systemd uno crea file di configurazione per definire un socket che systemd in ascolto e un servizio che systemd inizia. Il file "unità" del servizio ha impostazioni che consentono un grande controllo sul processo del servizio, incluso l'utente con cui viene eseguito.

Con quell'utente impostato come non superutente, systemd fa tutto il lavoro di aprire il socket, associarlo a una porta e chiamare listen() (e, se richiesto, accept() ) nel processo n. 1 come superutente e il processo di servizio che genera viene eseguito senza privilegi di superutente.


Ho un approccio piuttosto diverso. Volevo usare la porta 80 per un server node.js. Non sono riuscito a farlo poiché Node.js è stato installato per un utente non sudo. Ho provato a utilizzare i collegamenti simbolici, ma non ha funzionato per me.

Poi ho scoperto che posso inoltrare le connessioni da una porta a un'altra. Quindi ho avviato il server sulla porta 3000 e ho impostato un port forward dalla porta 80 alla porta 3000.

Questo collegamento fornisce i comandi effettivi che possono essere utilizzati per eseguire questa operazione. Ecco i comandi -

host locale/loopback

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

esterno

sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000

Ho usato il secondo comando e ha funzionato per me. Quindi penso che questa sia una via di mezzo per non consentire al processo utente di accedere direttamente alle porte inferiori, ma concedere loro l'accesso utilizzando il port forwarding.


Linux
  1. UNIX/Linux:come crontab convalida l'accesso in base ai file cron.allow e cron.deny

  2. Bloccare l'accesso alla rete di un processo?

  3. Associa a porte inferiori a 1024 senza accesso root

  4. stordisci il traffico VPN e assicurati che assomigli al traffico SSL sulla porta 443

  5. Perché un provider di hosting non dovrebbe consentire SSL sulla porta 443?

Ubuntu 22.04 apre la porta HTTP 80 e la porta HTTPS 443 con ufw

Come trovare l'ID di processo di un programma e ucciderlo [Suggerimento rapido]

Come aprire le porte 80 e 443 in FirewallD

Come consentire SFTP e non consentire SSH?

Ssh:come rifiutare un processo in esecuzione e associarlo a una nuova shell dello schermo?

Come scrivere ed eseguire un programma C in Linux