Linux is the perfect operating system to deploy in a hostile environment, the built in security features combined with the customization most window managers allow make Linux ideally suited to this task. Recently a local career planning agency wanted to deploy a dozen public access Internet workstations at various locations in the community including libraries and hospitals. Linux was chosen as the operating system for the task. This article provides details about how to setup Linux so that it can safely be deployed as a public access workstation.
When it came time to decide on how to setup the workstations various solutions were considered. It was decided before hand that the hardware would be Intel-based PC's. That essentially left us to consider the various Microsoft offerings or Unix. The licensing costs for NT would have added significantly to the projects budget. Even after buying NT licenses for each workstation, an experienced administrator would have had to spend time configuring and securing each NT machine. It was determined that NT was an option, but an expensive one. Win95 is significantly cheaper than NT, but lacks the built in security features of a more advanced operating system. Our biggest fear with Win95, was that we would frequently have people walking in and messing up the systems setup. Linux offered us a solution to all of these problems. The flexibility of X-Windows, combined with Linux's basic security features allowed us to setup the workstations such that we did not have to fear hostile users. The licensing costs were essentially non-existent, and setting up each workstation became a manner of following a simple routine.
When you have to setup a bunch of Linux workstations with essentially the same configuration, there are two approaches you can take. The first one consists of setting up and testing the first machine, then dupilicate the entire hard disk onto each workstation. (If you are doing this remember that you will most likely have to re-run Lilo on each workstation). The second method is to manually set-up each workstation by following a standard check-list. We opted for the second method due to logistical reasons. However, the installation procedure was automated by re-using config files, and running scripts where possible.
We used RedHat 4.3 as our distribution, installing from the RedHat PowerCD set. I suspect any decent Linux distribution would have worked equally as well. By the time we had finished the installation of the first machine, I had established a step by step checklist of things to do during the install. As we went along, we occasionally revised the check-lists which required us to go back to the original few machines and make some changes after the fact.
The installation started out as a standard Red-Hat install, the machines had plenty of hard disk space so we were quite liberal in what packages we installed. This included any networking stuff we felt was relevant, and X-windows. We had to manually install
ipfwadm since there wasn't an explicit option for it.
The XF86Config file is the configuration file for the XFree86 X server. We created this file as we would have for a normal Linux workstation running X except added the lines "DontZap" and "DontZoom". DontZap prevents a user from killing the X-server with a break key sequence. DontZoom prevents dynamic changing of resolutions. Both of these options prevent a hostile user from making the machine look somehow different for the next person that comes along. Further details about this file can be found in the XF86Config man page.
The following files are located in xdm go in /usr/X11R6/lib/X11/xdm.
The XResources file controls settings for xdm's log in process. We used the standard XResource file but added/changed the following lines. They all effect the apperence of the login window, with the exception of the last line which allows our guest account to work without a password.
and removed the following from the translations section to a user from getting around XDM.
xlogin*greeting: Welcome, please log in as 'guest', with no
password.
xlogin*namePrompt: login:\xlogin*fail: Login incorrect, please use the username 'guest'
with no password
xlogin*allowNullPasswd: true
Ctrl<Key>R: abort-display()\n\
We choose fvwm as our window manger as a matter of personnel preference and familiarity, most other window managers will require similar changes. All configuration information for a users fvwm setup is stored in a file named .fvwmrc located in their home directory. A system-default version of the config file is often located in /usr/X11R6/lib/X11/fvwm/system.fvwmrc. We will use this file as our base, and outline the important things you will have to check for. Since there is no "standard" base fvwm configuration, I will only outline the changes to make, and will assume familiarity with the format of an fvwmrc file.
The config file you use as your base will most likely start off with some pop-up menu's predefined. You will want to remove many of the predefined menu items.. I would recommend only leaving two items, "netscape" and "exit".
It is a good idea to disable paging, this will avoid some unnecessary user confusion.
This can be done with a line saying.
It is also a good idea to remove the "Pager" line if one exists.
PagingDefault 0
The GoodStuff program that comes with Fvwm places a "Button-bar" at a predetermined location on the screen. This button bar allows for easy launching of applications. GoodStuff is a flexible program that can be tailored to your taste. I chose a button bar consisting of a single row located at the top-left of the desktop. The following are the relevant lines.
I created a pixmap file named netscape.xpm containing the netscape logo to be used as my
icon. Pixmaps are usually stored in /usr/X11R6/include/pixmaps.
*GoodStuffRows 1*GoodStuff Netscape netscape.xpm Exec "Netscape"
/usr/local/netscape/netscape*GoodStuff Logout mini.exit.xpm Quit-Verify
Fvwm allows you to execute certain programs upon start-up. Since any guest users logging onto the machine would be using the Internet, we decided ensure that the modem starts to dial as soon as possible. We added an Initfunction section to the end of the fvwmrc file. If the PPP link already happens to be up, the ping will be successful, otherwise the kernel should start the connection process. Replace router.myisp.ca with the hostname of a machine located at your ISP.
Function "InitFunction" Exec "I" /bin/ping -c 1 router.myisp.ca &
EndFunction
In a situation where the console is publicly accessible the BIOS is your first line of defense against hostile intent. Most modern BIOS's support password protection of some sort. It is recommended that a boot-up password be set. In our setup, we decided that we only wanted to allow "trusted" people to be able to boot the machine. Otherwise someone could boot the machine using a floppy disk as the root file system,(thus they will be able to gain root privledges), or alternatively boot into DOS and format the hard-disk. In addition to the boot-up password we also installed a password to protect the BIOS setup, and disabled booting from the floppy drive.
/etc/inittab is the configuration file for the "init" process. Since we wanted our workstations to work only in X-Windows, we changed the initial runlevel to 5. It is done with the following line. This means that when the machine boots, The X-server and Xdm are started automatically.
id:5:initdefault:
"Init" is also responsible for handling the "getty"'s or terminal monitors which handle text-based logins from the console or other terminals physically connected to the machine. The default inittab file should have a section that looks similar to this.
You should remove the "5" from the second section of each line. The result should look
something like this.
1:12345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
This means that when the system is in runlevel 5(The runlevel where X-windows starts up to
handle log-ins.) A user is unable to login from the text-based console. Before making this
change it is a good idea to insure that X-windows and XDM are working properly. Disabling
text-based logins is not essential to security, but we felt that it would confuse users who
would walk up to a machine that was left logged in text mode. If for some reason X-windows
stops working after you disable text-based logins, you will have to boot the machine into
single user mode in order to login. This can be done by passing an option to the kernel from
the lilo command prompt.
1:1234:respawn:/sbin/mingetty tty1
2:234:respawn:/sbin/mingetty tty2
3:234:respawn:/sbin/mingetty tty3
RedHat uses the SVR4 style init-scripts to manage the boot-up process. The basic idea is that there is a directory for each runlevel under /etc/rc.d. When init switches runlevels it goes into the appropriate directory and executes each file that starts with a 'S' in ascending order. Eg on my RedHat system, when my system enters runlevel 3(multi-user) first /etc/rc.d/rc3.d/S10network is executed, and lastly /etc/rc.d/rc3.d/S99local is executed.
Even though we disabled the getty's for the console, a user could still press CTRL-ALT-F1 (or another function key) to switch to another virtual console from X-windows. I am unaware of a way of preventing this (short of kernel modifications). So in the event that a user accidently ended up switching virtual consoles we decided to leave the user instructions on how to get back into X-windows. We created the file S90Console and placed it in /etc/rc.d/rc5.d and gave root execute permissions to it. The file looks as follows.
Since getty does not run on any virtual-consoles, the X-server uses the second virtual console
by default.
#!/bin/shD="Press Ctrl+Alt+F2 to use this computer"
echo $D>/dev/tty1
echo $D>/dev/tty3
echo $D>/dev/tty4
echo $D>/dev/tty5
echo $D>/dev/tty6
echo $D>/dev/tty7
The file /etc/inetd.conf is the configuration file for the inetd daemon. This daemon is responsible for starting daemons that provide network services when needed. Not all daemons are started by inetd. Many, such as sendmail and httpd can either run in standalone mode, or under inetd. If your machine is only being used as a workstation, and is not providing network services to anyone then you should disable all unnecessary daemons. To disable a daemon that is currently being started by inetd, just added a '#' sign at the beginning of the relevant line to comment it out. I would recommend disabling finger, pop, ntalk, talk, and any other daemons that are not being used. We decided to leave telnet and ftp enabled to allow for remote administration. However if you are doing this remember to keep an eye out for security advisories that deal with problems associated with these packages(and any other program that is running on your system.) Usually fixing a bug is just a question of upgrading to the newest version of the program in question.
The Linux kernel can be configured to support IP Firewalling. This allows you to specify what packets the kernel should ignore, for example you can instruct the kernel to refuse to route any packets from the local machine destined to TCP port 25(of any machine). You must enable IP Firewalling, when compiling your kernel if you want to use this feature. You control the firewall parameters with the "ipfwadm" command, usually located in /sbin. We added the following lines to /etc/rc.d/rc5.d/S99local.
/sbin/ipfwadm -O -f
/sbin/ipfwadm -O -a deny -P tcp -D 0.0.0.0/0.0.0.0 25
/sbin/ipfwadm -O -a deny -P tcp -D 0.0.0.0/0.0.0.0 119
/sbin/ipfwadm -I -f
This restricts all outgoing traffic to port 25 (The mail port) so users can not send mail. Since anyone could walk up and use our workstations, we felt that it would be a bad idea to allow them to send mail. Likewise we restricted port 119(the news port) so usenet access is not allowed. Ideally we would have liked to allow read-only usenet access from Netscape, however I could not figure out how to do this so decided to be safe and restrict all usenet access.
In order to insure that your setup stays, you will want to change the permissions on various files located inside the guest users home directory. By this point you should have already created a guest user. You should also run netscape for the first time as the guest user before making these changes.
The commands above were executed, first we gave root ownership of the users home
directory. Changing ownership prevents the user from changing the permissions back. Then
we removed write access to the home directory. Next we changed ownership and removed
write access to the .fvwmrc file, the .bash_profile, .Xdefaults, .bash_logout, and .bashrc. This
prevents a user from changing aspects of his environment. Finally we secured the netscape
preferences file, and the bookmarks file. A user can still change the settings in netscape,
however they will not be saved, so the next person to login will be presented with the default
settings.
chown root /home/guestchmod 555 /home/guestchown root /home/guest/.fvwmrc /home/guest/.bash_profile
chown root /home/guest/.Xdefaults /home/guest/.bashrc
/home/guest/.bash_logoutchmod 555 /home/guest/.fvwmrc /home/guest/.bash_profile
/home/guest/.Xdefaults /home/guest/.bashrc
/home/guest/.bash_logoutchmod 444 /home/guest/.netscape/preferences
/home/guest/.netscape/bookmarks.htmlchown root /home/guest/.netscape/preferences
/home/guest/.netscape/bookmarks.htm