[indice generale] [precedente] [successivo] [indice analitico] [note introduttive]

124. Accesso a Internet attraverso una linea commutata

Per concedere un accesso a Internet, attraverso una connessione telefonica, così come fa normalmente un ISP (Internet Service Provider), bisogna predisporre un sistema Linux munito di molte porte seriali e di altrettanti modem in attesa di chiamata. In questo capitolo non verranno presentati i problemi tecnici legati all'installazione di una scheda seriale multipla, dal momento che questi variano da modello a modello, mentre ci si vuole concentrare sulla configurazione di getty e sull'attivazione del PPP.

Nel capitolo si fa riferimento a programmi e a concetti già presentati in precedenza, che vengono richiamati per favorire il lettore.

124.1 Configurazione delle porte seriali

Dovendo gestire le porte seriali, è opportuno preoccuparsi della loro impostazione attraverso il programma setserial, già descritto nel capitolo 81. Per questo si realizza solitamente uno script da includere nella procedura di inizializzazione del sistema. Potrebbe trattarsi di /etc/rc.d/rc.serial, o qualcosa di simile. Il suo contenuto potrebbe assomigliare all'esempio che segue.

#!/bin/sh

echo "Configurazione delle porte seriali..."

/bin/setserial /dev/ttyS0 port 0x3F8 irq 4
/bin/setserial /dev/ttyS1 port 0x2F8 irq 3

Se si utilizza una scheda seriale multipla, è molto probabile che si debba indicare lo stesso IRQ per tutte le porte, mentre queste si distinguono solo in base agli indirizzi di I/O. Nello stesso modo, potrebbe essere necessario specificare più elementi, come il tipo di UART, e forse dei flag spd_* (purché siano tollerati dal kernel).

Una volta configurate le porte, prima di procedere oltre, è necessario fare degli esperimenti collegando un modem e comunicando con questo attraverso un programma per la gestione del terminale, come minicom. Con qualche comando AT, si può verificare se il collegamento tra modem e computer è funzionante, oppure se la porta seriale richiede qualche accorgimento di configurazione ulteriore.

124.2 getty_ps, uugetty

Il pacchetto getty_ps, e precisamente il programma uugetty, non rappresenta la scelta ottima per risolvere il problema dell'accesso da un terminale seriale, attraverso la linea commutata e il modem. Tuttavia, la sua semplicità permette di comprendere meglio ciò che si fa.

uugetty richiede la presenza del file /etc/gettydefs, che serve a definire le caratteristiche elementari dei diversi tipi di linea. Nel caso delle connessioni via modem da linea commutata, sono necessarie in particolare le direttive seguenti.

230400# B230400 CS8 CRTSCTS # B230400 SANE -ISTRIP HUPCL CRTSCTS #@S login: 
#115200

115200# B115200 CS8 CRTSCTS # B115200 SANE -ISTRIP HUPCL CRTSCTS #@S login: 
#57600

57600# B57600 CS8 CRTSCTS # B57600 SANE -ISTRIP HUPCL CRTSCTS #@S login: #38400

38400# B38400 CS8 CRTSCTS # B38400 SANE -ISTRIP HUPCL CRTSCTS #@S login: #19200

19200# B19200 CS8 CRTSCTS # B19200 SANE -ISTRIP HUPCL CRTSCTS #@S login: #9600

9600# B9600 CS8 CRTSCTS # B9600 SANE -ISTRIP HUPCL CRTSCTS #@S login: #2400

2400# B2400 CS8 CRTSCTS # B2400 SANE -ISTRIP HUPCL CRTSCTS #@S login: #230400

Una volta verificata la presenza di questo file, e dopo aver visto che il contenuto è corretto, si possono predisporre i file di configurazione di ogni linea, che generalmente vengono collocati nella directory /etc/default/. L'esempio seguente fa riferimento alla prima porta seriale, /dev/ttyS0, e si concretizza nel file /etc/default/uugetty.ttyS0.

Se si è sicuri che i dispositivi obsoleti per le chiamate in uscita, contrassegnati dai file /etc/cua*, non vengono utilizzati, si può realizzare un unico file di configurazione per tutte le linee seriali gestite, ammesso che si abbiano a disposizione gli stessi modem, o almeno che questi accettino le stesse sequenze di inizializzazione.

#=======================================================================
# /etc/default/uugetty.ttyS0
#
# Configurazione per un modem compatibile Hayes.
#=======================================================================

#-----------------------------------------------------------------------
# Se si devono usare i dispositivi /dev/cua* per le comunicazioni
# in uscita, occorre togliere il commento alle righe seguenti.
# Se non fosse per questo, il file di configurazione potrebbe essere
# standardizzato per ogni linea seriale.
#-----------------------------------------------------------------------
#ALTLOCK=cua0
#ALTLINE=cua0
#INITLINE=cua0

#-----------------------------------------------------------------------
# Disconnette se resta inattivo per il numero di secondi specificato.
#-----------------------------------------------------------------------
TIMEOUT=60

#-----------------------------------------------------------------------
# Sequenza di inizializzazione del modem, che viene messo nella
# modalità di risposta automatica, al primo squillo.
# Per le particolarità del modem, si presume che il suo profilo interno
# di configurazione sia stato predisposto nel modo più opportuno
# (si utilizza il comando ATZ per richiamarlo).
# La sequenza ha il formato:
# 	<attesa> <invio> <attesa> <invio>...
#-----------------------------------------------------------------------
INIT="" \d+++\dAT\r OK\r\n ATH0\r OK\r\n ATZ\r OK\r\n  ATM0E1Q0V1X3S0=1\r OK\r\n

#-----------------------------------------------------------------------
# Si specifica un ritardo di un secondo prima di inviare la richiesta
# del login.
#-----------------------------------------------------------------------
DELAY=1

Infine, occorre inserire la chiamata di uugetty nel file /etc/inittab, con una riga per ogni porta seriale, e per ogni modem gestito.

s0:2345:respawn:/sbin/uugetty -d /etc/default/uugetty.ttyS0 ttyS0 115200 vt100
s1:2345:respawn:/sbin/uugetty -d /etc/default/uugetty.ttyS1 ttyS1 115200 vt100
#...

È bene ricordare che il numero 115200, che appare tra gli argomenti, fa riferimento alla voce corrispondente nel file /etc/gettydefs, e precisamente a quella seguente.

115200# B115200 CS8 CRTSCTS # B115200 SANE -ISTRIP HUPCL CRTSCTS #@S login: 
#57600

Se per qualche motivo si ritiene di voler iniziare da una velocità più bassa, basta cambiare questo argomento, per esempio con 57600, 38400,...

Prima di proseguire, occorre verificare che la connessione funzioni, e per farlo basta preparare un account di prova a cui sia abbinata una shell normale. Se tutto va bene, si deve poter chiamare il numero di telefono dove deve rispondere il modem appena preparato, attraverso un altro computer e un altro modem, per mezzo di un programma di gestione del terminale. Si deve riuscire a ottenere una connessione normale, via terminale.

124.3 Attivazione del PPP

L'attivazione del PPP sarebbe una cosa relativamente semplice, se non ci fosse il problema della definizione dinamica degli indirizzi IP. Di solito, si deve fare in modo che per ogni modem disponibile in ricezione venga assegnato lo stesso indirizzo IP remoto, cioè abbinato all'host dell'utente che si connette attraverso il telefono. L'indirizzo IP locale può essere sempre lo stesso, e di solito si tratta anche di un numero già utilizzato per un'altra interfaccia di rete, tanto non viene definito alcun instradamento sul lato locale della connessione PPP.

A titolo di esempio, si può decidere di utilizzare gli indirizzi seguenti:

Dalla parte locale si può decidere di usare sempre l'indirizzo 192.168.11.1. Si osservi la figura 124.1

192.168.11.10		   192.168.11.1	+---------------+
----------------------------------------| ttyS0		|
					|		| 192.168.11.1
					|  Host    eth0	|------+
192.168.11.11		   192.168.11.1	|		|      |
----------------------------------------| ttyS1		|      |
					+---------------+      |
	Linee seriali                                          |
							       |
							+--------------+
							|    Router    |
							+--------------+
							       |
							       V
							   Internet

Figura 124.1: Schema di esempio della distribuzione degli indirizzi IP. Per risparmiare numeri IP, viene dato lo stesso numero assegnato all'interfaccia eth0 anche alla parte locale dei collegamenti PPP.

124.4 Configurazione del PPP

La soluzione del problema dell'assegnazione degli indirizzi IP si risolve con i file di configurazione di pppd distinti in base al dispositivo seriale attraverso cui si intende convogliare il protocollo. Si comincia generalmente dalla configurazione generale del file /etc/ppp/options, che potrebbe assomigliare all'esempio seguente.

nodetach
modem
crtscts
ms-dns 192.168.1.1
proxyarp

Eventualmente si potrebbe decidere di aggiungere la direttiva netmask 255.255.255.255 che è la più appropriata nelle connessioni da punto a punto.

Si osservi la direttiva ms-dns che permette agli utenti che accedono attraverso il sistema operativo Windows di ottenere automaticamente l'indicazione dell'indirizzo IP del server DNS.

pppd permette di definire una serie di altri file di configurazione che servono a contenere le direttive specifiche per ogni linea di terminale, composti con un nome che abbia il modello /etc/ppp/options.<linea>. Per tornare all'esempio presentato, le particolarità della connessione attraverso la prima porta seriale potrebbero essere inserite nel file /etc/ppp/options.ttyS0. In pratica, si tratta di definire solo gli indirizzi IP.

192.168.11.1:192.168.11.10

L'esempio si riferisce alla prima porta seriale, e con questo si vuole indicare che l'indirizzo locale è 192.168.11.1, mentre quello all'altro capo della connessione è 192.168.11.10. Volendo sistemare la seconda porta seriale, occorrerebbe creare il file /etc/ppp/options.ttyS1 con il contenuto seguente.

192.168.11.1:192.168.11.11

124.5 Shell di avvio del servizio

Per fare in modo che dopo il login venga attivato il PPP, occorre abbinare agli utenti una shell speciale: uno script che avvia pppd. Questo script potrebbe essere più o meno complesso, per esempio allo scopo di verificare se l'utente ha diritto di accedere in base alle fasce orarie che gli sono state concesse, o secondo altri criteri. Alla fine, si deve avviare pppd chiudendo il processo che interpretava lo script (il comando exec).

#!/bin/sh
#
# /usr/bin/utente_ppp
#

/usr/bin/mesg n
/bin/stty -tostop

# Verifica che l'utente possa accedere.
if /usr/sbin/acua_login
then
    # L'utente viene accolto.
    echo Benvenuto $LOGNAME
else
    # L'utente viene estromesso e gli si dà modo di verificarne il
    # motivo.
    /usr/sbin/acua viewRec
    echo Premere un tasto per continuare
    read
    logout
fi

# Attiva la connessione PPP secondo la configurazione.
echo "Viene attivata la connessione PPP."
exec /usr/sbin/pppd

L'esempio appena mostrato, fa riferimento alla possibilità che l'utilizzo di risorse da parte degli utenti sia controllato da Acua (descritto nel capitolo 144). Se il programma acua_login restituisce un valore diverso da zero, viene eseguito il logout e l'utente non può accedere.

Supponendo di aver collocato questo script nella directory /usr/bin/ e di averlo chiamato utente_ppp, si deve abbinare tale file agli utenti, in qualità di shell. Così, nel file /etc/passwd apparirà qualcosa come nell'esempio seguente.

tizio:x:1001:1001:Tizio Tizi:/home/tizio:/usr/bin/utente_ppp
caio:x:1002:1002:Caio Cai:/home/caio:/usr/bin/utente_ppp
semproni:x:1003:1003:Sempronio Semproni:/home/semproni:/usr/bin/utente_ppp

Naturalmente, per evitare conflitti con i controlli del sistema di autenticazione, è necessario aggiungere tale shell nell'elenco del file /etc/shells.

/bin/bash
/bin/sh
/bin/csh
/usr/bin/utente_ppp

È importante tenere presente che in questo modo, il programma pppd deve poter essere avviato dagli utenti normali; di conseguenza, è probabile che sia necessario attivare il bit SUID.

# chmod u+s /usr/sbin/pppd

124.5.1 Instradamento e routing

Il bello della connessione PPP è che il programma pppd provvede da solo a definire le interfacce di rete ppp* e a inserire gli instradamenti corretti. Quindi, se la configurazione di pppd è fatta correttamente, non occorre provvedere ad altro.

Il problema rimane semmai nella gestione dell'inoltro dei pacchetti verso le altre interfacce, specialmente verso quella che permette di raggiungere la rete esterna. In pratica, occorre che il kernel del sistema sia disponibile alla gestione del routing, e che il file virtuale /proc/sys/net/ipv4/ip_forward contenga il valore 1.

# echo 1 > /proc/sys/net/ipv4/ip_forward

124.5.2 Complicare le cose

Secondo quanto mostrato fino a questo punto, gli utenti che accedono al servizio PPP attraverso la linea commutata, non hanno alcun modo di utilizzare i comandi del sistema operativo. Questa è una cosa positiva: sarebbe difficile dormire sonni tranquilli trovandosi a gestire un centinaio di utenti che se vogliono possono allenarsi a fare i pirati nel proprio computer. Tuttavia, ci sono alcune cose che sarebbe bene tali utenti potessero fare; per esempio: cambiare la password e controllare l'utilizzo delle risorse che gli competono.

Lo script seguente ricalca quello già visto nella sezione precedente, con la differenza che è scritto in Perl, e verifica quale sia la linea di terminale da cui proviene la connessione. Se si tratta di un terminale /etc/ttyS*, viene attivato il PPP; se si tratta di /etc/ttyp* sembra una connessione attraverso Telnet, e in questo caso viene consentito di compiere alcune operazioni elementari.

#!/usr/bin/perl
#======================================================================
# utente_ppp
#
# Verifica che l'utente possa accedere, e prima di attivare il PPP
# controlla che il terminale da cui accede lo consenta,
# altrimenti lo estromette, oppure gli offre altre opzioni.
#=======================================================================

#-----------------------------------------------------------------------
# Definisce le variabili che verranno utilizzate.
#-----------------------------------------------------------------------
$terminale="";
$scelta="";

#-----------------------------------------------------------------------
# Impedisce la scrittura sul terminale dell'utente.
#-----------------------------------------------------------------------
system( "/usr/bin/mesg n" );
system( "/bin/stty -tostop" );

#-----------------------------------------------------------------------
# Verifica che l'utente possa accedere (zero corrisponde a falso in
# Perl, quindi il risultato va invertito).
#-----------------------------------------------------------------------
if ( ! system( "/usr/sbin/acua_login" ) ) {

    #-------------------------------------------------------------------
    # L'utente viene accolto.
    #-------------------------------------------------------------------
    print STDOUT "Benvenuto $ENV{LOGNAME}\n";

} else {

    #-------------------------------------------------------------------
    # L'utente viene estromesso e gli si dà modo di verificarne il
    # motivo.
    #-------------------------------------------------------------------
    system( "/usr/sbin/acua viewRec" );

    #-------------------------------------------------------------------
    # Gli vengono concessi 15 secondi per leggere lo stato
    # delle risorse del suo account, quindi la connessione viene
    # interrotta.
    #-------------------------------------------------------------------
    print STDOUT "Fra 15 secondi la connessione verrà conclusa.\n";
    sleep( 15 );
    exit;

}

#-----------------------------------------------------------------------
# Se ha superato i controlli precedenti, l'utente ha diritto di
# accedere. Si procede verificando quale linea di terminale è
# stata usata.
#-----------------------------------------------------------------------
$terminale=`/usr/bin/tty`;

if ( $terminale =~ m|^/dev/tty\d+$| ) {

    print STDOUT "L'accesso dalla console non è consentito agli ";
    print STDOUT "utenti del servizio dial-in PPP.\n";
    sleep( 3 );
    exit;

} elsif ( $terminale =~ m|^/dev/ttyp\d+$| ) {
    
    #-------------------------------------------------------------------
    # Accesso da un terminale Telnet.
    # Viene concesso all'utente di cambiare password e di controllare
    # la sua posizione con Acua.
    #-------------------------------------------------------------------
    print STDOUT "Premere la lettera corrispondente, seguita da "
    print STDOUT "Invio, per scegliere l'opzione desiderata.\n\n";
    
    print STDOUT "P) cambia la parola di accesso (password);\n\n";
    print STDOUT "R) visualizza l'utilizzo di risorse;\n\n";

    #-------------------------------------------------------------------
    # Legge una lettera dallo standard input.
    #-------------------------------------------------------------------
    $scelta = getc;
    
    if ( $scelta =~ m|p|i ) {
    
	system( "/usr/bin/passwd" );

    } elsif ( $scelta =~ m|r|i ) {
	    
	system( "/usr/sbin/acua viewRec" );
	
    } else {
    
	print STDOUT "E` stata selezionata un'opzione non prevista.\n";
	
    }

    exit;

} elsif ( $terminale =~ m|^/dev/ttyS\d+$| ) {

    #-------------------------------------------------------------------
    # Attiva la connessione PPP secondo la configurazione.
    #-------------------------------------------------------------------
    print STDOUT "Viene attivata la connessione PPP.\n";
    exec system( "/usr/sbin/pppd" );
    exit;

}

#-----------------------------------------------------------------------
# Nel caso si riuscisse a raggiungere questo punto, esce.
#-----------------------------------------------------------------------
exit;

#=======================================================================

Nello stesso modo in cui viene avviato passwd, o acua, si potrebbe avviare una shell vera e propria, ma questo è meglio evitarlo se non si conoscono perfettamente le conseguenze.

---------------------------

AppuntiLinux 1998.11.22 --- Copyright © 1997-1998 Daniele Giacomini - daniele@calion.com


[indice generale] [precedente] [successivo] [indice analitico] [note introduttive]