Cover V06, I01
Figure 1
Figure 2
Figure 3
Figure 4
Figure 5
Figure 6
Figure 7
Figure 8
Figure 9
Sidebar 1


Connecting LAN Users to the Internet Using Linux and IP Masquerade

Charles C. Bundy

Connecting the users on your office/home LAN and to the Internet need not be an expensive proposition. You can manage it without IP address registration or Domain Name Service fees - all you need is a standard PPP account from an Internet Service Provider (ISP). At our site at the Virginia Department of Transporation (VDOT), we pay $85 a month for unlimited PPP access and 10 email accounts. The services provided on user computers are POP email, WWW browsing, and telnet. The number of client connections is limited only by the bandwidth provided by your modem. This article describes the VDOT system and provides tools for monitoring and managing the system.

A key component of the setup is a gateway machine running Linux v1.2.13 with a patched kernel that allows IP masquerade. IP masquerade is a way of aliasing IP addresses from one subnet range to a single IP address (the one that is assigned when you connect via PPP to the Internet). This aliasing is necessary because the routing information on the Internet side of the link leads back only to the ISP, and thus to the PPP interface on Linux, rather than to your LAN. The Linux gateway exchanges the PPP interface IP to your client's IP address and ships the packet out to the Ethernet interface. Figure 1 shows an idealized layout of the LAN <-> Internet connection for my site.

Note that IPC ports play a major role in IP masquerade. The LAN IP uses the port assigned by the IP masquerade to replace the return source IP address of incoming packets on the Internet PPP interface. Thus IP masquerade works only with "ported" applications, such as httpd, telnetd, popd, etc. ftpd works in kernel rev 1.3.39 or greater.

Fetching and Installing Linux

Linux is a POSIX-compliant Free UNIX for Intel x86, Alpha, and 68K processors. To get the version you'll need here, your best bet is to invest $50 in a slackware 3.0 book/CD. Make certain that it contains kernel v1.2.13, which includes the ip_masq patch. If your Linux distribution contains kernel revision 2.0 or greater, ip_masq and ftpPASV mode are included in the kernel source. If you cannot find this kernel rev, you'll need to get the ip_masq patch as well.

Your target machine should have at least 8 Mb of RAM. If you decide to run it solely as a router/gateway, a 386DX is adequate. Instead of installing an internal modem, use a COM port to make bandwidth upgrades easier (e.g., 14.4 -> 28.8 -> 64K ISDN -> 128K ISDN, etc.). Be sure the UART is a high-speed/buffered type (16540 or 16550). At my site, the router/gateway is a 486DX2-66 PC.

Full Linux installation instructions are beyond the scope of this article (if you need more details, Matt Welsh provides a good tutorial at I will simply review the basics and then concentrate on installation specifics related to building an IP masquerade kernel.

For simplicity's sake, let's assume your PC has no important data/programs on its HD, and you are going to sacrifice DOS for Linux. If you don't have a minimum setup of DOS CD-ROM drivers, you either need to create the setup or find a machine with an operational CD-ROM drive. Insert the CD-ROM, then find the program rawrite.exe and copy it to C:\DOS.

Find the Install subdirectory and enter the 3.5" 1.44M bootdisk subdirectory. If your CD-ROM drive is SCSI, use the "scsi" boot disk, otherwise pick a boot disk that contains a CD-ROM IDE driver (check the file Type rawrite and respond appropriately to the source file and destination drive questions. Go to the rootdisk subdirectory, repeat rawrite, and choose color.gz as the source file. Do not try to decompress this file: as of kernel 1.2.x, kernel files are compressed. Return to the designated Linux gateway/router and fire up Linux using the newly created boot/root disks.

Once you've logged in as root (no password), use the Linux fdisk command to partition your HD. I recommend doing three partitions, the first mounted as /, the second as swap, and the third as /usr. Once you've partitioned and set the Linux Partition Type (83 for Linux Native, 82 for Linux Swap), do the following:

cd /

Now it's just a matter of setting up your target drives (formatting and doing mkswap), selecting the source drive, and choosing which disksets to install. The default Linux kernels (IDE and SCSI) that are installed during setup don't have the correct network configuration for our purpose. You'll need to patch the kernel source for IP masquerade, so installation of the kernel source is mandatory. Below are the required router/gateway disksets. For simplicity's sake, select "ALL" items in each diskset.

A - base installation
AP - additional program/utilities
D - development
F - FAQ's and HOWTO documents
N - networking

I recommend creating a boot floppy versus installing the Linux Loader (LILO) boot menu on the HD. If you decide to install LILO, use the MBR (Master Boot Record) and only add "Linux" as a bootable partition in lilo.conf.

If your initial install went well, type <CTRL><ALT><DEL>. Watch your boot sequence messages. If you see the following error message,

BIOS32 error, sorry this version still depends on it.

don't be concerned; PCI BUS support is the default in this kernel. Simply make certain it is turned off when you reconfigure the kernel. In fact, it is important to avoid unnecessary hardware autoprobing, since such probing can cause the Ethernet driver (eth0) to fail.

Configuring and Recompiling the Linux Kernel

After logging in as root, enter the following command:

gcc -v

If you don't have gcc version 2.7.x, you need to fetch and create a development disk set that contains it. Prior versions are buggy, and some don't fully support kernel compilation of rev 1.2.x or greater. Check out the following URL for the above mentioned Linux disks and IP masquerade patch:

The most up-to-date information on IP masquerade for Linux is available at: in /pub/masq for kernel 1.2.13.

The firewall interface program (ipfw) is precompiled and available there as well. For the 1.2.13 kernel use the 1.2.n.ip_masquerade patch file, which I will refer to as masq.p. Make sure you are root before using the following commands.

cp masq.p to /usr/src
cd /usr/src
patch < masq.p

The next step is kernel configuration. My Linux box is a 486 with a SCSI CD-ROM/TAPE backup and an IDE hard drive. The Ethernet card is an Etherlink III board made by 3COM. The 1.2.13 kernel had trouble recognizing a no-name NE2000 brand Ethernet card and a 3COM 3c509 Etherlink III circa 1992. When I installed a 3c509 circa 1994, the eth0 interface came up. If you are having problems, read the NET2-HOWTO document to find out about specifying NIC board configurations at boot time. I highly recommend the 3COM 3c509 Etherlink III - just make certain it is of recent vintage. To configure the kernel, type:

cd /usr/src/linux
make config

Listing 6 is the output from my configuration session. You can use it as a guide for predetermining answers based on your installed hardware. Here are the TCP/IP specific answers:

Networking support' CONFIG_NET - y
'TCP/IP networking' CONFIG_INET - y
'IP forwarding/gatewaying' CONFIG_IP_FORWARD - y
'IP multicasting' CONFIG_IP_MULTICAST - n
'IP firewalling' CONFIG_IP_FIREWALL - y
'IP accounting' CONFIG_IP_ACCT - y
'IP masquerading (ALPHA)' CONFIG_IP_MASQUERADE - y
'PC/TCP compatibility mode' CONFIG_INET_PCTCP - n
'Assume subnets are local' CONFIG_INET_SNARL - n
'Disable NAGLE algorithm (normally enabled)'
'The IPX protocol' CONFIG_IPX - n
'Network device support?' CONFIG_NETDEVICES - y
'Dummy net driver support' CONFIG_DUMMY - y
'SLIP (serial line) support' CONFIG_SLIP - y
'CSLIP compressed headers' CONFIG_SLIP_COMPRESSED -y
'16 channels instead of 4' SL_SLIP_LOTS - n
'PPP (point-to-point) support' CONFIG_PPP - y
'PLIP (parallel port) support' CONFIG_PLIP - n

Next, you'll need to compile the kernel. Enter the following:

make dep
make clean
make zImage
cd /usr/src/linux/arch/i386/boot

If you installed LILO, enter the following to install the kernel (my LILO config file uses vmlinuz as the kernel filename):

cp /vmlinuz /vmlinuz.no_masq
cp zImage /vmlinuz
cd /

If you boot off a floppy, you'll need to do this: (put a formatted disk in drive A:)

dd if=zImage of=/dev/fd0

Use the rdev and swapdev commands to set the root and swap partitions in the kernel. Since my hard drive is IDE, I use /dev/hda1 for the root partition. Listed below are example root and swap set commands (based on my system).

rdev /dev/fd0 /dev/hda1
rdev -R /dev/fd0 1
swapdev /dev/fd0 /dev/hda2

Reboot to make certain the new kernel works before changing system files. If it doesn't work, use the install boot disk to bring the system up and see what went wrong. Using ipfw to configure IP masquerade and Firewall If you retrieved the precompiled version of ipfw from my URL or, copy it to /sbin. Add the following lines to /etc/rc.d/rc.local to enable IP masquerade for all the hosts on your subnet (in the example, I use a class C address of for MY_SUBNET):

/sbin/ipfw a m all from ${MY_SUBNET} to

Next, you'll need to modify /etc/rc.d/rc.local to limit forwarding of LAN traffic to the Internet. In the example below, I let the ISP see a certain amount of our LAN traffic (TCP/IP). If you prefer, you can limit this view to the Linux box by running ipfw on the fly when a PPP address is assigned.

/sbin/ipfw ad bl deny all iface ${WAN_PORT_IP} from 0/0 to 0/0

/sbin/ipfw ad bl accept all iface ${WAN_PORT_IP} from ${WAN_PORT_IP} \

to 0/0
/sbin/ipfw ad bl accept all iface ${WAN_PORT_IP} from 0/0 to \


You now have a kernel capable of forwarding IP traffic from a PPP interface to an Ethernet card. You also have IP masquerade set for client machines on your LAN. The next step is to make the actual dial/PPP connection. Once this is working, routing and DNS setup can be tested. Before proceeding, reboot your machine. This "reboot" test will enable firewalling and IP masquerade in the kernel.

Setting Up the PPP Link to ISP If everything went well, your kernel should have PPP support compiled in, so that you can run the PPP daemon (pppd). You'll also need a modem of some sort, the faster the better. I decided to use an external COM port to facilitate speed upgrades. Thus, I hooked a 28.8 modem to COM1. Outgoing modem configuration is simple, unlike dial-in modems. You can use it right out of the box with the default user settings (echo on, verbose status, etc).

With pppd running on your system and the serial port assigned, the last requirement is to make sure PPP is running on the remote end. This requires the following:

1. Dial the ISP (terminate gracefully using modem status)

2. Login

3. If PPP isn't automatically started, issue a PPP command to the terminal server. Our ISP automatically starts up PPP when a user logs in.

To automate the process use chat. chat reads a script file that contains phone number, login ID, and password information and automatically negotiates the ISP login. Listed below is a working chat script with dummy login information. It is safer to put this information in a script file rather than supplying it on a command line. If your Linux box supports multiple users, they can type ps -aux.

ABORT BUSY ABORT 'NO CARRIER' '' ATZ OK ATDT123-9876 CONNECT '' login: spam word: RuCrazy

Rather than typing in two different commands (chat and pppd), you can use the connect argument to pppd to invoke the chat script. Listed below is a working pppd command line. Note the use of the lock file option: this is important for modem line monitoring (Listings 1, 2, and 5.) All listings for this article can be found at in /pub/sysadmin.

/usr/sbin/pppd mru 296 connect "/usr/sbin/chat -vf /usr/lib/ppp/dial-ISP" \
/dev/modem 57600 crtscts modem defaultroute lock

At this point, save the chat script listed above to a file called dial-ISP in /usr/lib/ppp (you may need to create the subdirectory.) Replace the phone number, login, and password with your real ISP account information.

Listing 5 shows a script called check that runs pppd if the uucp lock file isn't set. Put it in /usr/lib/ppp and make certain it is called check, is owned by root, and has only user read and execute permissions set.

Check your current route table, and if the default is set, delete it:

/sbin/route del default

Now type:


Wait a minute, then enter /sbin/route: you should see a new interface, listed as ppp0. Try pinging an Internet IP, such as at (ping works from the Linux gateway, but it won't work from the LAN clients that are using IP masquerade). Use telnet to test IP masquerade. Assuming ping worked, check out the sidebar, "PPP Monitoring/Connection Options," which discusses options for keeping the link up, as well as shutting it down.

Setting Up config files for Routing/DNS In firing up the PPP interface, we deleted the default route (if set) temporarily. To ensure that LAN users can hit the Internet after a reboot, comment out the following line in /etc/rc.d/rc.inet1:

/sbin/route add default gw ${GATEWAY} metric 1

This allows pppd to set the default route to your ISP (using the defaultroute flag.) Thus any foreign traffic gets routed to the Internet. Our office has another router that connects the LAN to a corporate WAN. Those PC clients with Internet access will use the Linux box rather than the WAN router. The Linux box thus had to explicitly set routes for each WAN subnet through the WAN router. If this route information isn't set, a PC whose gateway IP gets changed will be unable to access WAN subnets. Listed below is a sample route redirect to the WAN router from the Linux box. The route commands are in /etc/rc.d/rc.local:

/sbin/route add -net gw

Once the default route is set, Internet addresses can reach their destination. However, since no nameserver has been set, telneting to an IP address works, but trying to use a domain name fails. Find out the IP address for your ISP's DNS and add it to the file /etc/resolv.conf. Listed below is resolv.conf from my system:


Make certain the file /etc/host.conf uses bind, in addition to host, for name resolution, that is:

order hosts, bind
multi on

At this point, you should be able to type:


And get a response. Assuming this works, the last step is client configuration. Again, client installation of TCP/IP and the various Internet client software packages is beyond the scope of this article, but the following are my top picks for free/share/licenseware:

TCPIP32 - Great if you are running Windows for WorkGroups

TRUMPET - Good for pre WfWG Windows (3.1 & 3.11)

Netscape - The defacto WWW browser standard. If you can't afford license fees, use Mosaic

Eudora - Lite version is free and it is a great POP email client

WinQVT - A good shareware package which has a great telnet VT220 emulation. We would have picked this except that Attachmate software's KEA! package provides Netscape and excellent mainframe connectivity (IBM 3270)

Go to for these and other Winsock packages.

Setting Up Windows 95/Windows for Workgroups/Trumpet Winsock VDOT PC clients typically run Windows with a few Windows 95 test platforms. I won't discuss TCP/IP installation for Windows here (see References for resources on this subject). Instead the focus is on configuration of pre-installed TCP/IP protocol stacks.

If you are running Trumpet Winsock, run/maximize tcpman.exe and choose FILE | SETUP. Using Figure 2 as a model, fill in the Gateway and DNS sections according to your ISP. Restart tcpman.exe and try running your Web browser with an Internet URL. Try or

If you are running WfWG and TCPIP32, select the Network program group. Run "network setup" and double-click on the TCPIP32 protocol. Referring, to Figures 3 through 5, fill in the Gateway and DNS sections.

If you use 3C509 cards, you'll need to choose the driver name carefully. We use an ODI driver called 3C5X9. WfWG insists on modifying C:\Windows\protocol.ini and renaming 3C5X9 to 3C509. This change really confuses WfWG when you restart, so manual modification of protocol.ini following a network setup session is mandatory.

If you are running Windows 95, step through the following buttons/menus/icons:

Start | Settings | Control Panel | Network

Refer to Figures 6 through 9 for various setup sections in the network program.

Conclusion Performance of our setup varies based upon the user task mix along with the speed of the external modem. With a 28.8 modem, six WWW users typically get 800-850 bytes/sec throughput. This is somewhat better than might be expected, largely because of the interactive nature of Web browsing. If all six clients were attempting to grab full bandwidth, their throughput would ideally be 2800 bps/6 = 466 bps.

We use an MTU of 1500, which is a compromise between file transfers and interactive sessions. When ftping from the Linux box, file transfers cause delays with interactive telnet sessions. This results in interactive sessions having a "bursty" flow of information: that is, you might type in a UNIX command and the resulting echo/command output would be delivered back in a few seconds as one burst of traffic.

Overall, the throughput doesn't seem to bother our users, and qualitatively the sessions seem as fast as they would be with a dedicated modem. At the moment, there are 11 PCs, one Sparc 10, and a VAX/VMS minicomputer using the Linux gateway. If more users request access, we intend to upgrade to a 64K ISDN line. This is easily accomplished since ISDN modems support the Hayes AT command set, and we are using an external COM port. The 16550 is capable of sustaining 115K bps, so a 128K ISDN connection is possible.

Any opening to the Internet of course raises security issues. This method of access is fairly secure. The IP address of our gateway is dynamically assigned, so hackers would have to probe for it frequently. Further, unless they have an account with our ISP, they should not be able to snoop on our IP traffic. And even if they are able to snoop, they should only see a fairly energetic IP, which is of course the IP masquerade, and certain generic broadcasts.

If they came across interesting IPs on our LAN, they would still have to go through our gateway to get there. Using the hosts.deny and hosts.allow files in /etc, I have limited access to telnet sessions and other inetd type services. A word of caution: those daemons that are run at boot and are not instantiated from inetd do not use hosts.deny and hosts.allow.

While this method is more secure than having a well-known IP (static) with published routing information, does limit Internet activity to gathering information versus supplying it. Right now this isn't a problem, since VDOT has Internet hosts that aren't connected to our WAN. If you are interested, check out VDOT's home page at:

About the Author

Charles Bundy received B.S. and M.CS degrees from the University of Virginia. He is currently a programmer/analyst for the Virginia Department of Transportation and has implemented a statewide WWW server program using surplus equipment and the Linux OS. He also founded an Internet Technology transfer program in 1994.