Almost Internet with SLiRP and PPP
It's the '90s. More and more people around the world have heard of “getting connected to the Internet.” Some of those have actually made the technological, intellectual, and cultural leap into “Cyberspace”. And some of those are using Linux to get connected. I'm part of all three groups. In fact, I've become rather dependent on my Internet connection—it's like having a telephone, only more expensive.
To be connected to the Internet, you used to have only two choices: either a direct (and expensive) Internet connection, like those used by corporations and institutions, or a modem connection into somebody else's machine which had a direct Internet connection, using your computer as if it were a “dumb terminal”. You can still do that today, if you feel like it, but with the increasingly common availability of “real” net connections like SLIP (Serial Line Internet Protocol) and PPP (Point-to-Point Protocol), fewer Internet users really want to feel as if all they have on their desk is a dumb terminal. Yet, for a number of reasons, the only Internet access available to some of us is a dial-up dumb-terminal-ish Internet account, or “shell” account.
Enter SLiRP. SLiRP is a freely available software package, written by Danny Gasparovski (email@example.com), which makes an ordinary shell account act like a SLIP or PPP account. There are other so-called “SLIP emulators” available (one of the more notable of which is The Internet Adaptor—see References sidebar, as well as “terminal multiplexers” such as term, which uses a non-standard protocol between the shell account and the local computer. SLiRP has advantages over both groups, many of which, along with some disadvantages, the author details in the README file accompanying the SLiRP package.
SLiRP does not run on your “local” computer (the one that would otherwise be a dumb terminal), but rather on the “remote” computer (the one that's actually connected to the Internet). In order to install SLiRP properly, you need the following:
A Unix shell account on the remote host
A C compiler available on the remote host
An editor that you know how to use on the remote host
If you're not sure whether you have a compiler or editor available, please contact your system administrator, or someone else who is familiar with your remote site.
The steps involved in installing SLiRP are as follows:
The most recent version of SLiRP available at the time of this writing is slirp-0.95h.tar.gz. See References sidebar to find SLiRP. Once you have the package, “untar” it somewhere useful (such as /usr/local/src)--perhaps with the command tar zxvf slirp-0.95h.tar.gz.
Documentation of many sorts is included in the SLiRP package in slirp-0.95h/docs. Instructions for compiling SLiRP are in slirp-0.95h/docs/README.compiling, the gist of which is: change to the slirp-0.95h/src directory and run the configure program located there (usually by typing ./configure); then build the program by typing make. If you have problems, consult the file slirp-0.95h/docs/README.getting-help.
When you have successfully compiled SLiRP, you will need to put the SLiRP binary somewhere where you can run it. If you don't already have a directory for your own programs, I suggest creating a directory called ~/bin, and then adding it to your PATH in your login scripts. If you're not sure how to do this on your system, check with your system administrator. Then, from the slirp-0.95h/src directory, perform the following commands:
strip slirp cp slirp ~/bin chmod 0700 ~/bin/slirp
(Alternatively, if your site has GNU `install' available, you may perform the above actions in one step with install -s -m 0700 slirp ~/bin.)
This is the tricky bit, partly because SLiRP is an evolving product, and its documentation is not necessarily entirely complete and up-to-date; however, I suggest reading slirp-0.95h/docs/CONFIG and slirp-0.95h/docs/README.ppp before doing anything else. Next, using your favorite text editor, create SLiRP's configuration file, called ~/.slirprc. At the very minimum, you will want to include a baudrate setting. If you're planning on using SLiRP to emulate PPP, you should also include a ppp flag, an asyncmap setting and mtu and mru values. Your .slirprc file might look something like mine:
baudrate 115200 ppp asyncmap 0 mtu 552 mru 552 log start
You will most likely want to adjust the “baudrate” to suit your modem—some experimentation may be necessary. [“baudrate” should really be bits per second, or bpsrate. Even geeks who happen to know that their 14400 bps modems run at 2400 baud shouldn't set the baudrate parameter to 2400.. —ED]
Once you have SLiRP installed and configured, you can start it by simply typing slirp; SLiRP will then attempt to initiate a connection.
SLiRP is only half of your net connection; you also need to activate the other half of the connection on your local Linux machine. Linux, like SLiRP, “speaks” both SLIP and PPP—that is, support for TCP/IP networking over both SLIP connections and PPP connections is built into the Linux kernel. However, although both are available under Linux, I highly recommend using PPP instead of SLIP, for the following reasons:
PPP is an Internet Standard Protocol—this means that it has undergone a standardization process approved by the Internet Architecture Board (IAB) and is an official part of the Internet Protocol Suite. SLIP, by contrast, is an “Internet non-standard” and is not on the standard track.
PPP will work over some connections that are not 8-bit-transparent; SLIP will not.
PPP can support authentication, peer address negotiation, packet header compression, and point-to-point error correction; SLIP can support none of these (although Compressed SLIP, or CSLIP, does support packet header compression).
In short, it is my opinion that PPP is capable of providing a more robust and reliable connection than SLIP without significantly reducing the apparent speed of the connection.
PPP support under Linux comes in two halves. One half is part of the network system drivers, and comes built into the Linux kernel. The other half is a daemon process called pppd, which comes as a separate package.
Most distributions today come with PPP support built in, but if your Linux system is built from an older distribution, you may need to install PPP support. In order to properly install PPP networking under Linux, you need gcc installed, and either:
A Linux kernel version 1.1.13 or greater with PPP support compiled in, or
A Linux kernel version 1.0 or greater, plus either some experience compiling a Linux kernel or someone to help you do it.
If you don't know whether your kernel has PPP support compiled in, look for a message similar to the following when you boot up your machine:
PPP: version 0.2.7 (4 channels) [...]
You can also use the command dmesg | grep PPP to search the kernel boot messages for the above line. If no PPP messages exist, you will need to recompile your kernel to add PPP support (unless you are using the PPP kernel module; some distributions come with a PPP module ready to use). If you don't know what version your kernel is, use the uname -a command to display information about your system. If your kernel version is less than 1.1.13, you may need to recompile your kernel with a new PPP driver in order to use PPP. If you need to recompile your kernel, and especially if you need to install a newer PPP driver, see the documentation accompanying the pppd package and the Linux Documentation Project's PPP-HOWTO and Kernel-HOWTO for more information.
The steps involved in setting up PPP are as follows:
The latest version of pppd at the writing of this article is ppp-2.1.2d.tar.gz. You may already have pppd; many Linux distributions include it. You can check for it with the following command: find / -name "pppd*" -print. If your distribution already has pppd installed, you can proceed to the configuration step. If you're going to be compiling pppd, untar the source package somewhere useful (such as the place you untarred SLiRP).
The pppd package comes with thorough instructions, including some specifically for Linux users, located in pppd-2.1.2d/README and pppd-2.1.2d/README.linux. I recommend you read both those documents and any documentation located in pppd-2.1.2d/linux before compiling and installing pppd. Then, change to the pppd-2.1.2d/pppd directory and create a Makefile using cp Makefile.linux Makefile (I recommend copying instead of linking so that you can make changes to the makefile if necessary without affecting the original). Inspect the makefile to make sure BINDIR and MANDIR are set to the correct location to install the pppd binary and manual page respectively (to comply with the Linux Filesystem Standard, they should probably be set to /usr/sbin and /usr/man). Make any required changes to the makefile using your favorite text editor. Build pppd by running make. To install pppd, first become the superuser (either by logging in as root or using the su command) and type make install; this installs both the pppd binary and the manual page. If you are replacing an older version of pppd, you may wish to make a backup copy of the older pppd until you are sure the new one works correctly. [If you are using the latest development kernel, you will need the latest version of pppd as well; it will be the latest in the 2.2.0 series, kept in the same places as the older 2.1.2 series pppd sources—ED]
The pppd package comes with a utility program called chat which performs “expect-send” scripts for dialing modems, performing automated logins, etc. chat is located in pppd-2.1.2d/chat/. The steps for compiling and installing chat are essentially the same as for pppd: copy the makefile, edit to suit your system, make, and then make install as the superuser. The chat manual page, however, needs to be installed by hand; use
install -m 0444 -o root -g man chat.8 /usr/man/man8/
to do this.
Now is a good time to read the manual page for pppd. While it is rather long, the manual page contains some information critical to understanding how to set up pppd, including explanations of several scripts called by pppd. There are several steps involved in properly configuring pppd, and a few more in making it convenient to use:
Creating the system-wide pppd configuration file /etc/ppp/options.
Modifying the network configuration files to work with a PPP connection.
Creating the scripts /etc/ppp/ip-up and /etc/ppp/ip-down to perform any needed actions when the PPP link becomes active and before it is closed, respectively.
Configuring the system logging facility so that messages from pppd are written to the system logs.
Creating scripts to start and stop pppd gracefully.
The system-wide configuration file, /etc/ppp/options, is the most important thing to get right for pppd to work. The file must exist and be readable by the root user, even if you don't plan to store configuration information in it—otherwise, pppd won't start. Unfortunately, there are so many possible options to configure for pppd that it's difficult to build a configuration file from scratch. I have put together an options file template for pppd, which includes each configurable option and explanatory text taken directly from the pppd manual page, and made it freely available for anonymous FTP (see References for locations). I recommend fetching the pppopt.tgz package to use as a starting point for configuration.
A configuration file for pppd looks like this:
## /etc/ppp/options -- config file for pppd # async character map -- 32-bit hex; each bit # is a character that needs to be escaped for # pppd to receive it. 0x00000001 represents # "<\>x00", and 0x80000000 represents "<\>x1f". asyncmap 0 # Use hardware flow control (i.e. RTS/CTS) to # control the flow of data on the serial port. crtscts # Add a default route to the system routing # tables, using the peer as the gateway, when # IPCP negotiation is successfully completed. # This entry is removed when the PPP connection # is broken. defaultroute # Set the MRU [Maximum Receive Unit] value to <n> # for negotiation. pppd will ask the peer to send # packets of no more than <n> bytes. The minimum # MRU value is 128. The default MRU value is 1500. # A value of 296 is recommended for slow links # (40 bytes for TCP/IP header + 256 bytes of data) mru 552 # Disables the default behaviour when no local IP # address is specified, which is to determine (if # possible) the local IP address from the # hostname. With this option, the peer will have # to supply the local IP address during IPCP # negotiation (unless it is specified explicitly on # the command line or in an options file). noipdefault
This file assumes that the modem is set to use hardware flow control (crtscts), that the link between the local machine and the remote one is 8-bit-clean (asyncmap 0), and that the remote machine will tell pppd what the local machine's IP address is (noipdefault). It also tells pppd to add a “default route” to the system routing tables (defaultroute), which is generally what we want for a dial-up Internet connection, and sets the “maximum receive unit”, the largest PPP packet that pppd will accept, to 552 (mru 552).
If you want to use software flow control instead of hardware flow control for your modem, you can use xonxoff instead of crtscts. You also need to add the XON and XOFF characters to the asyncmap option, as follows: the number following asyncmap is a 32-bit hexadecimal number, where each bit represents a character between 0x00 (^@) and 0x1f (^_) which must be “escaped”, or sent as a two-byte sequence to avoid getting swallowed or munged in transmission; asyncmap 000a0000 escapes characters 0x13 (^S) and 0x11 (^Q), the XON/XOFF characters. You will also need to add this asyncmap setting to your SLiRP configuration file on the remote host.
The network configuration files on your Linux system which you need to modify or check are:
/etc/rc.d/rc.inet1 or /etc/rc.net, the network configuration script (it may be called something slightly different, depending on your distribution)
/etc/hosts, the hostname-to-address configuration file
/etc/resolv.conf, the resolver configuration file
Configuration of these files is discussed in detail in the README.linux file that comes with pppd under the heading “General Network Configuration”; however, a few items are important for using pppd with SLiRP:
In /etc/hosts, use the address `10.0.2.15' as the address for your Linux machine; this is the address SLiRP uses by default. For example, my own machine is called “zephyr”, in the fictitious domain “earth”, and the following line appears in my host table after the loopback entry:
10.0.2.15 zephyr.earth zephyr
In order to fill in the nameserver part of /etc/resolv.conf, you need to know the address of the nameserver for the remote host. There are three ways to find out this information, in order from least to most effort:
(1) Use the command nslookup, which will print the name and numeric address of the default nameserver (use exit to exit nslookup);
(2) Read the remote resolver configuration file using the command cat /etc/resolv.conf--it should have nameserver entries just like the ones you need; or
(3) Ask the system administrator, who may or may not be willing to give you that information.
You may wish to perform certain actions when the PPP link opens and to perform others when the PPP link closes down; you can put such actions in scripts called /etc/ppp/ip-up and /etc/ppp/ip-down. For instance, I have configured smail (my mail delivery agent) to send outgoing mail to my Internet account provider, which is only available when my PPP link is up. In my ip-up script, I have a command to send any queued outgoing mail along to the smart-host for delivery.
#!/bin/sh # # /etc/ppp/ip-up -- do net-stuff when ppp is up # send queued outgoing mail over new net connection /usr/sbin/runq
The ip-up and ip-down programs do not have to be shell scripts—they could just as easily be written in Perl, Tcl, or any other scripting language. However, the scripts should be executable, i.e. they should have execute permission set (using
Do not break up the following line:
chmod 0755 /etc/ppp/ip-up /etc/ppp/ip-down
and the first line of the script should be of the format #!path-to-program, containing the complete path to the program that should run the script (e.g., #!/bin/sh for a Bourne shell script, or #!/usr/local/bin/perl for Perl).
pppd sends messages and some debugging information to the system logging facility syslogd. You may wish to configure syslogd so that those messages get logged to a separate log file; to do this you need to become the superuser and modify the syslogd configuration file /etc/syslog.conf. pppd logs to the “daemon” facility, so we add the following line to syslog.conf:
# Log daemon-related messages in a special place daemon.* /var/log/daemon.log
You should put the daemon log in the same place as your other system logs; the Linux Filesystem Standard recommends /var/log. In order to get syslogd to re-read its configuration file, send it a hangup signal using the command kill -HUP pid, where pid is the numeric process id for syslogd as shown in a listing made by a ps ax command. Alternately, use killall -HUP syslogd.
Since it can be a bit tedious trying to start and stop pppd from the command line, I recommend creating two executable scripts called ppp-on and ppp-off. The pppd package comes with sample scripts in pppd-2.1.2d/chat, which you may wish to use as a guide. Simple versions of each are shown in Figure 1 and Figure 2. You should probably install the scripts in the same place as you install pppd (for my system, /usr/local/ppp/bin).
Figure 1. Example ppp-on Script
Figure 2. Example ppp-off Script
With SLiRP installed on your remote host and pppd installed on your Linux machine, it's time to try to get them to work together. It's a good idea to dial into your Internet service provider (the remote machine) using your favorite communications package (such as kermit, minicom, or Seyon) for the first few times in order to test the login and connection process. There are several steps to take:
Display the system routing table using the command netstat -rn on your local machine. If netstat is not available, try using the command /sbin/route. If neither of those commands is available, you may need to install a networking package from your Linux distribution—stop here and check your distribution documentation or consult your local Linux guru. Your routing table should look similar to Figure 3.
Figure 3. Initial Routing Table
Start your favorite communications package.
Set your modem not to hang up when DTR is dropped (consult your modem documentation for how to do this—for Hayes-compatible modems, the command is usually at&d0).
If your communications package has a session logging feature (e.g., kermit's log session command), turn on session logging.
Dial the remote machine and log in as you normally do. If your communications package doesn't have a session logging feature, you should record the login procedure by hand, writing down both what prompts appear and what you type in response.
Start SLiRP from your shell prompt, using the command slirp.
Stop session logging if you started it above, and either suspend your communications program or disconnect it from the modem (I recommend the second; in kermit you can say set line at the command prompt to disconnect without hanging up or exiting kermit).
Start pppd using the command ppp-on.
Wait a few seconds for the connection to come up, and then display the network routing table again. Your routing table should now have entries for the remote host similar to Figure 4, where xxx.xxx.xxx.xxx is the IP address of the remote host.
Figure 4. Final Routing Table
If your routing table appears to be correct, try connecting to the remote machine with the command telnet xxx.xxx.xxx.xxx, using the IP address shown in the routing table, and log in as you normally would. If that works, try [telnet hostname of the remote machine or telnet to another host that you know of. You're connected! When you're done, use ppp-off to stop pppd, and resume your communications program. To stop SLiRP, wait a moment and type 0 (zero) five times. SLiRP actually requires a short pause in between each 0 to recognize it as a shutdown string, but normal typing speed works fine. Log out, and hang up your modem.
If those routing table entries do not appear, first check that your pppd configuration file /etc/ppp/options contains a defaultroute entry. Next, check that there is no entry for passive or silent in your pppd configuration file—by default, SLiRP silently waits for the other end of the PPP connection (in this case, pppd) to send configuration packets. If the entries are not there, check that pppd is still active, using the command ps ax | grep pppd--if it's not in passive or silent mode, pppd will time out if it receives no answer after sending a certain number (10 by default) of configuration requests.
If pppd times out, check the system logs for entries from pppd. If you didn't configure syslogd to catch messages from pppd as described above, now would be a good time to do that. Note that you can increase the level of system log messages from pppd by putting a debug entry in pppd's configuration file. SLiRP will also perform several levels of logging: slirp -d ~/slirp.log will log debugging output to the file ~/slirp.log on the remote host; adding the entry log start to the SLiRP configuration file ~/.slirprc will log startup information to ~/.slirp_start; and adding the entry debug to the PPP section of the SLiRP configuration file will log PPP debugging output to the file ~/ppplog.
Once you have pppd and SLiRP talking to each other, you can create a more sophisticated ppp-on script to automatically dial the remote host, log you in, start slirp, and then start pppd on your Linux machine. I have created such a script which uses the “chat” utility that came with the pppd package; it is shown in Figure 5.
This shell script is designed to look in a certain directory (such as ~/.ppp or /usr/local/ppp/script) for “chat scripts” to use in dialing and logging in. When started with an argument, e.g., ppp-on my-isp-name, this version of ppp-on will use a chat script called ~/.ppp/my-isp-name.chat for dialing and logging in. Such a feature allows a single user to have multiple dialing scripts for multiple Internet Service Providers, and allows multiple users to keep their passwords private.
When started with the -c option, this ppp-on script can also execute a custom script after starting the PPP connection. For example, ppp-on -c would perform a script called ~/.ppp/default.ppp after starting pppd, and ppp-on -c my-isp-name would dial and automatically log me in using the chat script as described above, then perform ~/.ppp/my-isp-name.ppp after starting pppd. This can be a useful substitute for the /etc/ppp/ip-up script in a multi-user environment. Additionally, this ppp-on script allows a verbose option -v to log the execution of the chat script to the system logs for debugging.
A chat script consists of a sequence of “expect-send” strings separated by whitespace. chat expects to receive on its standard input the first non-keyword string in the script; when it does, it sends the next non-keyword string followed by a carriage return to the standard output, and so on. To make a customized chat script, you can use the session log you made above while logging into your remote host. A sample session log and the resulting chat script are shown here; you may wish to consult chat's manual page as well.
First, the sample session log:
at OK atz OK at&b0s0=0 OK atdtMY-PHONE-NUMBER CARRIER 28800 PROTOCOL: LAP-M CONNECT 115200 Welcome to My Internet Service Provider suchandsuch login: MY-LOGIN-ID Password: --SYSTEM NEWS-- blah blah blah blah blah blah blah blah blah blah. TERM = unknown TERM = (vt100) vt102 MY-SHELL-PROMPT% slirp
And this is the chat script that matches the session log:
ABORT BUSY ABORT "NO CARRIER" ABORT "NO DIALTONE" TIMEOUT 2 OK-at-OK atz TIMEOUT 5 OK at&b0s0=0 OK atdtMY-PHONE-NUMBER TIMEOUT 60 CONNECT "" TIMEOUT 10 ogin:--ogin: MY-LOGIN-ID ssword: \qMY-PASSWORD (vt100) vt102 MY-SHELL-PROMPT% slirp
The script uses several features of chat which make it easier to perform automated logins:
The ABORT keyword, which aborts the script at any time if any of the strings listed is received.
The TIMEOUT keyword, which adjusts the chat timeout in seconds, so you don't have to wait for 45 seconds to find out that your modem is not responding.
The “empty” send string surrounded by quotes, "", (chat accepts single or double quotes), which simply sends a carriage return.
The “sub-expect” sequences using hyphens (if the first string is not received, chat sends the string following the first hyphen, followed by a carriage return, and then expects the string following the second hyphen; if the first string is received, the rest of the hyphenated sequence is skipped)
The \q (“quiet”) escape sequence, which keeps the string from being logged, making sure that your remote password does not appear in the system logs.
If we can make it easier to log into a remote host using SLiRP, pppd, and chat, we ought to be able to make it easier to log out as well. The ppp-off script (see Figure 2) does some of this, but not quite enough. pppd does have a disconnect option, but since you may wish to use pppd to connect to multiple Internet service providers, one or more of which may not use SLiRP, there's a more flexible solution: instead of trying to use pppd to hang up the phone (which is not its job), we'll use chat to exit SLiRP and hang up the phone after pppd has disconnected the PPP link.
Figure 6. The remote-slirp-off script
Figure 6 contains a shell script called remote-slirp-off, which does just that. This shell script shows chat scripts included as arguments to chat instead of read from a script file. Note the use of double-backslashes for chat escape sequences—if they weren't doubled, the shell would remove them, and the characters which follow would simply appear to be part of the send string. The \d escape delays for one second, while the \p escape delays for a tenth of a second. \c indicates not to send a carriage return after the send string in which it appears. The script also provides a verbose option -v to log the chats to the system logs for debugging. Like chat, remote-slirp-off expects the modem to be on both standard input and standard output.
Armed with the “glue” of the foregoing scripts, including your custom-made chat script for dialing into your Internet account, you can start a PPP connection between pppd and SLiRP using the simple command:
and you can stop the connection using the simple command sequence:
ppp-off remote-slirp-ff </dev/modem >/dev/modem
If you simply must have simple, one-word commands to perform these actions, you can easily put them into an alias, shell function, or yet another shell script.
In addition to the features and capabilities I have discussed here, SLiRP has more sophisticated facilities for load-balancing and restarting interrupted connections, as well as utility programs for starting a remote shell without having to log in via telnet or for sending a file over a SLiRP connection without having to use FTP; however, none of these are necessary for a working Internet connection. Check out the documentation accompanying SLiRP and the SLiRP WWW pages for more information about those extras.
Be careful not to get too addicted to a SLiRP connection. Remember: it's like having a telephone, only more expensive.
Jim Knoble (firstname.lastname@example.org) has been friends with computers since the days of homebuilt Heathkit Z80 machines running CP/M and has been learning about Linux since late 1992. When Jim's not at work, he enjoys international folk dancing, singing in his church choir, brushing up on his German, cycling, baking bread, hiking, and writing poetry. He lives in Chapel Hill, North Carolina, home to many fine Linux products and personalities. Jim hopes that one day the world will experience lasting peace.