Find out what's happening when using IP Masquerade and diald to access the Internet remotely.
Imagine making a telephone call on a system with no dial tone, no ringing signal and no busy signal. You'd just dial your number and wait until someone either answered or did not. It might be a frustrating experience after a while. This is similar to the experience of someone on a LAN using diald on a remote computer without any way to monitor the status of the remote link, and the problem I set out to solve about a month ago.
My home LAN includes my main Linux box and a number of other computers running some combination of Linux and Windows 95. With the main Linux box configured to use diald and IP masquerade, my wife can use her Win95 computer to check her e-mail, surf the Web, and do other Internet tasks without having to do anything with the modem, dial strings or the Linux box. She simply starts Netscape, goes to a site out on the Web, and waits. The Linux box dials the ISP, authenticates automatically and establishes the connection in about thirty seconds—unless the modem gets a busy signal. Unfortunately, there wasn't any feedback mechanism to tell the Win95 box about the state of the connection. This article describes my solution to that problem.
A single Linux box, equipped with a modem and configured to use IP masquerade and diald (which is short for “dial on demand”), allows every computer on the LAN to “think” it's directly attached to the Internet. An Internet request originating on a node of the LAN gets sent to the Linux box. If diald determines that the serial link to the Internet service provider (ISP) is not currently active, it initiates the dial sequence (hence “dial on demand”). When the connection is made, the Linux box authenticates with the ISP's computer, and the link to the Internet is established. IP masquerade allows that single connection to be used by every computer on the LAN by examining each packet destined for (or coming from) the outside world and substituting addresses where appropriate. The ISP side of the connection sees traffic only to (or from) the single IP address with which it authenticated—addresses in reply packets are then substituted back into place before the IP Masquerade box places the packets on the LAN side. While very complex, this all works remarkably well when properly configured.
When my wife checks her e-mail, however, she has no way of knowing the current state of the link. Her computer attempts to fetch the mail, sending a request to the Linux box running diald. The Linux box initiates the dial and authentication with the ISP, but this takes about 30 seconds, and the Windows 95 machine isn't that patient. When I use her machine, I just use TELNET to get to the Linux box and observe diald's progress by doing something like tail -f /var/log/messages, but this requires access to the system logs and some knowledge of how to interpret them.
The primary goal of the system was to provide an easier way to monitor the status of the remote link. Since I already had an HTTP server, Apache, installed and running on my Linux box and all of the computers in the house have some kind of web browser, it seemed an HTTP-based solution would be simplest. It has the advantage of requiring changes only to the Linux machine, making deployment quite simple. Conceptually, what's needed is:
a way to monitor the state of diald on the Linux box
a means by which a cgi-script can get that information and pass it to the client
some means of automatically updating the information on the client side
Starting from the bottom and working up, you'll need to get chat working first. I use a chat script, /etc/ppp/chat.mindspring (see Listing 1) to dial in to my ISP, Mindspring. I found both the ISP HOWTO (metalab.unc.edu/mdw/HOWTO/ISP-Hookup-HOWTO.html) and the diald mini-howto (metalab.unc.edu/linux/HOWTO/mini/Diald.html) very helpful in getting chat and diald working well. The IP Masquerade mini-howto (metalab.unc.edu/linux/HOWTO/mini/IP-Masquerade.html) was instrumental in helping me configure IP Masquerade. By reading carefully, planning meticulously and working methodically, you should be able to get your system working without too much difficulty within a couple of hours.
This chat script uses the SAY option, which allows the printing of strings from within chat to STDOUT. However, STDOUT must be redirected to a file to be useful in this application. This is done by using a Perl script to run chat (see Listing 2).
This script is necessary, because we use the single diald FIFO (first-in, first-out) to send back messages. As you can see from the script, we use the “message” prefix to send messages to the diald control FIFO. Additionally, the complex method by which we call chat is required, because old versions of diald call the connect script with STDERR directed to the output device. Normally this works just fine, but we need to send the STDERR results to a file and not to the modem. Versions of diald from 0.98 on will direct STDERR output to monitors by default, making this process much simpler. Fortunately, diald sets a number of environment variables which are useful for this script, including MODEM and FIFO which allow us to write a fairly portable script.
In the diald control script (Listing 3), note the connect line (line 3) which runs the runchat.pl Perl script. It has a single argument, which is the name of the chat options file used. This is useful in the event that multiple diald dæmons are running simultaneously. In my case, one diald establishes a connection to my ISP. Another diald dials into my office LAN. The only required difference between the two diald scripts is the argument provided to the runchat script. Other differences in my case are the pppd-options file specified in the last line, and the defaultroute line (my office connection uses a separate routing script).
The diald control script will need to be changed somewhat if you're using a more recent version of diald. I'm still using diald version 0.16.4 and the 2.0.36 kernel, but I plan to upgrade to the latest diald, version 0.99.1, as soon as I move to the 2.2 kernel. In addition to a number of bug fixes, the new version includes features which would probably be useful for a script like this. You can find out about the latest version of diald, now maintained by Mike Jagdis, at http://diald.unix.ch/.
A few more pieces are required to make all of this work. One is the script that establishes a connection to diald and listens via monitor FIFO to whatever diald and chat have to say. This script is reproduced in Listing 4 and is a Perl implementation of a poor man's dæmon.
This simple script maintains a file (/tmp/diald.status) which contains the last few relevant entries. Following the lead of the Tk dctrl program, the file is cleared whenever the CONNECT string is received. This is a useful way to slice things, since the user is likely interested in only the current connection progress and not in historical data. The CONNECT message is the first one transmitted via FIFO when the need for a new connection is determined by diald. Note also that the messages are detected and passed unparsed to the output file.
Finally, the end user has to actually see the results of all this work. This is done by having a special web page on the Linux box, which causes the client browser to spawn a separate status window, allowing the user to monitor the state of the Internet connection while browsing or downloading e-mail. The browser's home page is set to an appropriate local page (i.e., a page served by the Linux server) containing the following JavaScript tag:
<SCRIPT LANGUAGE="JavaScript"> <!-- comment hides the script from old browsers newWindow = window.open ( 'http://clyde/cgi-bin/dialdstate.pl?', 'dialdstate',<\n> 'scrollbars=no,status=no,width=365,height=285, status, marginheight=2, marginwidth=2'); // end of hidden portion. --> </SCRIPT>
The height and width were chosen empirically, and “clyde” is the name of the server box as presented to the LAN. All that remains is the content of the dialdstate.pl program, which is in Listing 5.
This script does very little except set up a simple page with JavaScript. The only reason it is not just an ordinary HTML page is that we use an automatic reload to cause the browser to refresh the page automatically every 7 seconds. This is the setTimeout("location.reload() ", 7000); line, which executes the location.reload command every 7000 milliseconds. This causes the Perl script on the server to rerun and provide the latest data to the user. This is fine on my home LAN with few users and little traffic, but you should carefully consider the load implications before deploying this on a larger LAN.
This solution meets the goal of providing link status information to the user, with minimal effort required by the user and no custom software on the client side. As with any project, though, there is room for continued improvement.
Possible future enhancements include upgrading to the latest version of diald and exploiting more of its features, such as reporting on the state of multiple connections. Another improvement might be to rewrite the “dæmon” in C++ rather than Perl. The existing version works, but it's not particularly elegant.
Also possible is the addition of remote link control via JavaScript buttons (e.g., Up, Down, Block, etc.), but this should be done carefully to avoid opening a security hole. Allowing external sites to see the status of the LAN's dialup link wouldn't necessarily be a security problem, but allowing external sites to control it would be. On my Linux box, I have IP masquerade set up such that the HTTP server is visible only from within the LAN. An alternative approach might be to use the security methods in Apache to limit access to sensitive web pages.