inetd (internet services daemon) è un demone presente su numerosi sistemi UNIX che controlla i servizi Internet. Apparso per la prima volta in 4.3BSD[1] , si trova solitamente in /usr/sbin/inetd.
Spesso chiamato Internet super-server[2], inetd si pone in ascolto su tutte le porte TCP ed UDP usate dai servizi internet quali FTP, POP3, o Telnet. Quando un pacchetto TCP o un pacchetto UDP arriva con un determinato numero di porta, inetd lancia l'appropriato servizio per stabilire la connessione. [3] Per servizi che non si aspettano un carico di lavoro molto alto, questo metodo usa la memoria in modo molto efficiente, dato che i server specifici vengono invocati solo quando necessario. Allo stesso modo, non è richiesto nessun codice di networking nei demoni specifici di ciascuna applicazione, dato che inetd aggancia i socket direttamente allo standard input, standard output e standard error del processo invocato. Per protocolli che invece hanno un traffico frequente, come HTTP e POP3, un server dedicato che possa intercettare direttamente il traffico, è da preferire.
Quello che segue è il codice C di un semplice servizio inetd, che accetta al più un parametro sulla riga di comando che specifica un nome di file per il log; in esso saranno trascritte tutte le stringhe inviate attraverso il socket. Il programma si basa un servizio di logging per un programma di elaborazione distribuita che dovrebbe essere in grado di accettare messaggi da processi multipli in esecuzione su macchine differenti. Utilizzando un servizio inetd per ricevere i messaggi di log, tutte le macchine possono indirizzare i messaggi al medesimo destinatario, che provvederà a memorizzarli in un unico file di log.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv)
{
/* questo è un buffer per i messaggi da registrare */
char str[4096];
/* puntatore al file di log */
FILE *fp = NULL;
/* se inetd passa un parametro, utilizziamolo come nome di file */
if(argc == 2)
fp = fopen(argv[1], "at");
else
/* altrimenti apriamo un file nella directory /tmp */
fp = fopen("/tmp/errorLog.txt", "at");
/* segnaliamo un errore se il file non può essere aperto */
if(fp == NULL)
return -1;
while(!feof(stdin))
{
/* preleviamo un massimo di 4095 caratteri, fino al ritorno carrello;
fgets aggiungera' per noi un byte null alla fine */
fgets(str, 4096, stdin);
/* scriviamo la stringa nel file, quindi effettuiamo il flushing */
fprintf(fp, "%s", str);
fflush(fp);
}
/* chiudiamo il file ed usciamo */
fclose(fp);
return 0;
}
In questo caso, vogliamo che tutti i messaggi siano scritti su un singolo file, così che l'esecuzione di una sola istanza del servizio possa soddisfare tutte le richieste; ciò significa che il protocollo giusto da utilizzare è l'UDP. Per prima cosa, bisogna scegliere un numero di porta non utilizzato. In questo esempio si userà la porta 9999, poiché era libera sul sistema in cui è stato sviluppato il sorgente. La voce di /etc/services sarà simile alla seguente:
errorLogger 9999/udp
E la voce in /etc/inetd.conf sarà simile alla seguente:
errorLogger dgram udp wait root /usr/local/sbin/errlogd errlogd /tmp/logfile.txt
La riga indica ad inetd di eseguire /usr/local/sbin/errlogd, passandogli come parametri errlogd /tmp/logfile.txt (si faccia riferimento alla pagina di manuale di inetd.conf per ulteriori informazioni sui parametri). Il primo parametro è sempre il nome del programma da eseguire, mentre il secondo (il numero 1 negli array C, in cui il primo elemento è marcato con uno 0) contiene il nome del file da utilizzare per il log, /tmp/logfile.txt. inetd eseguirà il servizio quando sarà necessario, e collegherà la porta 9999 agli stream di input ed output: tutte le stringhe inviate a quella porta verranno scritte sul file. L'opzione wait segnala ad inetd di utilizzare un'unica istanza del server per gestire tutte le richieste, a differenza dell'esempio proposto prima con telnet, in cui un nuovo server viene invocato per gestire ciascuna richiesta in arrivo.
Nota: le funzioni offerte dall'esempio vengono di solito implementate utilizzando SysLog ed un processo quale syslogd. syslogd sarebbe normalmente avviato in parallelo ad inetd, e non come servizio separato.
In anni recenti, a causa delle limitazioni di sicurezza nel progetto originale di inetd, lo si è sostituito con xinetd[4], rlinetd, ucspi-tcp ed altri ancora in molti sistemi. In particolare, le distribuzioni di GNU/Linux offrono molte opzioni e macOS (a partire dalla release 10.2) utilizza xinetd. Allo stato di Mac OS X 10.4, Apple ha unito le funzioni di inetd a launchd.
I servizi forniti da inetd non sono vitali, e possono essere disattivati completamente. Questa pratica sta diventando sempre più comune su macchine dedicate ad un'unica funzione. Ad esempio, un server HTTP potrebbe essere configurato per eseguire semplicemente httpd, tenendo chiuse tutte le altre porte. Un firewall dedicato potrebbe non avviare alcun servizio.
Mentre il concetto di inetd come smistatore di servizi non è intrinsecamente insicuro, la lunga lista di servizi di cui tradizionalmente inetd si occupa diede la sua bella dose di grattacapi agli amministratori di sistema. I servizi non sono perfetti, e in quanto tali bisogna considerare la possibilità che questi abbiano delle vulnerabilità sfruttabili o che vengano semplicemente abusati. Per questo motivo vennero disabilitati tutti i servizi non necessari e lo spegnimento di default divenne la norma. Nelle moderne distribuzioni Linux non è raro trovare un /etc/inetd.conf con quasi tutti i servizi commentati.