Hinter PPP ('Point to Point Protocol') verbirgt sich ein Mechanismus, der es ermoeglicht IP-Verbindungen (Internet Protocol) zwischen 2 Rechnern ueber eine Modem-Verbindung herzustellen.
Der Betriebssystemkernel von Linux enthaelt einen Treiber fuer das PPP-Protokoll, der jedoch meistens erst aktiviert werden muss; die eigentlichen PPP-Verbindungen werden unter Linux ueber einen eigenen Daemon, den 'pppd' realisiert.
Die Voraussetzungen fuer die PPP-Unterstuetzung unter Linux sowie der prinzipielle Aufbau einer PPP-Verbindung zwischen 2 Rechnern werden unter anderem in [1], dem LinuX Anwenderhandbuch [2], dem Linux Wegweiser fuer Netzwerker [3] und im Linux PPP HOWTO-Dokument [4] erlaeutert.
PPP ermoeglicht theoretisch nicht nur eine Verbindung zwischen Unix-Hosts sondern auch eine Anbindung eines Linux-Rechners an einen Windows NT Server ueber den sogenannten 'Remote Access Service' (RAS).
Um eine solche Verbindung herzustellen, sind einige grundlegende Voraussetzungen zu beachten:
Kommt eine solche PPP-Verbindung zustande, sollen ueber sie folgende Aktivitaeten abgewickelt werden koennen:
Es stellt sich also nun die Frage, ob und auf welche Art und Weise eine solche Verbindung zwischen Linux und Windows NT hergestellt werden kann.
Der 'einfachste' Fall (PPP-Zugriff mit beliebigem Authentifizierungsschema) scheint auf den ersten Blick ohne groesseren Aufwand realisierbar, da Linux im System die benoetigten Module schon bereithaelt.
Zuerst muss der Windows NT-Systemverwalter ueberzeugt werden, im Windows NT-Remote Access Service unter 'Network Configuration' bei den 'Server settings' TCP/IP zu konfigurieren und bei den 'Encryption settings' den Punkt 'Allow any authentication including clear text' zu aktivieren.
Nachdem diese Huerde genommen ist, muss man sich im Klaren sein, dass Windows NT-RAS beim Einloggen des Clients (Linux-Host) nicht in gewohnter Weise den "Login:/Password:"-Algorithmus, sondern zur Authentifizierung PAP/CHAP benutzt. Ein Blick in die Man-Pages des 'pppd' ueberzeugt davon, dass von diesem PAP/CHAP unterstuetzt wird.
Leider unterstuetzt die hier verwendete 'pppd'-Version standardmaessig das MS-CHAP-Protokoll nicht. Ein dem Paket beiliegender Patch (README.mschap80), der eine "client-only" Implementation von MS-CHAP ermoeglicht, soll dieses Manko ausgleichen.
MS-CHAP benutzt eine Kombination aus "MD4 hashing" und DES-Verschluesselung. Um die MS-CHAP-Erweiterung mit 'pppd' nutzen zu koennen, wird eine spezielle DES-Bibliothek benoetigt: Eric Youngs's DES-Library; zu finden unter ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/libdes-3.06.tar.gz.
Nach Erzeugung und Installation dieser Library kann nun nach Einspielung der erwaehnten Patches der 'pppd'-Daemon neu uebersetzt werden. Hierbei sind neben den Anweisungen in der Datei README.mschap80 unter "BUILDING THE PPPD" (undedingt Option -DUSE_MSCHAP verwenden) auch das Kapitel INSTALLATION in der Datei README.linux zu beachten: Die aufgefuehrten Punkte 2 bis 4 (Kernelcompilierung) werden nicht durchgefuehrt, da der aktuelle 'ppp'-Treiber des 'pppd' schon als ladbares Kernelmodul vorhanden ist (Kernel 2.0.25).
Das selbe Bild ergibt sich jedoch auch bei der Ausnutzung des Callback-Features von Windows NT: 'pppd' liefert keinen Hinweis auf Unterstuetzung dieser Option.
Gluecklicherweise finden sich in den Quellen des 'pppd'-Paketes ein paar entsprechende Patches, um beim Aufbau der PPP-Verbindung dem Windows NT Server eine entsprechende Telefonnummer mitzuteilen, unter der dann der Rueckruf erfolgt.
Um dieses Callback-Feature zu nutzen, muss nun der dem Paket beiliegende Patch README.cbcp eingespielt werden. Leider bezieht sich dieser Patch nicht auf die der verwendeten Linux Distribution beiliegenden 'pppd'-Version (ppp-2.2.0f), so dass ein automatisches Einspielen nur bedingt moeglich ist; der verbleibende Rest ist per Hand nachzufuehren.
Dieser Patch unterstuetzt jedoch nur das "User-Defined" Callback-Verfahren. Um zusaetzlich das "Admin-Defined" Callback-Verfahren nutzen zu koennen sind noch ein paar kleine Erweiterungen in den Dateien pppd/options.c und pppd/cbcp.c durchzufuehren:
diff -r --unified=10 options.c.noadmin options.c
--- options.c.noadmin Sat Mar 15 16:47:07 1997
+++ options.c Sat Mar 15 16:38:40 1997
@@ -1004,20 +1004,21 @@
static int
setcbcp(argv)
char **argv;
{
lcp_wantoptions[0].neg_cbcp = 1;
cbcp[0].us_number = (char *) malloc(strlen(*argv) + 1);
strcpy(cbcp[0].us_number, *argv);
cbcp[0].us_type |= (1 << CB_CONF_USER);
+ cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
return (1);
}
/*
* nopcomp - Disable Protocol field compression negotiation.
*/
static int
nopcomp()
{
lcp_wantoptions[0].neg_pcompression = 0;
diff -r --unified=10 cbcp.c.noadmin cbcp.c
--- cbcp.c.noadmin Sat Mar 15 16:50:14 1997
+++ cbcp.c Sat Mar 15 16:34:47 1997
@@ -286,28 +286,30 @@
PUTCHAR(CB_CONF_USER, bufp);
len = 3 + 1 + strlen(us->us_number) + 1;
PUTCHAR(len , bufp);
PUTCHAR(5, bufp); /* delay */
PUTCHAR(1, bufp);
BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
- if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
- PUTCHAR(CB_CONF_ADMIN, bufp);
- len = 3;
- PUTCHAR(len , bufp);
- PUTCHAR(0, bufp);
- cbcp_send(us, CBCP_RESP, buf, len);
- return;
- }
+ if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
+ syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN");
+ PUTCHAR(CB_CONF_ADMIN, bufp);
+ len = 3 + 1;
+ PUTCHAR(len , bufp);
+ PUTCHAR(5, bufp); /* delay */
+ PUTCHAR(0, bufp);
+ cbcp_send(us, CBCP_RESP, buf, len);
+ return;
+ }
if (cb_type & ( 1 << CB_CONF_NO ) ) {
syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
PUTCHAR(CB_CONF_NO, bufp);
len = 3;
PUTCHAR(len , bufp);
PUTCHAR(0, bufp);
cbcp_send(us, CBCP_RESP, buf, len);
ipcp_open(us->us_unit);
return;
Nur mit dem Einspielen der Patches ist es jedoch nicht getan: Es muss bedacht werden, dass ein ankommender Rueckruf vom System erkannt, untersucht, ausgewertet und bei erkannter PPP-Anforderung der 'pppd'-Prozess aktiviert wird.
Die Ueberwachung eines Kommunikationsports auf Anforderungen fuer einen Verbindungsaufbau (von einem Terminal oder einem Modem) wird in der Regel von sogenannten 'getty'-Prozessen durchgefuehrt, wobei fuer jeden Kommunikationsport, ueber den ein Login zulaessig ist, ein eigener separater 'getty'-Prozess benoetigt wird.
Bei 'getty' handelt es sich um ein Programm das von der Init-Routine (init (1)) des Systemes aufgerufen wird. Es ist der zweite Prozess in der Serie "init-getty-login-shell", mit der ein Benutzer letztlich an ein Unix-System angeschlossen wird: 'getty' gibt zunaechst eine Login-Meldung aus, liest den Login-Namen des Benutzers und ruft dann das Kommando login(1) auf, dem der Benutzername als Parameter uebergeben wird. 'login' fordert dann ebenfalls die Eingabe eines Passwortes. Beim Lesen des Namens versucht 'getty', das System an die Geschwindigkeit und den Typ des eingesetzten Kommunikationspartners anzupassen.
Da jedoch wie erwaehnt Windows NT nicht den "Login:/Password:"-Algorithmus benutzt, kann dieses Verfahren nicht verwendet werden. Es ist dazu ein intelligentes 'getty'-Programm notwendig, das die Modem-Kommunikation beherrscht, einen Anruf erkennt, der das PPP-Protokoll benutzt und das faehig ist, den 'pppd'-Prozess automatisch zu aktivieren.
Hierzu findet sich in den Linux-Quellen ein Paket namens 'mgetty+sendfax distribution' (kurz 'mgetty'), das diese Anforderungen erfuellt. Unter http://www.leo.org/~doering/mgetty/index.html liegt die aktuelle (Beta-)Version (mgetty-0.99.3).
Bei der Neukompilierung ist zu beachten, den PPP-Modus explizit zu aktivieren (im Makefile den CFLAGS die Option -DAUTO_PPP mitgeben), den Pfad des verwendeten 'mgetty'-Konfigurationsverzeichnisses (Definition 'prefix=/etc' im Makefile) zu definieren und den Namen des Lock-Files mit dem des 'pppd' abzustimmen ( Parameter LOCK in policy.h bzw. Parameter LOCK_PREFIX in sys-linux.c im 'pppd'-Paket).
Ueber dieses Lock-File synchronisieren die beiden um die serielle Schnittstelle konkurrierenden Prozesse 'mgetty' und 'pppd' den exklusiven Zugriff auf dieses Device; aus diesem Grund sollte fuer den bei diesen Programmen definierten Devicenamen immer der physikalische Geraetename angegeben werden (z. B.: ttyS0 fuer COM1). Das Lock-File liegt im Verzeichnis /var/lock und traegt den Namen LCK.. <device> (d. h. fuer ttyS0 LCK..ttyS0).
Damit 'mgetty' einen ankommenden Rueckruf korrekt uebernehmen kann, ist beim angeschlossenem Modem unbedingt der 'AUTOANSWER'-Modus zu deaktivieren (d.h ueber den Modembefehl 'ATS0&W' permanent abzuschalten): 'mgetty' verwendet nicht diesen Modus (Modembefehl z.B. 'ATS0=2'), sondern bantwortet einen Anruf manuell ueber die Modemsteuerung per 'RING --> ATA --> CONNECT'-Erkennung.
Bevor nun detailliert auf die erforderlichen Konfigurationmassnahmen unter Linux eingegangen wird, erst einmal eine kurze Beschreibung der vorhandenen Linux-System- und Umgebungskonfiguration:
Systembeschreibung:
Bei Verwendung eines 'schnellen' Modems (d.h. Datenuebertragungsrate > 14.400 bps) sollte unter Einsatz eines geeigneten Schnittstellentreibers (z. B. UART16550A) die Geschwindigkeit des Datentransfers zwischen Modem und der seriellen Schnittstelle entsprechend angepasst werden:
Die Geschwindigkeitseinstellung der seriellen Schnittstelle wird auf 115200 Baud (fuer Modemverbindungen 28.8k/komprimiert) heraufgesetzt:
setserial /dev/ttyS0 spd_vhi
Diese Einstellung kann natuerlich auch permanent beim Systemstart vorgenommen werden (in der Datei /sbin/init.d/serial).