ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


Testing and Automating PPP

by Bill Unruh
05/24/2001

After you have connected to your ISP, there are a few more steps you need to go through to test and automate your PPP connection in Linux.

The first thing you'll need to do is ping the address of the remote host.

(Note: The following example is for a particular connection on my system. The IP addresses will be different for your ISP.)

In the /var/log/ppp file, you should see two lines that provide your computer with the remote computer's IP numbers for the duration of the connection. For my system, these two lines would look like

Feb 7 12:52:21 ppptest pppd[27378]: local IP address 137.82.43.5
Feb 7 12:52:21 ppptest pppd[27378]: remote IP address 142.103.234.16

Next, you need to enter the following

/sbin/route -n 

and look for an entry in which the first entry is the remote IP address, and the last entry is ppp0. It must be there for the connection to work.

Now you'll need to add the IP address for the remote computer like so:

ping <remoteIPnumber>

Inserting the example IP address above, this line would look like:

ping 142.103.234.16

You should get back a sequence of lines -- about one every second. This shows that your connection to the remote host is active. Type ^C (Ctrl-C) to stop the ping command. Sometimes the remote computer will not respond to the ping command because of the way your ISP is set up. Do not worry yet unless you get a "network or host unreachable" message.

Now, look at the lines you added to /etc/resolv.conf at the beginning of this script. You'll need to enter the ping command and the name server of the remote computer like so:

ping <nameserverIP>

where the IP address is taken from the file /etc/resolv.conf from the line that (for my system) reads

nameserver 123.456.789.012 

Again, you should get a series of responses. If you do not, there may not be support for ping on those machines. However, if you get a response saying that the host or network is unreachable, there is definitely something wrong, either with your setup or with the name server address your ISP gave you.

Now try

ping 142.103.234.16

using that actual number.

This should work unless there is something wrong with my machine. In this case, try other IP numbers. If none of these work, then there is a problem with your connection -- for example, default route problems.

Now try pinging a name like

ping axion.physics.ubc.ca

which is the location where this page is kept. The key thing to remember is that ping should report back on its first line the IP address of "axion." If it did, it means your name server is working. If the previous test worked, but this one did not, you either forgot to follow the initial instructions on this page about setting up the file /etc/resolv.conf, or your ISP has name server problems.

Previously in this series

Initial PPP Setup

Troubleshooting ISP Connection Problems

Try a few more names of machines that you know. If your system passes all these tests, try running Netscape and connecting to a page. Everything, I hope, now works.

If not, collect all of the details you can, such as the output in /var/log/ppp -- making sure that you remove your passwords from that file -- and ask for help in the comp.os.linux.networking, alt.os.linux.dial-up, or alt.comp.linux.isp newsgroups.

Be polite and look in the archives on Dejanews because your question may already have been answered many times. When you ask for help or search, make your subject and description as specific as possible. "Nothing works" as a symptom is very, very hard to suggest fixes for.

Possible problems

The PPP setup returns the error "Could not determine remote IP address".
This means that your ISP has a damaged implementation of PPP, which does not know (or refuses to report) who it is. So you need to assign your ISP an IP number. Put the lines

 :192.168.255.1
ipcp-accept-remote

into the /etc/ppp/options file. These lines assign your ISP the IP number 192.168.255.1 (a "reserved" IP number) because they refuse to tell you theirs, and also tells pppd to accept their version if at this point they wake up and finally send you an IP address.

If this happens, you might want to notify your ISP that they should know their own IP number.

Ping works -- the ping tests above all worked -- but telnet or surfing does not seem to work.
Again your ISP seems to have a defective version of PPP. Try putting the line

novj

into /etc/ppp/options. This disables compression of the headers on the packets which often causes problems.

Miscellaneous error messages

There are a few error messages which crop up with the newer versions of PPP and the newer (2.2.x) kernels.

On the 2.3.9 and 2.3.10 versions of pppd, the message modprobe: can't locate module char-major-108 is displayed in the log file. Ignore this. These versions of pppd use some new features of the PPP kernel drivers in the development kernels on Linux if they are available. This message says PPP cannot find these features. This is fine as these versions of PPP also work perfectly well with the older (2.0.x and 2.2.x) kernels.

You may see a series of lines like

modprobe: Can't locate ppp_compress-21

or 24 or 26. Put the following three lines into /etc/conf.modules (/etc/modules.conf on the 2.4.x series of kernels)

alias ppp-compress-21   bsd_comp
alias ppp-compress-24   ppp_deflate # From original RFC draft
alias ppp-compress-26   ppp_deflate # Final standard per ppp-2.3.4

Again these error messages cause no harm -- except in the unlikely event that the remote side supports these compression modes, you will not be able to use these compressions. (Modems today do compression themselves, so the advantages of software compression are often minimal).

Automation and clean up

Typing the above command line every time you want to connect can get tiring and be prone to errors. It also suffers from the problem that it must be run by "root," not an ordinary user, and is also insecure in that details like passwords are left lying around on the command line for anyone who can run the command ps to see. Thus, we want to enable the programs to be run by any user and make them easy to use. We also want to make sure that it is at least somewhat secure.

SUID

To allow ordinary users (usually you are an ordinary user) to use PPP, some changes need to be made. Just make sure that the pppd file provides "read" and "execute" permissions for users

chmod a+rx /usr/sbin/pppd

and that /usr/sbin/pppd is setuid for root

chmod +s /usr/sbin/pppd

In addition, you may have to make the serial port accessible by your users. Assuming that your port is /dev/ttyS1 (COM2) type

chmod a+rw /dev/ttyS1

Note that some programs (like linuxconf or mgetty) like to change the permissions of the serial port back to a more protected form. So, don't run linuxconf or mgetty, or get used to having to keep resetting the permissions of the serial port. Alternatively, get one of the more recent versions of pppd (such as 2.3.9). If you put the port (for example, /dev/ttyS1) into /etc/ppp/options, instead of on the pppd command line as I do in the scripts below, pppd will connect to the port as root, rather than as user, and you will not have to worry about the permissions on the port.

If you have users who you do not want using your modems, edit /etc/group and insert a line like

ppp::25:<list of names of users>

where the list of users is a comma-delimited list of the users you want to give permission to use PPP. The group number -- 25 in the above example -- is arbitrary, but should not be the same as any other group in /etc/group. Then do

chown root.ppp /usr/sbin/pppd
chmod o-rx /usr/sbin/pppd

in addition to the above changes.

Alternatively if you are running mgetty put your modem users into the group uucp, which should already be defined in /etc/group. (mgetty keeps resetting the ownership and permissions of the device, such as /dev/ttyS1, to have group uucp, and no rw permissions for ordinary users.)

Script

Let's now automate the running of pppd by writing two scripts. The first script file will contain the commands, while the second will contain the expect/send pairs that chat needs to log you on. The first file I will call pppon to distinguish it from the ppp-on which comes with your distribution, while the second will be chatscript.

The pppon script is simple, but comes in two versions. The one for the case in which you discovered that your ISP expected you to log on

pppon


===============================================
#!/bin/sh
#This script is for the case where you log on to your ISP
/usr/sbin/pppd /dev/ttyS1 57600 connect "/usr/sbin/chat -f
$HOME/chatscript"
----------------------------------------------

In this case I have assumed that each user will keep their chatscript in their home directory. Replace $HOME with the path if you want it kept elsewhere.

It is important to note that I have removed the -v from the chat command and the debug option from the pppd command. This is important as otherwise your password will be recorded in the /var/log/ppp file -- a bad idea.

In this case, where the remote ISP wants you to log in, the chat script is complex. I will also add some extra features to the chat script to make it more robust than the minimal commands I used above. (The lines starting with "#" are comments which may safely be removed or left in.)

chatscript


============================================
                      ABORT "NO CARRIER"
                      ABORT "NO DIALTONE"
                      ABORT "ERROR"
                      ABORT "NO ANSWER"
                      ABORT "BUSY"
#The above lines indicate conditions for chat quitting
                      ""    AT
                      'OK-\d\d+++\d\d\c-OK'   ATH0
# The A-B-C form of the expect sequence 
# means that it is to expect A, if A does not 
# arrive, send B and then expect C. So this line 
# means -- expect OK, if it does not arrive, wait two
# seconds,(each \d is a 1-second wait) send +++
# wait for 2 more seconds and then do not send a 
# carriage return. Finally wait for OK again. 
# If it arrives, send ATH0 The +++ is in case your 
# modem has not hung up. You may want to know if
# your modem is not hanging up, if so, remove 
# this whole line.
              OK    'AT&F\\Q3\\V1&D3M1#CC1'
# These are various controls sent to my particular 
# modem. CHANGE FOR YOURS!
# The &F, &D3, and M1 seem to be quite generic 
# for setting the modem with factory defaults, allowing
# the DTR line to reset the modem (Used when pppd shuts 
# itself down), and  M1 allows the speaker on while the
# call is being established, but off after the remote 
# system has answered. USR/3COM Sportster modems require 
# &F1 instead of &F.
# \Q3, \V1, and #CC1 are almost certainly peculiar to 
# my particular modem. Note that a backslash must be 
# doubled to get through. This sequence
# should also always be enclosed in single  quotes
# because of the special characters like &.\,#.
              OK     ATD8765432
              CONNECT ""
              ogin:--ogin:    unruh
# Again the A-B-C, except the middle B to be sent if 
# ogin: is not received is nothing except a  
# carriage return
              assword:      "dontyouwish"
---------------------------------------------------------------\

If in your determination of what your ISP wanted, you found you had to expect other text (such as "PPP? y/n") and send a response, insert those onto the end of this file. Also, since your user name, password and phone numbers are highly unlikely to be as in this script, change those.

The other possibility is that the ISP uses PAP/CHAP authorization. In this case, the pppon script needs the "user" option. You can put it into the file permanently, if you will ever only use a single ISP or, as in the following, you can allow it to be given as an option to pppd.

pppon
==============================================================
#!/bin/sh
if [ "$1" = "" ] ;then
   echo "Usage: pppon username"
   exit 1
fi
/usr/sbin/pppd /dev/ttyS1 57600 user $1 connect "/usr/sbin/chat -f
$HOME/chatscript"
----------------------------------------------------------------

This script asks for your user name on the remote system as part of the options to the pppon. You could replace the lines between the if and fi and just put the user name in instead of the $1 in the pppd command line, if you wish.

It is important to note that I have removed the debug option to pppd. Under especially PAP, using debug will store your PAP password in the /var/log/ppp file, which is not what you want. Additionally, erase your /var/log/ppp file at this point to remove the possibility of anyone reading the password in that file.

The chat script here is less complex because you do not need to log on. (For an explanation of the various lines in this script, look at the above example where I set up a sample chat script for the case when the ISP expects you to log on first.)

chatscript


======================================================
              ABORT "NO CARRIER"
              ABORT "NO DIALTONE"
              ABORT "ERROR"
              ABORT "NO ANSWER"
              ABORT "BUSY"
              ""    AT
              OK-\d\d+++\d\d\c-OK   ATH0
              OK    'AT&F\\Q3\\V1&D3M1#CC1'
              OK     ATD8765432
              CONNECT '\d\c'
# The \d means wait a second, the \c means do not 
# send a carriage return (sending a carriage return 
# at this point almost always confuses the ISP)
------------------------------------------------------

When you have created the above scripts, perhaps with the debug option for pppd in pppon and adding a -v after the chat command so you can see what goes wrong, remember to remove both of these once you have finished testing and copy them to their final home.

mv pppon /usr/bin
chmod a+rx /usr/bin/pppon
chown <user> chatscript
su <user>
mv chatscript $HOME
chmod go-rwx $HOME/chatscript

Note that we have made the chat script readable only by the user. This is important since it may contain the user's password, in the logon case.

Extra security

When you are connected to the Internet via PPP, others are also connected to you, and this could open you to break-ins while you are connected. To help alleviate this, put the line

ALL: ALL

into the file /etc/hosts.deny and

ALL: 127.0.0.1 127.0.0.0

into /etc/hosts.allow. This will disallow all external hookups by anything to your machine. If you want more detailed control, read man 5 hosts_access.

For example, if you have an internal Ethernet network, you obviously want to allow members of the network, but not others, to log on to your system.

Stopping PPP

To stop the connection, use the command

killall pppd

This sends a signal to the pppd program telling it to shut down. Pppd shuts itself down by dropping the DTR line to the modem, and by running the commands in /etc/ppp/ip-down and /etc/ppp/ip-down.local. The biggest problem with the above is that the command may not work unless you are logged in as root. I have had this trouble, others have not. If the above does not work, for example your PPP connection stays up and your modem does not hang up after a minute or so, you will either have to log on as root and then run the above command, or you can use a "wrapper" so that any user can run the above command as root. This wrapper is a C program that makes running the command as set user ID root safe. The details are given on the PPP Kill SUID Wrapper web page.

Since pppd tries to hang up the modem by switching the DTR line to the modem, the modem must be set up to reset itself when this occurs. The modem will eventually hang up if pppd stops, but it takes a while (a minute or so at times). Thus it is useful (but not crucial) that you set up your modem to use the DTR line to reset the modem. You must look up the command in your documentation for your modem. For the three different modems I have, the command is &D3 (Reset modem setting ON to OFF transition of DTR). So you would add &D3 to the modem initialization string in the chat script files.

For example, the line

OK        'AT&D3'

should be added just before the line where you dial up your service provider.

One useful safety net against running up huge bills with your ISP and making your family angry at your hogging the phone is that pppd has an option to hang up the connection if no traffic has gone across the PPP network in a certain amount of time. Enter the line

idle 1800

into /etc/ppp/options file. This will hang up the phone if there has been no traffic for 1,800 seconds (30 min.). Change that number (1800) if you want this idle option to work more quickly (or slowly).

You might want your system to do "demand dialing" -- to have your system call your ISP on its own every time you or your computer wants to connect. This is especially handy if you have a number of computers connected to yours and your computer acts as the gateway via PPP to the outside world. To do so, use the program diald from http://www.loonie.net/~eschenk/diald.html.

See Richard Senior's diald configuration page for instructions)

An alternative to diald is masqdialer which some have found easier to set up than diald. It allows users on other machines in your network to bring the connection on your Linux server up and down.

Finally, the newer versions of pppd have the demand option that will also bring up the connection when something tries to send out a request to some machine on the net.

To have others connect to your machine or to have yourself act as an ISP, use mgetty. Also get the guide to setting up dial-in access.

Here are a number of links to documentation to help you get mgetty up and running, including configurations with multiple incoming telephone lines.

For a variety of scripts, which can be of help in a some situations, see C Kite's site. In particular, for dialing a number of ISPs in a row if they are busy. This is for ISPs who all use CHAP or PAP authentication.

Previously in this series

Initial PPP Setup

Troubleshooting ISP Connection Problems

For a patch to chat, although this is by now an old version of chat, to allow use of SecureID see SecurID.gz.

For another "SecurID" type one-time password patch see http://www.inetport .com/~kite/chatbypipe.tar.gz

For a discussion on RAS callback for Linux PPP, see http://www.inetport.com/~kite/RAScb.gz

I have not tested these scripts, so use them at your own risk.

Finally, if you really want to run kppp, see http://www.crosswinds.net/~beginnerslinux

I'd like to thank staehle@nevalue.net for help in whipping this article into shape. Thanks also to pacman@cqc.com for additional improvements to this piece. Last but not least, I would thank James Carlson and Clifford Kite. Their posting at comp.protocols.ppp has taught me a lot of what I know about PPP.

I would appreciate your feedback on this article, especially if your ISP has some other strange way of authenticating you. Also if anything in this document is ambiguous, hard to follow, or wrong, please let me know.

Good luck in your connection!

Bill Unruh works for the Advanced Research Department of the Canadian Institute for Physics and Astronomy.


Return to the Linux DevCenter.

Copyright © 2009 O'Reilly Media, Inc.