Linux System Administration- a Guide to Services and Duties of Administration, From the Ground Up

by: Christopher Pace
www.armory.com/~cerberus/
ares@armory.com


Overview:
Advantages of Linux Over Other Operating Systems
Distributions
Getting Started
Configuring Linux
Your Friend, the Shell
An Overview of System Services
The DHCPD Server
The Apache HTTP Server
The BIND DNS Server
The Secure Shell Server
The Pro-FTPD Server
The NFS Server
The Samba SMB Server
Assorted Servers and Services
Securing Your Linux System
Customizing Your Linux Kernel
Appendix A: Common Linux Commands
Appendix B: Continued Reading

Advantages of Linux over other Operating Systems

Linux has *MANY* advantages over other Operating Systems (OSes). Here are some of the advantages:

* Portable- can be ported to most platforms.
* Stable- can run for years without having to restart the OS.
* Better Networking- Linux was developed with networking in mind, thus it has a better TCP/IP stack than most other OSes.
* Compatibility- Linux can even be used as a Microsoft shared file server (NETBIOS), thanks to the Samba project.
* Performance- Linux is a fast, light OS that can be customized to the hardware of a particular server, allowing it to run faster than Windows NT, and many other OSes.
* Open Source- Linux is completely open source, as well as the majority of its services, if you don't like how a program operates, you can simply change it.
* Low Cost- Linux is free, and will always be free, thanks to the GNU Public License, the legal license that governs over it, preventing anyone from selling Linux, and not making it available for free.
* Small Kernel- The Linux kernel is about 25 MB. It can run on a 486 with 8 MB of RAM.

Now then, what are the disadvantages of using Linux? In a server environment, there are few, if any. The main problems that Linux does have, however, pertain to lack of hardware support (video cards, which are not needed for a server, plain text will do fine). Also, there are some driver problems with Windows-based hardware, such as "Win Modems". Again, this is not a problem in a server environment, who would want to use a software-based modem in a server? Another disadvantage to Linux is lack of software support, such as in productivity software, and games. Yet again, this is not needed in a server. So therefore, Linux has numerous advantages over many other OSes, and very few disadvantages.

Distributions

Linux is distributed through several companies, and each company has a different idea of how Linux should be used. Here is a list of some of the more popular Linux distributions, and their strengths/weaknesses:

Red Hat Linux
Red Hat Linux caters itself to the server market. It is the #1 Linux distributor.
Advantages:
Red Hat is easy to install, and easy to update, thanks to the up2date package from Red Hat, which checks for programs that are out of date. Also, the Red Hat Package Manager (RPM) format allows easy install of software.
Disadvantages:
The RPM format uses pre-compiled programs, which may be unsuitable for a faster running server (if you custom compile the program, it runs faster under most circumstances). However, source code RPM packages do exist, and they are called SRPMs (the S stands for source). Also, for a server system to be set up properly (with as much customization as possible), the system must be configured after the install.

Debian GNU/Linux
Debian GNU/Linux uses mostly GNU software (mostly open source), hence the name Debian GNU/Linux.
Advantages:
Debian allows customization of software in the installation procedure, allowing post-install configuration to be limited. Debian includes the dselect program, which allows packages with dependencies on other packages to be excluded or included. It also includes its own alternative to the RPM format, known as a .deb package, or Debian Package.
Disadvantages:
Debian is for the most part harder to install than most other distributions.

Slackware
Slackware is not as popular as Debian or Red Hat Linux, but it still warrants mention.
Advantages:
Slackware is easier to install than Debian, and easier to maintain. It aims for closeness to the original UNIX, while maintaining Linux compatibility. Also, one of their distributions, Zip Slack is only 100 MB, and it can fit on either a zip disk, or a CD-ROM, if someone wants to look at it before they decide to go with Slackware.
Disadvantages:
Slackware doesn't have a distribution-specific package. Slackware is prone to instability also, which makes it un-fit for a server environment. In addition to all of this, Slackware lacks a security updates page, so it is further unfitting for a server environment.

SuSE
SuSE, a German-based company, also aims towards simplicity.
Advantages:
SuSE is very simple to install, and to configure. It is compatible with RPM formats.
Disadvantages:
SuSE is mostly GUI-driven, and it has a high memory cost. The recommended requirements for memory is 48 MB without the GUI installer. Also, SuSE's security section isn't version-specific, meaning that all exploits are listed, leaving the novice at a loss as to whether or not they are affected.

The above listed distributions are by far the most popular, but by no means the end of the list. For more distribution information, refer to linux.com.

Getting Started

Once you have selected the desired distribution, you should then write down all specifics regarding your hardware. Also, if you are planning on dual-booting (running multiple OSes on one server), then you will have to make an empty partition, or better yet, just make empty space. However, dual booting in a server environment is probably not what most people will go with, as the server must be up constantly.

Specifics to write down include your network interface(s), the IP address(es), any SCSI adapter make and model, and of course the CPU and motherboard (some motherboards require special bug fixes to work around errors, but most likely if it is a quality motherboard, a bug fix is not needed). Since video and sound are not recommended for a server environment , after all why do you need a Graphical User Interface (GUI) for a server? Also, multimedia applications in a server environment are pointless. So, either don't put a sound card in the server (saves you $20), or just don't configure it. Also, the X Window system (GUI for Linux) uses up some resources, so you will have a faster server if you leave out the GUI altogether.

Something else you should have in mind is what role(s) is this server going to have? Is it going go have a HTTP server, a FTP server, a SMTP server, a SSH server, or another server? Write down all the intended uses of your sever before installing the OS, this will save you headache when you are "rooted" (when an attacker gains root, or superuser privileges), due to forgetting that an old version of Sendmail was running on a HTTP server. Also, it increases performance, as the extra running services take up system resources. Also, what programs will you be using (or your users)? Will Emacs be used (Emacs is a text editor that is very powerful, but at the same time takes up resources)? Will a MTA (Mail Transport Agent, program that sends mail) be used? Will any programming compilers be used? Write down a list of all the packages that you feel are needed for your server. There are two main reasons why you should do this. The first reason is that the extra packages take up disk space, which is valuable in a server. The second reason is that extra programs create extra worries, dealing with security. If there is an exploit for a program that you have, you must update it. Therefore, the philosophy with software is that the less that you install, the less you have to worry about. Worst-case scenario, if a user requests a legitimate program, you can later install it.

So, before installing, make a list of hardware details, and of what software you wish to install. Then, enter in the information when requested, this varies from distribution to distribution. Make sure to create a boot disk when asked, as this is generally a good idea, LILO (the boot manager for Linux), sometimes has problems with large hard drives on older computers. Once the distribution is installed, you are asked to restart, and then you will see a nice little login prompt. Now is where the real fun begins.

Configuring Linux

Once at the login prompt, login as root. Supply the password that you entered at the install phase. Now you can create more users, including less privileged ones, for test purposes (security), and for general use purposes (if this server will double as a workstation). You can do that with the useradd command, which will create the user only. For instance, to create a user named bob, you would enter:
useradd bob
Now, your user needs a password, you may set this using the passwd command, with their name as an argument, for instance:
passwd bob
You will then be asked for a password, and the system will warn you if it is too short (a large security risk, which will be discussed in the security section). Now then, we need to add bob to a group, lets make a new group, and name it friends:
groupadd bob.
This will create the requested group, with a GID (Group ID) as a number higher than 500 or so. The GID is a numerical number that is used to identify the group to the system. All groups under 500 are considered system groups. The lower the number is, the more privileged the group is (this is a convention only). For instance, the root group has a GID of 0. This is as low as it can go, so the root group is really powerful. Also, there are UIDs, or User IDs. These numbers work in the same exact way as GIDs, except that they identify users. Again, it is convention to use above 500 for non-privileged users. Also, the UID for root is 0. To change a UID, or GID, you will type (to open the /etc/group file for changing GIDs):
vi /etc/group
This will invoke the vi editor, a powerful text editor for Linux and UNIX. To insert text, press the insert key. Then, move down the list using the down arrow key on your keyboard, and so forth for left, right, and up. To change text, move to the desired position, and press delete to erase a character, as desired. Then, you may enter in new text, as desired. To exit and save your changes,first hit escape, then type:
:write
Type that with the ":", as that invokes the command mode of vi. Then, type to exit:
:exit
This is the beauty of Linux, you can edit configuration files that pertain to system services and the actual system, thus giving you more control. Now then, lets say that you wanted to insert a name for our friend bob:
vi /etc/passwd
This will again open our editor, vi. Now then, look at the columns of data that are presented here. So many options! Lets start with a given example line that you might see:
bob:x:500:501::/home/bob:/bin/bash
There are 7 fields in this line, each field is separated by a colon. The first field is the user name, in our case bob. The second field is the password, which is always set to "x" when shadow passwords are enabled, which will be further described in the security section. The third field is the UID. The fourth field is the GID. The sixth field is the user's name, which can be any plain text, with spaces. For example, our entry would look like this if we called bob Bob the Slob:
bob:x:500:501:Bob the Slob:/home/bob:/bin/bash
Thus, our user bob's name to the Linux system is now Bob the Slob. The seventh field is the user's home directory, where the user is allowed to write to the hard drive in this space, and where their configuration files are kept. If you do not see this line, don't be frightened, you can add it now, and then type the following commands:
mkdir /home/bob
chown bob /home/bob

The "mkdir" command makes any given directory, if you have the permissions. The "chown" command makes that directory or file set as owner by a given user. The last line in /etc/passwd is the shell, which is normally the BASH, or Bourne Again SHell. This is by far one of the most popular shells, and my personal favorite, for compatibility.
System startup files are in the /etc/init.d directory. These files control all services started, one service you might want to stop is the mouse daemon (a daemon is similar to a DOS TSR, it is a program that runs in the background). It frees up a little more resources, and besides, why would you need a mouse daemon in text mode? To view the contents of a script (a script is a text file that is executed, like a batch file in DOS), just type:
cat scriptname
Where scriptname is the name of the script. To display all the scripts, type:
ls
This will generate a listing (hence the 'ls' command) of all the files in that directory, you may wish to use a pipe (the | key) to redirect it to the more command, to where you can hit the space bar to scroll down a screen, to do this, type:
ls | more
An easy way to configure Linux is through linuxconf. To start linuxconf, simply enter:
linuxconf
Linuxconf contains a host of options, from configuring the network devices, to configuring user accounts. It is recommended that you start using linuxconf while you are still new to Linux, but that you learn how to perform given tasks (such as network device configuration) later on, as you will learn how to get more customization out of your Linux system. Also, linuxconf must be installed to work, so if you are ever in a limited environment (cannot install linuxconf), you will have to learn to perform a given task manually reguardless.
Installing software in Linux is incredibly easy. Lets say that you want to visit a given website, for instance, www.developer.com and download the latest version of their software. To visit websites in Linux (text-based only), you may invoke Lynx, a nice browser for Linux. Simply type:
lynx www.developer.com
You will then be taken to the manufacturer's website. Press 'h' to view all help, such as navigational procedures. Now then, lets say that you've downloaded the new software, and saved it in your home directory. There are two three main formats this package may be in, the first is an RPM. To install a RPM, exit out of lynx by pressing 'q'. Then, type:
ls
This will show you the contents of the current directory, the package should be in that listing. Then, type:
rpm -i packagename
Where packagename is the name of the package. This will automatically install the software. The other two formats (most popular anyways) are the .tar and .tar.gz packages. The difference is that .tar is not compressed, whereas .tar.gz is (.tar.gz may be abbreviated by .gz). To uncompress a .gz, or a .tar.gz, simply type:
gunzip packagename
This will now change it to a .tar format, which you can now extract via the following command:
tar -xvf packagename
This will extract all the files in the package, and place them in a directory, usually named after the package. Perform a 'ls' to verify the new directory name, usually in blue if colors are enabled. Then, type:
cd directoryname
To enter that directory, then perform a 'ls', and look for any files that pertain to README, be it README.txt, README, etc. Then, type:
cat README | more
Where README is the name of the file. This will redirect the output to the 'more' command, which will enable you to page through the file, press the spacebar to go forward a page, and 'q' to quit. This file is important, it gives you the directions to install the software. As you can see, RPM formats are a bit easier to install, but .tar and .tar.gz (both are often called tarballs) are the most common formats, as it is easier to make than a RPM file. This concludes configuration of Linux, if you have an error, or wish to configure it more, you may visit linuxnewbie.com, or you may email me at ares@armory.com. Throughout this tutorial, I have used redirectors (the '|' key is one). Now, we will take an in-depth look at the shell, your interface to Linux.

Your Friend, the Shell


The shell is by far your friend. Although it may look intimidating, I can assure you, it is of utmost importance. The shell allows you to create scripts, which are *EXTREMELY* important in Linux, as it is one of the advantages to Linux. Scripts are text files which execute commands, similar to DOS and Windows batch files, only far more powerful. The following section on the BASH shell is taken from a tutorial I wrote a while ago (why re-invent the wheel?). The location for the tutorial in its entirety is here. It is however in text format, which is generally not browser friendly.

Okay, so you have this $ thing. What is this? First of all, the dollar sign you see is a prompt, the remote server is waiting for you do do something. Type the following, and press ENTER:
echo "hello." Nice, you now can print stuff, kinda useless, eh? Not hardly. The beauty of *NIX is that it combines many small programs that just do one thing, so that you can combine them to perform a complex task. Now, lets start with taking a look at what's in our home directory (the path default):
ls -l
The -l specifies to print a long list, showing file permissions, the name, the date, the size, etc. This is similar to the "dir" command in DOS, but it is more powerful. Okay, now lets edit the following file, either using vi or joe:
vi .bash_profile
  or:
joe .bash_profile

This opens the file that is run every time you log in. scroll to the bottom and type : echo "Welcome to my account."
and press for vi:
(The escape key)
:write
:quit
and for joe:
Control K + X
Congratulations! You've just edited your first Linux configuration file, a common, and thus needed skill. You may wish to re-login, or you can simply type the following:
sh .bash_profile
The "sh" command invokes a shell, which reads the file specified as if it were a script (which it is). We will delve into this later. For now, lets make a listing of our directory, then save it to a file, so we can look at it later:
ls -l > ls_1.txt
What this does is it redirects the output of the command 'ls -l' to a file, which is ls_1.txt. The ">" redirector does this. Now, lets take a look at that file. We just want to see what's in the file, not edit it, so we'll type:
cat ls_1.txt
If the output is too long, we can use another redirector, the pipe. This is located usually on the same key as the backspace key. It is a little vertical line. Lets make it to where the output of the 'cat' will go to another program, which is 'more':
cat ls_1.txt | more
This makes it to where you can page through it using the space bar, this is handy when the file specified is too big to show it all on one screen, use the space bar to page through a screen at a time...nice. Now, then, we shall cover another simple command, the who, or w command (either will work):
w
The "w" or "who" command will output a list of all logged in users, their task(s), when they logged in, etc. Nice. Lets suppose though that we wanted to use a single command to output the task(s) of our friend, john:
w | grep "john"
You will remember, the "|" operator redirects the output of 'w' to 'grep "john"', grep is a tool that searches for text in a file, or whatever input is. For instance, if you wanted to write a file of current users and their tasks, and then search that for john:
w > users.txt
cat users.txt | grep "john"
As you will recall from earlier, cat displays the contents of a file, when piped to grep, grep searches for and displays any strings having john in them. Now then, lets cover another file, .bash_history. .bash_history is exactly that, it is the history of all BASH commands inputted, lets display it:
cat .bash_history
You can pipe it to more command if you wish, so you can page through it. Nice. Now then, lets say that we want to copy the .bash_history file to bash.history.bkup:
cp .bash_history bash.history.bkup
This will duplicate the file, so we now have two copies. Well, what if we want to rename that file (the backup) to bash.history:
mv bash.history.bkup bash.history
The mv command moves files, what we are doing is moving it from one name in your home directory (we'll cover this soon), to the same directory, under a different name. Now then, what's this home directory stuff? As specified in /etc/passwd, your home directory is the directory that you are placed in when you login. You usually have full permissions of this directory, lets see what your home directory is:
echo ${HOME}
The echo command, which we've already covered, prints the ${HOME}, but what is that? That is called a shell variable. $ means that it is a variable, {HOME} specifies that it is the variable named HOME. Lets make a new directory in your home directory, first we will switch to that directory:
cd ${HOME}
The cd command means change directory. It changes the user's current directory for the directory specified. Now, lets make the new directory:
mkdir TEST
The mkdir command makes a directory, under the name TEST. Now then, lets change directories to that directory:
cd TEST
Now we are in that directory. Nice. Now, we'll back out of this one, returning to the parent directory, or the directory above this one:
cd ..

The ".." specifies to move back one directory. To verify that we are in your home directory, we will display the current dir:
pwd
The pwd command displays the present working directory. Okay, now lets copy the backup of our history file to the TEST directory:
cp bash.history TEST
The cp command once again copies it to a location, this time a directory. Perform a 'cd' to that directory, then do an 'ls' to see the contents:
cd TEST
ls -l
The -l option gives a long list, without -l simply shows the file names. Okay, lets create a file, test.txt containing the string 'This is a test.' :
echo "This is a test." > test.txt
Now you can cat it if you wish, but the main reason we created this is to cover the next subject, chmod. Chmod changes a file's permissions, which can be tricky at first, but is *IMPORTANT* for basic security. In order to do this, you need to know binary, or you can use the simpler string format, which we will use in this example, I don't want to confuse anyone this soon, if you want to know how to use chmod, check out the man page (you'll learn about this later, too). Now then, chmod follows the following syntax:
chmod (permissions) (file)
u means the current user
g means the user's group
a means all users
- means take away this privilege
+ means give this privilege
= means that this will be the only permissions this file will have
r means that you can read the file
w means you can write to it
x means that you can execute it
User permissions are displayed as:
-rwxrwxrwx
The first bit, or character is a special one, used to run as that user, to specify a directory, etc. The next three characters 'rwx' refer to the user that owns that file. The next three after that 'rwx' refer to the permissions of that owner's group. The last three characters 'rwx' specify all other user's permissions. a '-' instead of a character means that that permission is disabled. For instance:
-rwx-r--r--
Means that the owner can read, write, and execute, but the owner's group, and all other users can only read from it. Now then, lets modify our new file, test.txt so that we cannot read from it (follow me here, this is to demonstrate something):
chmod u-r test.txt
Now lets try to cat it:
cat test.txt

You should get an error basically stating that you don't have read permissions for this file. Now, lets change it back:
chmod u+r
Cat it again to be sure that it is changed. Nice, now lets make it to where only we can read, write, and execute to that file:
chmod ga-rwx test.txt
That made it to where no one can read,write, or execute:
chmod u+rwx
This will give us read, write, and execute privileges. Take this time to play around with it, learn how to use it better. Now, since we are discussing file ownerships, I figured that I would throw in another command, chown. Chown changes a file's owner, following the format of 'chown (user:group) (file)'. For instance the following command:
chown root:root test.txt
Will make it to where only root is the owner. Don't do this, otherwise you will have to write a letter to root, kindly asking them to change the permissions back (unless you have root access). Another command you should learn how to use is rm. use this with caution, however, as 'rm' removes files:
rm -R ${HOME}/TEST
Will completely delete the contents of the directory TEST that we created earlier, plus delete the directory itself. The -R parameter means that it should operate recursively, which means to delete every file, to descend into directories, then remove those files, and the empty directories. Now, lets say that you want to cat a text file, but you want to be able to scroll back a page or two wile reading (be able to go back and forth), you would:
cat filename.txt | less
Use the space bar to go forward, and the P key to go to the previous page.

Now that we have covered the basic commands, we will dive into scripting via the shell. For those of you that feel as if the shell doesn't offer enough power, I recommend you taking a look at Perl, an excellent scripting language that was designed out of a need for more power than the shell provided. One of the most important commands to remember is chmod. When dealing with scripts, you have to make the file executable. This can be accomplished by simply:
chmod u+x filename.sh
OR:
chmod 700 filename.sh
The 700 part will give the owner read write and execute privileges, while giving all other users no privileges whatsoever. Alternatively, and also more annoyingly, you can simply use the 'sh' command, followed by the script name, without needing to modify the permissions. Lets get into basic principals now of scripting, so we will start with a simple "hello world" script. Scripts are like normal text files, so you can use a text editor like vi, vim, joe, jed, etc. So, lets create a file called hello.sh, and place in it the following lines:
# hello.sh a simple script
echo "Hello World"

And save it. Now, you can either 'chmod u+x' this file, or you can execute it by:
sh hello.sh
However, if you chmod-ed it, like I suggest, you will need to:
./hello.sh

Now, what's this './' stuff all about?? The answer is simple, the './' indicator means the current directory, which is similar to '..' when we were playing with 'cd'. If you 'cd ./' it will stay in the same directory. For instance, if the current directory was '/home/user', the value of ./ would be the same as typing /home/user. If you want to just execute hello.sh by just typing hello.sh, you will need to change your search path. Your search path is a variable that is defined as the paths to search for an executable file. Instances of this are '/bin', '/usr/bin', and usually '/usr/sbin'.
Now that we have the actual execution parts taken care of, lets dissect the script. We shall start with the first line, which begins with a '#'. This is known in the Linux and UNIX world as a hash mark, and it is used for comments. Anything after a '#' is ignored, so you can type whatever comments you want without any worry of bothering the script. Now, for line 2, 'echo "Hello World"'. This command, echo, tells the shell to repeat, or echo whatever is in the parentheses, which in this case is Hello World. Now then, lets cover another important feature of scripts, the ability to force many commands onto one line:
# force.sh This demonstrates the use of the semicolon to force many commands onto a single line.
echo "1" ; sleep 1 ; echo "2" sleep 1 ; echo "3"

This should echo 1, wait a second, echo 2, wait another second, then echo 3 to display a nice little timer. First lets cover the sleep command, the syntax of the sleep command is: sleep {# of seconds} {suffix} the suffix may be s for seconds (default), m for minutes, h for hours, or d for days. This is used in between commands that you would want a pause in, such as the timer example. Now, lets cover the purpose of this example, the semicolon ';'. The semicolon is used to separate commands that you want executed one after another. Now, you may question the importance of this, so I'll tell you: the semicolon is important, because you can enter entire scripts (if they're short enough) on a single command line, without having to make an actual script. So in the example above, with the exception of the first line (everything behind a hash mark is ignored, remember?), if it were entered into a command prompt, it would work just the same. Plus, if you want to get really technical about it, it would be faster, as the system doesn't have to read from the hard drive, it is right in memory (the commands). Now then, lets deal with making a script that will echo whatever you want it to:
# argument.sh Echos an argument of the shell script
echo $1

This will echo whatever you choose, you just have to use it in its own special syntax, which is:
argument.sh The text that you want displayed
Now then, you may notice that if you type:
./argument.sh text that i want
The script only echos "text". How should we remedy this? You remember that echo had to have quotes surrounding it? Well the same aspect is here, you *have* to enclose it in quotes, like:
./argument.sh "text that I want"
You should also know that the & symbol after a command/script tells it to run in the background. For instance, 'ls &' will preform an ls, just in the background. If you want to re-direct the output of a program to somewhere that it isnt taking up space on your console, you can redirect it to /dev/null, which will not return any output at all, it is a system device that is designed for uses such as this, for example:
ls > /dev/null
This redirects the ls output to /dev/null. Also, you can spawn another shell to execute a command (has to be a command, or executable file, cant be the name of a script in the local directory, without the absolute path ('./'), is to use the ! symbol. For instance:
! ls

However, it should be also noted that 'sh' can only execute scripts, not binary executables, such as the ls program. Now then, lets go a step beyond the "hello world" class of scripts, and lets dive into utilities, how to tailor Linux to your liking:
# delete.sh Moves files to /usr/username/trash, which is only readable by that user.
mv -f $1 ${HOME}/trash

As you will remember, the 'mv' command moves a file, and the -f option forces it. What this does, is it creates a "recycle bin" like that in Microsoft Windows, in your home direcory, under trash. Now then, what about recovering it????

# undelete.sh undeletes file specified by user.
mv ${HOME}/trash/${1} ./

This is relatively simple: the mv command of course moves it, this time we'll leave the -f option off, we want to be warned if a file is going to be overwritten (if the destination file has the same name as the file to be recovered). ${HOME} means $home, or the user's home directory. ALWAYS enclose variables in {}, this keeps the values intact, so it doesnt mess up, without this, the above script(s) won't work. Now then, the ${1} is a little new here, once again enclosed in {}. It is good practice to always enclose your variables in {}. And of course ./ is the current directory. Simple stuff. Now then, lets say that you wanted to time a script to get a directory of all the files in your home directory, then to compare that listing every hour and look for changes:
# ls.sh Compares a directory's contents (in this example the users home dir) for changes in a given time interval, in this case one hour.
ls -l ${HOME} > ${HOME}/.ls
sleep 1h
ls -l ${HOME} > ${HOME}/.ls-comp
diff ${HOME}/.ls ${HOME}/.ls-comp

This will give a non-null output if the contents are changed. Actually, it should have the files listed that have changed as well, but lets break this down some. First line is easy, it executes an 'ls -l' (long list of directory) in ${HOME}, then redirects it to a file, called .ls (In Linux, any file that begins with a '.' is hidden, unless you preform an ls -a), then we wait for an hour. Then we take another 'ls -l' and redirect it to a seperate file, .ls-comp. Then, the diff command is executed, which searches for any differences in the files. If one is found, it is displayed. Otherwise, it exits with no return value. Let's play with this some though, as it does not run continuously:
# ls.sh part 2 origional modified to send user warning of file change.
while echo "Perpetual loop" > /dev/null
do
ls -l ${HOME} > ${HOME}/.ls
sleep 1h
ls -l ${HOME} > ${HOME}/.ls-comp
if diff ${HOME}/.ls ${HOMR}/.ls-comp
then echo "this is ignored, since it is being redirected to /dev/null" > /dev/null
else
clear
ECHO "FILES CHANGED!"
break
fi
done

Lets start from the first line, this script invokes what's called conditional logic, which states basically that if something is true (no returned value in the instance of shell commands), then the script should do something. The first conditional logic we will use is the while statement. The while statement will continue to preform what is between "do" and "done" until either it is broken out of, or the test returns a non-zero value (it returns text, whatever). While follows:
while command_that_returns_no_value
do
some commands
done
Now then, the command that we want while to test is going to be echoing something to the null device, /dev/null, which returns no output. This creates a perpetual loop, until we break out of it. The rest is the same, up to the if statement, which follows:
if command_that_returns_no_value
then do something
else do something different
fi
The 'fi' ends the if loop. What we are now saying is that if when we compare the diff output, if it returns no value (is true), then we want to do nothing, which in this case is another practice in using /dev/null. Now, if it returns other than zero, it means that a change has been made, which echos a nice little warning, then breaks out of the while loop, exiting the script. Well, what if we want an email report? Insert the following line after the warning, but before break (or line 12):
diff ${HOME}/.ls ${HOME}/.ls-comp | mail yourusername@yourdomain
This will email you the contents of the output of the differences in the files. Now, if you want this script to run non-stop, you'll strip the break command out, so it will email you each time that a change is made, continuously running. Also, you'll take out the echo "CHANGES...." part out, which will thus print no info, and invoke it like:
./ls.sh &

As you will remember, the '&' after a command tells the shell to execute the command in the background. Nice, now you have a free VT (Virtual Terminal, discussed later), or telnet session to monitor any changes made to your directory. As I'm sure you're getting the picture of, Linux can be tailored to fit your individual needs. The only limitation is yourself. If you feel you need something that others can't provide, or if you want to do it yourself, you CAN! And its relatively easy, as opposed to writing C code all day long. Now, you basically should get the idea of how scripting works. Now though, we will go into aliasing and linking, and modifying your search path. First, the search path:
$PATH = ${PATH}:/directory_you_want_included
export $PATH

This will add an entry to the PATH variable. Place this line in your .bash_profile, or /etc/profile (for all users). This will search your directory for a given command, after all others direcories specified in your $PATH variable have been searched. You can also:
$PATH = /dir_you_want:${PATH}

If you want it first. I prefer it to be last. Now, what about aliasing? Aliasing is used to make one "command" act as if you entered another. Type to see all aliases:
alias
To add an alias:
alias desired_command_name='real_command_name'

This will create the alias of a desired reference command to a real command. For instance, a common alias is to do alias ls='ls --color' which causes the defualt 'ls' to output 'ls --color' each time. Now, about linking. Linking is used to link one file to another. For instance, lets say you want a link in your home directory to /home/some_user/their_mp3s:
ln -s /home/some_user/their_mp3s ${HOME}/cool_mp3s
This will create a "directory" in your home directory called cool_mp3s, which acts as if it were the target directory. Thus, you can 'cd cool_mp3s' to cd to that user's mp3 directory.
By now, you should understand how to make shell scripts, and how to execute them. There is an appendix at the end of this document worth reading, Appendix A: Common Linux Commands, if you are having trouble with the Linux commands. Also, there are a few personal favorite shell scripting books of mine whole titles are listed in Appendix B: Continued Reading.

An Overview of System Services


System services are the services that your server will run, and be used. These are what makes your server a server basically, and what brings you customers. Whether your customers be paying users (such as in an ISP), or they be donation users (users that give little or no money towards your server), they are still important. They are the reason that you want a server, so it is important to think of them. Linux offers *MANY* services, here are some of the more common services:

* Shell Services (The Secure SHell (SSH), Telnet, Remote Shell, etc)
* Mail Services (POP3, SMTP)
* Web Services (Web Hosting)
* DNS Services (Domain Name Services)
* FTP Services
* Talk Services (via Talkd, enables users logged in to chat with each other)
* Kerberos Services (secure authentication techniques)

Linux offers many other services, of which will be described in detail later. Most of the services lie in the /etc/init.d directory, which is actually a set of startup scripts, but as most services are started at boot, so the /etc/init.d directory would be a good place to start looking for services installed.....you can also try telnetting to known service ports, which are listed as follows:


Telnet: 23
SMTP: 25
HTTP: 80
DNS: 53
SSH: 22
Talk: 517
Kerberos: 750
FTP: 21

If you are running the service, you will get a message that looks like:
/home/ares> telnet localhost.localdomain 22
Trying 192.122.209.42...
Connected to localhost.localdomain.
Escape character is '^]'.
SSH-1.5-1.2.20


Then you are running the service that is reported. Also, you can download the portscanner nmap from from insecure.org. It is available in RPM formats, as well as .tar and .tgz formats. Once installed, you can invoke it by using the following syntax:
nmap localhost.localdomain
Nmap will then ouput all the open ports on your server. This is also good for scanning other servers on your network, to see what services they are running. If you see a service, such as Sendmail (SMTP service) running, and you dont need it, i reccomend removing it, via commenting out the lines in /etc/init.d/sendmail, or by just issuing the following command:
/etc/init.d/sendmail stop
Then uninstalling it, with the package manager for your distrobution (i.e. rpm for Red Hat Linux). For instance, to uninstall a rpm package, use the following command:
rpm -e packagename
To see a list of all rpm packages, use the following command:
rpm -qa | more
This will send the output to the more command, as we have covered earlier. If a package gives you a dependency error, you will need to uninstall the dependency first, or you may force the uninstall with the -f option (*NOT* reccomended). You can use the dselect program in Debian Linux to remove the unwanted package, simply type:
dselect
To bring the dselect menu up. This is more user-friendly than the rpm utility, if you like interfaces that is. Now, we will move on to specific services, the first on the list is the apache web server.

The DHCPD Server


The DHCPD server is a server that allows DHCP clients to connect to the server, and request IP addresses and gateway/dns information. DHCP is used in most large networks as a means of easily managing IP addresses. Linux has a server of its own, creatively called DHCPD. DHCPD is available from the Internet Software Consortum's website at isc.org. The server should also be available from your distrobution however, so check with your distrobution first.
ISC only supplies standard tarball packages, so if your distrobution does not supply the DHCPD package, you will have to use the ISC's package. Download the file and extract it using the following two commands:
gunzip dhcpd-version.tar.gz
tar -xvf dhcpd-version.tar

Make sure to replace version with the actual version. Now, preform the following commands:
cd dhcpd-version
./configure
make
make install

DHCPD should install flawlessly, if not then you should complain to the mailing list on the ISC's website. We will only have to preform three tasks with DHCPD, the first is to edit the configuration file. Place the following text in your /etc/dhcpd.conf file:

# /etc/dhcpd.conf by Christopher Pace
ddns-update-style ad-hoc;
default-lease-time 259200;
max-lease-time 300000;
option subnet-mask 255.255.255.0;
option routers 192.168.0.1;
option domain-name-servers 192.168.0.1;
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.20 192.168.0.40;
range 192.168.0.50 192.168.0.90;
}

Of course you will want to substitute the routers, domain-name-servers, netmask, and range with what is for your network. For instance, I have a network that I use DHCP to assign a total of 60 IP addresses. This range is from .20-.40, and from .50-.90. DHCPD will only assign IP addresses within this range, as I like to keep .1-.19, .41-.49, and .91-.254 free for servers and such. The 'default-lease-time' and 'max-lease-time' settings are used to specify how long the DHCP lease will last if the client doesn't request extra time (default), and if it requests the max time (max). This time is in seconds. If you want to have a static IP assigned to a host, then you can use the following syntax in your /etc/dhcpd.conf file:
host Joe {
hardware ethernet 00:c0:f0:25:b7:15;
fixed-address 192.168.0.205;
}

This will assign the IP of 192.168.0.205 to Joe each time that it requests an IP. The MAC address is the 'hardware ethernet' address.
Now then, we move along to the next step, creating the /var/state/dhcp/dhcpd.leases file:
touch /var/state/dhcp/dhcpd.leases

Now, we will start DHCPD, to test it out. First, if you are currently using another DHCP server on your network, disable that one. Next, run the following:
/usr/sbin/dhcpd
Finally, start up a DHCP client (if you are using Windows 98/2000/XP/NT, you can use the ipconfig command to release the IP and then renew it by typing:
ipconfig /release_all
ipconfig /renew_all

This should take a while, as the DHCP client is searching for the original server. After a while, it will time out, and then query the network for any DHCP servers, finding our Linux one. Now, once you are sure that DHCPD works, we should create an init script for DHCPD. This is used to start, restart, and stop the DHCPD service. Also, this init script will be automatically run at boot to start DHCPD. Place the following text in /etc/init.d/dhcpd:
#!/bin/sh
# /etc/init.d/dhcpd file by Christopher Pace
case "$1" in
start)
echo -n "Starting DHCPD Daemon: dhcpd"
start-stop-daemon --start --quiet --exec /usr/sbin/dhcpd
echo "."
;;
stop)
echo -n "Stopping DHCPD Daemon: dhcpd"
killall -9 dhcpd
echo "."
;;
restart)
echo -n "Restarting DHCPD Daemon: dhcpd"
killall -HUP dhcpd
echo "."
;;
*)
echo "Usage: /etc/init.d/dhcpd {start|stop|restart|reload|force-reload}" >&2
exit 1
;;
esac
exit 0

You should now:
chmod 700 /etc/init.d/dhcpd
ntsysv
     
update-rc.d dhcpd defaults     If you run a different system then listed, you should check with your distribution on how to properly tell the system to use the init file you just made. On some systems, simply chmod-ing the init file will work. Also, some systems only have a /etc/rc.d directory, where the init file should be placed in the run levels associated with startup, halt, and so forth. Read the FAQs that your distribution has as to which run levels are for which tasks, as some distributions tend to go against POSIX.
DHCP is a useful client, but when routers are shipped with DHCP server capabilities, too often the DHCP server is stripped-down, leaving the many options that DHCPD offers missing. Thus, it is necessary to have DHCPD instead of these stripped-down servers, in order to satisfy particular needs. For instance, I need 60 DHCP-assigned addresses, in two different IP ranges. Thus, I would recommend DHCPD for anyone who needs a truly customizeable DHCP server.

The Apache HTTP Server


The Apache Web Server is available from apache.org. This is an extremely powerful, and highly configurable web server, which is available for many platforms, including win32 platforms. It also has SSL capabilities, and by far is the server of choice if you plan on having a web server. In addition to all of this, it is more secure, and costs less than Microsoft's IIS server.
To get started with Apache, you should first download the latest version from apache.org. Apache offers both pre-compiled versions, and source versions. Source versions are generally better, because they allow your system to compile the source (to ensure compatibility), and so that you can include or exclude any options you deem necessary. Also, the only formats supported as of June 7, 2002 is the tarball format. However, several distributions have made packages to conform to their packages, such as Red Hat. Should you decide to download Red Hat's package, you may install it by entering:
rpm -i apache-1.3.19-5.i386.rpm
Assuming that version 1.3.19-5 is the version, and that i386 is your architecture.
For those of you that would rather compile your Apache server, first you must download it, and place it in the /root directory (I prefer to always copy software to be installed to the /root directory). Once downloaded (assuming that you downloaded the tarball), you will then issue the following commands:
gunzip apache.tar.gz
tar -xvf apache.tar

This will extract the Apache source into a directory called httpd-version. Then, we will 'cd' into that directory, and then enter the following command:
./configure desired_installation_path
If you desire a directory to install Apache into other than the default, then enter it in place of 'desired_installation_path'. Otherwise, leave it blank. This will check your system to see what compilers, and system settings are on your server. After the configuration script has finished, you will then need to type:
make
This will compile the Apache files, now would be a good time to grab a bite to eat from the company fridge, or to count the tiles on the ceiling. This step should take about 10 or 15 minutes, depending on the speed of the installation system. Once this is complete, we will enter the following command:
make install
This will take not nearly as long, all that this does is install the compiled software. This should typically take under a minute or so. Now then, we will issue the following command to start the Apache service:
/path_to_apache_install/bin/apachectl start
Insert the directory you specified when you installed Apache. If you didn't specify a directory, then it is /usr/local/apache OR /usr/local/apache2. To test the Apache install, point your favorite browser to the address 127.0.0.1, which is the standard address for localhost.localdomain, or the local system. You should be seeing the standard Apache welcome message, which will say something to the effect of (in Lynx, so its text-only):
Test Page for Apache Installation
If you can see this, it means that the installation of the Apache web server software on this system was successful. You may now add content to this directory and replace this page.
___________________________________

Seeing this instead of the website you expected?

This page is here because the site administrator has changed the configuration of this web server. Please contact the person responsible for maintaining this server with questions. The Apache Software Foundation, which wrote the web server software this site administrator is using, has nothing to do with maintaining this site and cannot help resolve configuration issues.
___________________________________

The Apache documentation has been included with this distribution.
You are free to use the image below on an Apache-powered web server. Thanks for using Apache!

Now, the real fun begins, with editing the Apache configuration file. In order to do this, you should know how to use a text editor of your choice. Refer to the section on the shell if you are unable to remember how to use the given text editors. First you will need to change directories to the directory named 'conf' in the root directory of the Apache install. In this directory are several configuration files, most notably is the httpd.conf file. This file controls much of Apace, and is all that you will have to worry about. This file is pretty much self-explanatory, however we will cover the more important settings in this file. The first setting that is important is the Timeout setting, which is defaulted at 300 seconds. This means that the server will wait 300 seconds before stopping a transfer request, whether it be a send, or a receive. I recommend for maximum performance decreasing this number. What value to choose varies, if this is an Intranet server, lower it to around 45 seconds. If it is to be used as an Internet server, lower it to 120 seconds. If a client takes longer than a minute and a half to get a HTML document, they will try again. This is not for actual transfer times, but rather for times during a transfer request.
The Listen setting allows you to bind Apache to a port other than the default. This is good if you desire for your clients to connect to yourserver.com:8000, but it is rarely needed. Also, this directive will allow Apache to listen for requests for a certain IP. However, the VirtualHost directive is going to be used also if you desire to do this.
Next, the ServerAdmin setting should now be changed, change this to your email address, or the address you desire for users to email you. This address can be posted on the 404 error pages, and is also used by Apache sometimes to send you status reports.
The ServerName setting should now be changed, this will be on error pages, so it is important. Change this to the domain name of the server, or to the IP address, if you do not have a domain name for the server. You must also enable the UseCanonicalName setting, simply set this to "Yes".
Next, and most important, is the DocumentRoot setting, which enables you to specify the desired directory for your HTML pages. Change this to the directory in which that you wish to store all of your website-related files, such as images and Java applets also.
The Directory setting should also be set to the same directory as DocumentRoot.
The next setting that should be looked at is the ErrorLog setting. This allows the error log for Apache to be any file that you choose. The default is normally fine, but if you would prefer the error log to be in another location, then enter that location.
Next is the ServerSignature setting, I would recommend setting this to Off, because anyone can request a 404 just to see what version you are running.
A nice feature is the ErrorDocument settings, which allow you to specify a file, or custom message to be sent to the client upon an error, such as a 404, 403, etc.
The last directive is the VirtualHost directive, which looks like this:

NameVirtualHost otherhost
(VirtualHost otherhost>
ServerAdmin web@otherhost.com
DocumentRoot /www/docs/otherhost.com
ServerName otherhost.com
ErrorLog logs/otherhost.com-error_log
CustomLog logs/otherhost.com-access_log common
(/VirtualHost>


Note, the '(' should be a '<', I had to change that because this is an HTML document. The NameVirtualHost directive should be the name for this other host, which should be in the directive. ServerAdmin is the address for the administrator for this host. DocumentRoot is the root for this host. ServerName is the domain name of the server (or IP). The ErrorLog is the error log for this host. The CustomLog is the path for a custom log (if you desire one). You may also include any other directives, such as ErrorDocument directives. Simply add them in between the VirtualHost directive.
Now that configuration is complete, you will need to restart the Apache service. Enter the following on a command line:
/path_to_apache/bin/apachectl restart
You may replace restart with start if you previously stopped the server. You may stop the server by replacing restart with stop.
Most of the time (unless your version of Apache was a vendor-specific version), Apache will not restart when you restart the system. There are several ways to fix this, the easiest is to add the following line in your /etc/rc.local file:
/path_to_apache/bin/apachectl start
This will start the service every time the system boots. A good idea whenever you make changes to the Apache configuration file is to test the new configuration. You can do this by entering:
/path_to_apache/bin/apachectl configtest
If all is well, you will see the following:
[root@hate2 cerberus]# /usr/local/apache2/bin/apachectl configtest
Syntax OK

[root@hate2 cerberus]#

This tutorial only briefly covers all of the Apache uses/options. If you find that you still have unanswered questions, you may either email me at ares@armory.com, or you may visit the official Apache webpage at apache.org. Also, if you are extremely interested in Apache, there is an organization that will email you their weekly newsletter for free. They are located at apacheweek.com. Now, we will cover how to make Apache and other services operate on a domain, or rather, configuring the BIND DNS Server.

The BIND DNS Server


DNS service is crucial for your server if you wish for it to be accessed from the internet. The reason for this is that domain names are much easier to type for users, and easier to remember. Thus, you need a DNS server if you plan on having internet users connect to your server. The standard DNS server is the Berkley Internet Name Domain (BIND). BIND is available through the Internet Software Consortum, or ISC at isc.org. In addition, BIND should be available through your distrobution. In the case of BIND, I would reccomend downloading the packages through your distrobution's website. Before you may use a domain name, you must first register it, which there are several services available to register domain names. Once installed, you should then edit /etc/named.conf, and add the following information to it:
zone "desireddomain.com" {
type master;
file "desireddomain.db";
};

You will of course replace the "desireddomain" strings as appropriate with your new domain name. This entry tells the named service that this server is the master server (with DNS, 2 DNS servers are required, for redundancy). Now then, we will now create the "desireddomain.db" file, which should be placed in the working directory of named, which is specified in the beginning of /etc/named.conf. In this file, we should place the following information:
IN SOA nameofyourfirstdnsserver.com. nameofyourseconddnsserver.com. (
1000000; Serial
10800 ; Refresh - 3 hours
3600 ; Retry - 1 hour
86400 ; Expire - 24 hours
3600 ) ; Minimum - 1 hour

IN NS nameofyourfirstdnsserver.com

www IN A ipaddressofwebserver
ftp IN A ipaddressofftpserver
smtp IN A ipaddressofmailserver


This should be saved in the directory specified in the first few lines of /etc/named.conf. Now, we will configure a secondary DNS server, or a slave DNS server. This is much easier than setting up the primary/master server. The only file to change will be the /etc/named.conf on the secondary server. You should place the following in the /etc/named.conf file:
zone "desireddomain.com" {
type slave;
file "desireddomain.db";
};
Now, we can grab the configuration file from the first server using a utility that comes with BIND, named-xfer. We will do this by entering:
named-xfer -z desireddomain.com -f desireddomain.db \ -s 0 addressofprimarynameserver
This will copy the configuration file from the primary DNS server.
BIND should start automatically, if not, you may start it with the following command (for most systems):
/etc/init.d/named start
You should allow somewhere between 24 and 48 hours for the DNS records to be updated once you move your DNS server from host to host. DNS is a great protocol, and makes our lives easier, by allowing us to be lazy (simply type a domain name instead of an IP).

The Secure Shell Server

The Secure Shell (SSH) Server is a secure replacement for telnet and rlogin, etc. SSH uses encryption from the point the client connects to a server, to the time the connection is terminated. SSH uses encryption to hide passwords, user names, and other sensitive information that is normally sent "in the clear" in servers such as telnet and rlogin. SSH as of this writing supports the following encryption algorithms: 3DES, Twofish, Blowfish, Arcfour, CAST128, AES (Rijndael), and DES. SSH now comes with a variety of distributions, so downloading the server and the client should be a pinch. If, however, your distribution lacks a SSH server package, you may download it from the SSH website at www.ssh.org. SSH is one of the more easier to install packages, so installation should be a breeze. Install the package from your distribution using the appropriate package manager (for example use rpm -i packagename for Red Hat-based systems, and dpkg -i packagename for Debian-based systems).
Once installed, SSH should work properly. To test it, you may login to your server by issuing the following command:
ssh -l username 127.0.0.1
Replace "username" with your desired user name. If all is working correctly, you will be prompted for a password, and then connected. If this does not work, if you installed SSH from source, and don't have an /etc/init.d or /etc/rc.d file for the SSH daemon, you can build one from scratch following the guidelines for Pro-FTPD. The SSH config file (normally located in /etc/ssh or /etc/ssh2) is sshd_config or sshd2_config. An example configuration file looks like the following:

# sshd2_config
# SSH 2.0 Server Configuration File

*:
Port 22
ListenAddress 0.0.0.0
Ciphers AnyStd
# Ciphers AnyCipher
# Ciphers AnyStdCipher
# Ciphers 3des
IdentityFile identification
AuthorizationFile authorization
HostKeyFile hostkey
PublicHostKeyFile hostkey.pub
RandomSeedFile random_seed
ForwardAgent yes
ForwardX11 yes
PasswordGuesses 1
MaxConnections 50
PermitRootLogin no
# AllowedAuthentications publickey,password,hostbased
AllowedAuthentications publickey,password
# RequiredAuthentications publickey,password
ForcePTTYAllocation no
VerboseMode no
PrintMotd yes
CheckMail yes
UserConfigDirectory "%D/.ssh2"
SyslogFacility AUTH
# SyslogFacility LOCAL7
Ssh1Compatibility yes
Sshd1Path /usr/sbin/sshd1
# AllowHosts localhost, foobar.com, friendly.org
# DenyHosts evil.org, aol.com
# AllowSHosts trusted.host.org
# DenySHosts not.quite.trusted.org
# NoDelay yes
KeepAlive yes
RequireReverseMapping yes
/ UserKnownHosts yes
# subsystem definitions
subsystem-sftp sftp-server

Most of these settings you shouldn't have to change from the default. One notable exception is the port that SSH will use. You can change this to any port within the 65535 limit. Also, you might want to change PasswordGuesses from its default (3) to 1. The reason for this is that it deters cracking attempts (the cracker has to make a new connection for each failed password). MaxConnections is a very important setting if this server is going to have any other services on it. MaxConnections helps keep your connections down, so that SSH requests and processes don't take up 90% of the server's resources. However, there is a down side to it- someone can login to your server the amount of times allowed in MaxConnections, then just leave the sessions logged in, which will prevent other users from logging in. PermitRootLogin is also an important setting, *ALWAYS* set this to no (the default is yes). If you need to login as root, simply create a user with a GID of 0 and UID of 0. This is known as a suid root account. Leaving root with the ability to login leaves a small chance that someone may crack root. SSH1 compatibility is crucial, many people have not yet upgraded (or are aware of the upgrade) to SSH2. AllowHosts and DenyHosts really shouldn't be used as a security measure in my opinion. Instead, ipchains or a similar kernel-level firewall should be used instead. However, you may elect to use them, but be warned that when using a application level security measure, exploits in the application can allow denied (or blocked) hosts from connecting anyways. One great thing about SSH is that it comes with the sftp server, which allows encrypting of FTP sessions. Also, no FTP daemons are needed on the server, just the SSH daemon. However, the client must have a SSH package, in order to take advantage of the sftp server.
SSH is an extremely valuable service. It allows encryption of what were traditionally non-traditional services (such as telnet and FTP). This section has only briefly touched on the subject of the SSH server. For more information, read the FAQs and HOW-TOs available at ssh.org.

The Pro-FTPD Server


The most popular FTP servers available today are the ProFTPD and WU-FTPD servers. WU-FTPD is by far one of the most insecure servers, it was written by Washington University. Taking a look at www.wu-ftpd.org gives you an insight as to how many security issues it has. Therefore, I would recommend choosing Pro-FTPD for your FTP server, in that it is more secure, and also more configurable. Those of us who have edited Apache's httpd.conf file will be reminded of it while editing Pro-FTPD's conf file. It uses the same syntax, such as for the global config, for the anonymous FTP config, and so forth. You may download Pro-FTPD from proftpd.org. Installing it is rather easy, and we will concentrate on Pro-FTPD, as opposed to WU-FTPD.
Pro-FTPD contains various download formats including the traditional tarball, rpm, srpm, and bz2. If you run Red Hat, or have a rpm installer on your system, you may wish to just go with the binary package. There is not a real good reason to use the source packages, unless you just like to compile your own source. Also, you may be required to make your own init file, if you decide to go with the source package. To install on a system that supports the rpm packages, simply enter:
rpm -i packagename.rpm
Where of course packagename is the name of the package. If you do not have a rpm installer on your system, then you can download the tarball package and extract it like so:
gunzip packagename.gz
tar -xvf packagename.tar
Now you will have to 'cd' to the directory named packagename, which is something like proftpd-1.2.5 or the like. Thus, the sequence of commands would look like this:
cd packagename
./configure
make
make install

If you get any serious errors, you should either email me and ask for help, or better yet submit a bug report (emailing me will save you some face, whereas the bug report will make your problem visible to the world). Now that you have the package installed, what next? Now, depending on your distribution, you may have to make a special file called an init file that will start the service/restart it. This is really easy, so don't worry. First, try the init file that Pro-FTPD has. This is located in the packagename/contrib/dist/rpm/ directory, under proftpd.init.d. You should copy this to the /etc/init.d directory, and then restart, and test it. To do this:
cp ./contrib/dist/rpm/proftpd.init.d /etc/init.d/proftpd
Upon restarting, you may try to ftp to yourself. Simply enter:
ftp 127.0.0.1
If you get a "Connection Refused", then the particular init script will not work for you. If you get a login prompt, then you are in luck, and should skip this step. If the supplied init file does not work for you, relax, as I have written a sample init file for you, which will work on virtually any system. If it does not work, first type:
rm /etc/init.d/proftpd
Then, change directories to /etc/init.d, and start the Vi editor, like so:
cd /etc/init.d
vi proftpd

Now, press either the 'i' key, or the insert key to begin the editing process. Now, enter in the following script, as you see it.
#!/bin/sh
# Pro-Ftpd init script by Chris Cerberus Pace
# cerberus@armory.com

     case "$1" in
     start)
     echo -n "Starting FTP Daemon: proftpd"
     /usr/local/sbin/proftpd
     echo "."
     ;;
     stop)
     echo -n "Stopping FTP Daemon: proftpd"
     killall -9 proftpd
     echo "."
     ;;
     restart)
     echo -n "Restarting domain name service: named"
     killall -HUP proftpd
     echo "."
     ;;
     force-reload|reload)
     echo -n "Not supported, use restart"
     echo "."
     ;;
     *)
     echo "Usage: /etc/init.d/proftpd {start|stop|restart|reload|force-reload}" >&2
     exit 1
     ;;
     esac
     exit 0

Now then, press the escape key to get out of insert mode, and press the colon key (:), followed by write, and then repeat the colon procedure, only with quit. For instance:
:write
:quit

That should get you up and going. Now then, depending on your distribution, there are several ways that you can tell the OS where the init file is. In Red Hat, you would use the 'ntsysv' utility to start the daemon at boot. In Debian, you would issue the 'update-rc.d' utility, like below:
update-rc.d proftpd defaults
Or, whatever creative name you decided to call the init script. If you have a rather odd distribution, you should pay a visit to the distribution's website, and find out how to do this with your distribution. On a worst-case scenario, you can edit /etc/rc.d/rc.local or /etc/rc.local, depending on where your distribution threw the rc local init file, and enter the following line into it:
/etc/init.d/proftpd start
That will make sure that Pro-FTPD is started upon each and every boot. Now you should restart the server, in order to ensure that Pro-FTPD is started up correctly. Make sure to test it by ftping to yourself:
ftp 127.0.0.1
If Pro-FTPD still refuses to start up, perform a ls of /usr/local/sbin to ensure that proftpd is in there. If not, refer to packagename/INSTALL for other information, where packagename is the directory where you installed Pro-FTPD.
Configuration of Pro-FTPD is similar in respect to Apache, in that it includes directives in the configuration. For the full list of directives, visit http://proftpd.org/docs/directives/linked/by-name.html. The configuration file should be located in /usr/local/etc, with the name of proftpd.conf. You may wish to do what I do, either specify the directory to store proftpd.conf, or easier yet, create a symbolic link, which points to /etc/proftpd.conf in /usr/local/etc/proftpd.conf. To do this, issue the following commands:
cp /usr/local/etc/proftpd.conf /etc
rm /usr/local/etc/proftpd.conf
ln -s /etc/proftpd.conf /usr/local/etc/proftpd.conf

This way, the proftpd.conf file is somewhat organized with the majority of your other conf files, in /etc. To make sure that proftpd is okay with this change, issue the following command:
/etc/init.d/proftpd restart
Thus, to edit the proftpd.conf file, you will simply use your favorite editor to edit /etc/proftpd.conf. With the default settings, Pro-FTPD will work fine. However, you may wish to change the MaxInstances directive to something a little higher, or lower, depending on the load you plan on having Pro-FTPD handle. If you are using it for a FTP server that anyone can use on the Internet (such as anonymous FTP), then set the MaxInstances to something like 100. This allows 100 different connections to be made to the FTP server, before it stops accepting connections. If, however, you only wish for the FTP server to have one or two users, you can sleep safely with setting the MaxInstances at a lower number. If you plan on having Pro-FTPD run from inetd (the Internet super server), you should also change the ServerType directive, and change it to inetd. However, I usually recommend against using inetd for FTP, WEB, SMTP, and related high workload services. Should you choose to use inetd, you will also have to add the following line in your /etc/inetd.conf file:
ftp stream tcp nowait root /usr/local/sbin/proftpd proftpd
It is generally better though to run it as a standalone service. Also, if you are planning on running Pro-FTPD on another port (for instance, to test it out before you switch FTP daemons), you can specify the desired port to use also, by using the Port directive.

The NFS Server


The NFS server is a native Unix and Linux way of sharing filesystems. NFS has better security and performance over Samba, a server for the SMB protocol. This section will cover how to setup both a NFS server, and a NFS server.

NFS Server Setup


NFS server setup is extremely easy. First, you will require the NFS-utils, and possibly another NFS package, depending on how your distribution's nfs packages are set up. After installing the nfs-utils package, and meeting all dependencies upon nfs-utils, you may then proceed to creating the server share. In this example, we will assume that server A wishes to share /important_data with client B. We will also assume that server A wishes to share /not_important_data with all the clients in the network. Client A will have read and write access to the NFS share, and all the clients in the network will have read-only access to their NFS share. We will do this by editing /etc/exports and adding the following:
/important_data      clienta(rw)
/important_data      192.168.0.0/255.255.255.0(ro)

These two shares could actually be written numerous ways, however the more secure way (in my opinion) is to specify the network addresses, as opposed to using * to specify all hosts. Also note that the host clienta must be added to /etc/hosts in order for this to work properly. On the network-readable share, 192.168.0.0 specifies the network, and 255.255.255.0 specifies the netmask that all requesting hosts must have in order to access the share. Once this information has been written, one must make the changes take effect by causing nfsd to read the configuration file again. This is done by issuing the following command:
killall -HUP nfsd
This completes the server setup with NFS. Now, on to the client setup:

NFS Client Setup


NFS client setup will vary according to needs, but most networks will require that the client mount the NFS share upon boot. To perform this, you should add the following line into /etc/fstab for client A:
servera:/important_data      /data_from_server_a      nfs     defaults
And for all clients in the network:
servera:/not_important_data      /data_from_server_a_read_only      nfs      defaults

Please note that the directories /data_from_server_a_read_only and /data_from_server_a must be created prior to attempting to mount a NFS share. Once this has been completed, you may mount the NFS share by specifying the mount point:
mount /nfs_directory
Where of course /nfs_directory is the directory the NFS share will be mounted locally. You may specify "noauto" in /etc/fstab to prevent the system from automatically mounting the share when the system starts up.


NFS Options


NFS offers many more options for the server configuration, such as whether or not to allow root the same permissions of the remote filesystem as root has locally on the server. (insecure), here are a few options:
no_root_squash : This option allows root on a client machine the same power and permissions as root on the remote server. This is insecure, and should not be performed without just cause. If no_root_squash is not specified, the root user of a client is stripped down to the permissions of the user "nobody" on the remote server.
no_subtree_check : Enable this option to speed up transfers in circumstances where an entire device is mounted, if you only mount a portion of a volume, leave this unset, as subtree checking makes sure that the remote file is in the right place on the remote volume.
no_wdelay : This option disables any delay in writing information to disk on the remote server. NFS normally will delay writing a file to be written to disk, awaiting similar commands. In an environment where many files are being written at once, this may decrease performance. Thus, no_wdelay is offered. No_wdelay must be used with sync.
sync : This prevents the NFS server from delaying any pending writing actions once a write request is received. Should the NFS server crash, this is the safest way to write data, as data is written as soon as it is received. However, this incurs a performance hit.
nohide : This options is only to be used in a single client configuration! This prevents a child mount within a parent mount to be hidden from a client. For instance, if /backup and /backup/important are two mounts on a NFS server, normally /backup/important must be mounted in order to write to it. However, if nohide is enabled, /backup/important does not need to be mounted to view it. Once again, only use this option if there is only one client connecting to the server. The hide option is the exact opposite of the nohide option, and is the default.
all_squash : This option is the same as root_squash, but for all users.

Those are the main NFS options to be used. Please remember that /etc/exports is extremely picky with syntax, the below two examples:
/data      host1(ro)
/data      host1 (ro)

are *NOT* the same. NFS is one of the best servers to use for file sharing, and also one of the easiest to maintain and setup. Any system administrator should take a look at NFS, if there is more than one Linux system on their network. Next we will look at a non-native file/printer server, SMB.

The Samba SMB Server

The Samba SMB server is used to connect to a pre-existing Windows NT, 9x, 2000, XP, or DOS network using Microsoft networking clients/servers. With Samba, you can mount shares off of other clients/servers, or you can make your own share on the network. This is vital for most mixed OS environments, because with Samba, you can have a central location for users to get/put files. Also, should you need to grab updates, data, or the like, you can grab files from other shares. Samba's website is located at samba.org. Packages are available in the traditional tarball, RPM, and SRPM. If your system supports the RPM package format, I would recommend using it, as there is little to no advantage to downloading the tarball. You would install the RPM using the rpm command, like this:
rpm -i samba-version.rpm
Where of course "version" designates the version. If you are using a distribution which does not support the RPM format, then you should of course download the tarball. You would then decompress/extract it by issuing the following commands:
gunzip packagename.tar.gz
tar -xvf packagename.tar

Once again, where packagename is the name of the package. Once extracted, change directories to the newly made directory, and then to the source directory beneath it.
cd packagename
cd source

Then, run the standard configure/make commands:
./configure
make
make install

Once all of this is completed, you will then need to verify that the samba distribution has been installed into /usr/local/samba. To do this, type:
ls /usr/local/samba
You should see a directory listing. If not, then the make script may have installed it into /etc/samba. So check there. If it still isn't showing up in the listings, then read the online documentation. Once we have located the distribution, we should now create an init script for it. Init scripts are used at boot to start the services specified, and when you desire to restart or stop a service, you can use the script. Now then, the script should reside in /etc/init.d. If this directory does not exist, consult your distribution documentation. The script should contain the following text, word for word (unless of course you have Samba in a directory other than /usr/local/samba. In that case, substitute what you have for this string.
#!/bin/sh
# Samba init script by Chris Cerberus Pace
case "$1" in
start)
     /usr/local/samba/bin/smbd
;;
stop)
     echo -n "Stopping SMB Daemon: Samba stopped"
     killall -9 smbd
;;
restart)
     echo -n "Restarting SMB Daemon: Samba restarted"
     killall -HUP smbd
;;
force-reload|reload)
     echo -n "Not supported, use restart"
;;
echo "Usage: /etc/init.d/smbd {start|stop|restart}" >&2
exit 1
;;
esac
exit 0

Now that we have this taken care of, we are ready to edit the configuration file. Samba comes with SWAT, A user-friendly interface for Samba. However, with security in mind, I generally recommend against using web-based tools for system configuration. It is a better idea (in my opinion) to just hand edit the configuration file. If, however, you would still like to use SWAT, then add the following line to your /etc/inetd.conf file:
swat      stream      tcp      nowait      root      /usr/local/samba/bin/swat      swat
Also, make sure that /etc/services lists port 901 as SWAT. If not, then add it. You can then restart inetd by using the following command:
killall -HUP inetd
Then, bring up your favorite browser and point the address to 127.0.0.1, port 901, which should be entered like 127.0.0.1:901. For those of us that would rather use the configuration file, you should open /usr/local/samba/lib/smb.conf (also /etc/smb.conf or /etc/samba/smb.conf on some systems). We will now make a sample configuration file:
vi /usr/local/samba/lib/smb.conf

# Global parameters
[global]
workgroup = HNSG
server string = Debian
printcap name = /etc/printcap
load printers = yes
printing = lprng
log file = /var/log/samba/%m.log
socket options = TCP_NODELAY SO_RCVBUF=81922 SO_SNDBUF=8192
netbios name = Debian
security = share # Share definitions
[storage]
comment = Shared Directory
path = /shared
read only = no
guest ok = yes
[4L]
guest ok = yes
comment = HP 4L
printable = yes
path = /var/spool/samba

The global definition is of course a single definition that is true in all shares, etc. The workgroup is your workgroup, which in my case, is HNSG. In this example, the server string is "Debian". This is also known as the description field in Windows networking. The printcap name is only useful if you plan on sharing a printer. In my case, I have a HP 4L that I share, so I want to specify where the printcap is. In 90% of the cases, you can leave /etc/printcap as it is. The load printers setting allows you to specify whether or not if you want to load the printers automatically. The printing setting should also be left as-is. This specifies which program Samba should use to write to the printer, which is in most cases lpr. The log file setting allows you to specify the log file used, in this case I use the %m variable, which stands for the machine connecting. The socket options setting should also be left alone, this setting is for speed purposes. The netbios name is what the server will appear to be on the network. The security setting has 3 different possible values: user, share, and server. The user setting should only be used if a windows user has an account on the server, and they both have the same passwords. The share setting allows the user to specify a password, but it does not require the Samba server to have the same password. The server uses another SMB server to do all authentication. Here, I use share, because this is a trusted environment, and I do not have an account on the server for every user.
Now begins the share definitions. The share is enclosed in brackets, just like the global definition. Comment is not really needed, the share definition (name in brackets) will be displayed. The path setting specifies which path to use for this directory. The read only setting specifies whether or not to restrict all access to read only. Because I want everyone to write to the shared directory, I disabled this. Finally, we have the guest ok setting, which allows anyone to access the share. This is important, because I want anyone on the LAN to be able to write to this directory.
Now we have the definition for the laser printer, the HP 4L. Again, guest ok makes sure that anyone can use this printer. The comment field, again, is pretty much useless, but it keeps things sane (when you have 100 or so definitions, it can get crazy). We of course want the printable setting enabled. The path setting is just a directory where queued print jobs will reside until they are completed. One thing to make sure when using Samba with guest ok=yes, is that wherever the directory is, it should be world readable, and probably writable. You can set this by using the chmod command:
chmod 777 /path/to/share
Now we will test the Samba configuration:
testparm
If this doesn't work, then precede testparm with /usr/local/samba/bin. You actually might want to put this in your path, to do so, enter the following:
export PATH=$PATH:/usr/local/samba/bin
This runs the utility that comes with Samba, which will test the configuration for any errors. After this is completed:
killall -HUP smbd
Which will restart the Samba server. Now, jog over to a Windows or SMB-enabled system and view the network. You should be able to see your server, if not, make sure that you didn't make any typos. If you are still unable to view your server, wait 10 minutes. Sometimes Windows takes a while to refresh the list of SMB clients. If after 10 minutes, you are still unable to view your server, issue the following commands:
ps -waux | grep "nmbd"
If you do not see any output: nmbd
Again, if nmbd does not work for you, try /usr/local/samba/bin/nmbd. If, after again waiting 10 minutes, or if you see a process called nmbd in the ps output, re-check the configuration file, and make sure that the security setting is correct for your network. If you are still unable to connect, try using the smbclient program, which is designed to enable you to browse shares as if they are FTP servers:
smbclient //127.0.0.1/sharename
Where sharename is the name of a share to test. If you are still unable to access your Samba server, make sure that Samba is running issuing the following commands:
ps -waux | grep "smbd"
If you do not see any output: smbd
Once again, you may have to enter /usr/local/samba/bin/smbd if it is not in your path. Make sure that you are running all of these commands as root, of course. If you are *still* unable to view the Samba share, run:
netstat -a | grep "139"
If you see output, then your server has opened the port correctly. Again, wait 10 minutes. Some NT servers have been known to take up to 45 minutes to refresh. If you are still unable to connect, either from your server, or a client, then read the Samba Project Documentation available at: http://us1.samba.org/samba/docs/man/Samba-HOWTO-Collection.html. This should solve your problem. Make sure though before you do all this, to flush all ipchains rules. Ipchains is a firewall, and while flushing them isn't recommended for a long-term use, you can flush them to test Samba. To do this, enter:
/sbin/ipchains -F
Also, you can mount SMB shares using the 'smbmount' command. For instance, let's say that I have a client named ralf1 on my network. I would first make a directory to store the mount in:
mkdir /shares
mkdir /shares/ralf

Then, I would specify the share name in which I desire to mount, followed by the directory I want the SMB share mounted in:
smbmount //ralf1/shared /shares/ralf
You can add this to your /etc/rc.d/rc.local, or /etc/rc.local file, which is processed at startup. Also, there is an EXTREMELY useful utility for DHCP networks, the nmblookup utility. This fine utility will tell you the IP address of a host. For instance, if I desired to know the IP address of ralf1, I would issue the following command:
nmblookup ralf1
The nmblookup utility will then report back to me the IP address of ralf1. This is useful if ralf1 has a telnet server running on it for troubleshooting purposes, and if ralf1 has enabled DHCP for its IP address.
Samba is an excellent server, and in most cases, it will work flawlessly. Incidentally, in a test done by PC Magazine, Samba outperformed Windows 2000 servers by 100%. Here is the original article.

Assorted Servers and Services


This is mostly a collection of some miscellaneous services, and the servers that run them. These services and servers offer some interesting, and very useful features.

Talkd
Talkd is a service which allows two users to talk in a real-time "chat" interface. Talkd should be downloaded from your distribution's packages. Talkd is enabled in either /etc/inetd.conf, or /etc/xinetd.d/talkd. To talk to a user, the user must first run:
mesg y
This enables talkd to communicate to the user. Note that only the receiving party must run this command.


Fingerd
Fingerd allows a remote user to "finger", or retrieve important information, local or remote users of a shell server. For instance, this is the output of fingering myself on my home system:
root@hnsg:/etc# finger cerberus
Login: cerberus      Name: Chris
Directory: /home/cerberus        Shell: /bin/bash
On since Sun Aug 25 23:39 (MDT) on tty1 7 hours 1 minute idle (messages off)
On since Sun Aug 25 23:40 (MDT) on tty2 7 hours idle (messages off)
On since Sun Aug 25 23:40 (MDT) on tty3 6 hours 58 minutes idle (messages off)
On since Mon Aug 26 04:51 (MDT) on pts/0 from 192.168.0.4
On since Mon Aug 26 04:52 (MDT) on pts/1 from 192.168.0.4
No mail.
No Plan.

As you can see, this gives a great deal of information out about a user, which can be useful, for instance if someone wanted to know whether or not I was at the desk, this output would tell them that I am not physically at the system, but I am logged in remotely, from 192.168.0.4, which is on the local LAN. Therefore, they could thus determine that I am in the building.
With fingerd, there is a lot of information released that may be of potential interest to attackers, so choosing whether or not to implement this may be a obstacle. Please note that fingerd *DOES NOT* have to be running in order for LOCAL users to finger each other on the same server, fingerd only has to be installed for remote users to finger local users. Fingerd should be downloaded from your distribution's website, and enabled in either /etc/inetd.conf, or /etc/xinetd.d/fingerd. Also, by simply issuing the 'finger' command alone, one can view all logged in users:
root@debian:/etc# finger
Login       Name       Tty      Idle  Login Time   Office     Office Phone
cerberus  Chris     *tty1     7:09  Aug 25 23:39
cerberus  Chris     *tty2     7:08  Aug 25 23:40
cerberus  Chris     *tty3     7:07  Aug 25 23:40
cerberus  Chris     *pts/0       4  Aug 26 04:51 (192.168.0.4)
cerberus  Chris      pts/1           Aug 26 04:52 (192.168.0.4)



Daytime
Daytime is a primitive, and limited service that only displays the server's internal clock time. This can, however, be useful for time clocks, and the like. Most of the time, Daytime is incorporated into a set of scripts that perform a given task using Daytime. Daytime is enabled by downloading the daytime package from your distribution's site, and then enabling it in either /etc/inetd.conf or /etc/xinetd.d/daytime.


POP3 via Qpopper
Qpopper, a popular POP3 server, allows users to connect remotely to a server, and retrieve their mail via the POP3 protocol. Qpopper is usually ran as an inetd or xinetd service. Qpopper can be obtained from Qualcomm's FTP site at: ftp://ftp.qualcomm.com/eudora/servers/unix/popper/. Qpopper is an extremely secure and fast POP3 server, any administrator who is looking for a POP3 server should DEFINITELY check it out.


Telnetd
Telnetd allows a remote machine to connect to a server to establish a login, much in the same way that SSH works, however it is less secure. Telnetd does not allow any encryption. Telnetd can be installed by downloading the server from your distribution's website, and then enabled by editing /etc/inetd.conf or /etc/xinetd.d/telnetd. Telnet, the client used to access a telnetd server, is available with almost every OS nowadays, which has a significant advantage over SSH.

Securing Your Linux System


There are essentially three steps to securing a system. The first step is disabling any unnecessary services. The second step is to configure the services as appropriate. The third step is to keep updating the services, and the kernel, when new exploits are developed. We will cover the first step now.

Disabling any unnecessary services


To disable any unnecessary services, you should edit either /etc/inetd.conf, or you should edit the scripts within the /etc/xinetd.d directory. This is extremely easy. First, you should get an idea of exactly what services you do and do not need running. Examples of needed services may be the SSH daemon, the HTTP daemon, or the FTP daemon. Examples of unnecessary services may be the telnet daemon, the echo daemon, or the talk daemon. In order to find out exactly what services are currently running on your system, I would recommend using a portscanner. Some experts may disagree, and instead suggest you use 'netstat -a' to find out, but I believe that portscanning is needed in the end in any event, to give you an idea of what exactly the outside is seeing on your network. The best portscanner (in my opinion), is by far nmap. This portscanner allows not only the vanilla tcp connect() scans, but also SYN stealth scans, Stealth FIN, X-mas, null, ping, any many other types of scans. The nmap portscanner can be downloaded from http://www.insecure.org/nmap. Once you have downloaded the source (rpm packages are available as well), you can install nmap by issuing the following commands:
tar -xvf nmap-version.tar.gz
gunzip nmap-version.gz
cd nmap-version
./configure
make
make install

You can invoke nmap by issuing the following command, which will begin the portscan to see what ports you have open:
nmap 127.0.0.1
When nmap is finished, you should see something similar to the following:
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on (192.168.0.15):
(The 1598 ports scanned but not shown below are in state: closed)
Port State Service
21/tcp open ftp
23/tcp open telnet

Nmap run completed -- 1 IP address (1 host up) scanned in 1 second

This will then tell you what services you have running (allowing connections). Therefore, according to this output, my server has two services running, telnet and ftp. Once you have your list of services that you find are not needed, you may edit /etc/inetd.conf, or /etc/xinetd.d/servicename, for instance, if I wanted to remove the telnet service from xinetd, I would edit /etc/xinetd.d/telnet:
# default: on
# description: The telnet server serves telnet sessions; it uses \
# unencrypted username/password pairs for authentication.
service telnet
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.telnetd
log_on_failure += USERID
}
Then, I would change the sixth line from the top, from disable = no, to disable = yes. This would disable the telnet service from starting from within xinetd. If, however, my system used inetd, I would edit /etc/inetd.conf:

#
#
#:INTERNAL: Internal services
#echo stream tcp nowait root internal
#echo dgram udp wait root internal
#chargen stream tcp nowait root internal
#chargen dgram udp wait root internal
#discard stream tcp nowait root internal
#discard dgram udp wait root internal
#daytime stream tcp nowait nobody internal
#daytime dgram udp wait root internal
#time stream tcp nowait root internal
#time dgram udp wait root internal
#:STANDARD: These are standard services.
telnet stream tcp nowait telnetd.telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd

Then, I would comment out line 15, by placing a '#' in front of the line. This mark is called a hash mark, and is used in the Linux/Unix world for commenting configuration files, shell scripts, and the like.
Once you are finished editing /etc/inetd.conf or the /etc/xinetd.d directory, you should restart the inetd or xinetd service, which can be done by issuing the following command:
killall -HUP xinetd OR inetd Then, you should re-run nmap, in order to assure that all services that are not needed are taken care of. Some services, such as the Apache web server, Pro-FTPD, and Sendmail are not run via xinetd, or inetd. There is an easy way (the method I prefer) to disable these services. For each of these services, there is either a startup file in /etc/init.d, or /etc/rc.d that starts the appropriate service. If you 'chmod 000' the init file, and then kill the process, the server will be halted, and will not be again started if the server restarts. For instance, if I was running the Pro-FTPD FTP server, I would issue the following commands to stop the server, and prevent startup of the server again:
chmod 000 /etc/init.d/proftpd
killall -9 proftpd

Once this has been performed for any other services, run nmap once more time to ensure that the services are indeed stopped. The next step in securing a Linux system is to configure the running services.

Configuring the running services


Configuring all running services is extremely important. For instance, in many organizations, a web proxy is used so that clients inside the LAN may have Internet access. However, having the proxy open to where outside hosts may connect is unnecessary, and a security risk. Therefore, the proxy must be configured to only allow access from hosts inside the LAN (on a given IP subnet, such as 192.168.0.1 through 192.168.0.255). To perform this action, there are several ways in which to do this. One of these methods is to enter a rule into hosts.allow and hosts.deny which state the following:
/etc/hosts.allow
in.telnetd: 192.168.0.
/etc/hosts.deny
in.telnetd: ALL
Again, to recap, these rules will allow any connections from the 192.168.0.x network, and disallow any connections from any other networks. The in.telnetd part of the line is the service name, which is telnetd (without the in) on systems that do not run tcp wrappers. You can write these rules for any service. That being said, there are several vulnerabilities within using tcp wrappers, one of which is a vulnerability in the event of a kernel exploit. Sometimes, certain parts of the Linux kernel will become vulnerable to exploits. Since tcp wrappers is a high-level configuration, the kernel is vulnerable. Therefore, I recommend using ipchains, or another packet filter to write security rules. Using ipchains is fairly easy, here is how we would re-write those rules, to allow and dis-allow telnet connections:
To allow:
ipchains -A input -j ALLOW -p tcp -d 192.168.0 telnet
To deny:
ipchains -A input -j DENY -p tcp -d telnet
You should repeat these two steps for each and every service that is not required to accept connections from the outside.

Updating the kernel and system services


Updating the kernel and services on a Linux server can be tiring work, but it does not have to be. For those of you that run either Mandrake, Debian, Red Hat, or SuSE, updating services and the kernel is extremely easy. These distributions come with client programs which enable you to download updates with little or no intervention. However, if you run another distribution, life is more difficult for you, as you have to be even more vigilant over your network. New vulnerabilities and exploits are released daily, so you should check for updates by using Yast2 (SuSE), Up2date (Red Hat), or Apt (Debian). One policy that I follow is to immediately subscribe to the security announcements list of every distribution, as well as the security announcements list of every major system service. These can be found by searching your distribution's website, and the websites of the services you run. If you decide that SuSE, Red Hat, Debian, or Mandrake are not desirable, you should subscribe to the security announcement lists of every system service you run. This is painstaking, because some distributions (such as Slackware) are slow to release binary packages of new versions of software. Therefore, you may be required to build from source on many occasions. There is nothing outright wrong with building from source, but using a package manager makes keeping track of installed software easier, and faster than building from source. Also, in most circumstances, binaries from distributions have been thoroughly tested with which compile-time switches to use. In addition, the default installation path on most binaries are organized better than the source versions (which by all means can be changed).
If you run Red Hat, you must first register with the Red Hat Network if you desire to use up2date to retrieve packages. To do this, you may run the following command:
rhn_register
Once registration is complete, you may invoke up2date by using the following syntax:
up2date -u upgrade
If you are using Debian, you can use apt-get to update the lists of available packages, and to download them and install them. To do this, edit /etc/apt/sources.list and add the following line:
deb http://security.debian.org/stable/updates main
You may then update the Apt list by executing:
apt-get -u update
Then, you may download and install the applicable updates by executing:
apt-get -u upgrade

This article has merely touched on security in the Linux environment, but should have sufficient information to allow most sites to secure their Linux servers and clients properly. For more information on Linux security, you may read Unix Security, a tutorial that I previously wrote specifically for this topic, and also Unix Security from the Black-Hat View, a tutorial that describes how "hackers" determine vulnerabilities within your network, and how to view your network through the eyes of a black-hat "hacker".

Customizing Your Linux Kernel

One of the best ways to customize your Linux system is by customizing the kernel. Nowadays, this is extremely easy, all you have to do is answer some questions, and run a few commands. First, you should obtain the official kernel source from kernel.org. The reason for this is that sometimes individual distributions (Mandrake is really bad with this) will alter the source code to the kernel when they distribute it. 99.9% of the time, they don't add any new features, they just basically change a few defaults, etc. What this also means is that the kernel may or may not work with an individual author's pre-compiled binary. Thus, you should get your kernel from the official page. Also, most distributions run about 3 weeks or more behind the official version.
Why should you upgrade your kernel? There are four main reasons. The first, and most important, is that often there are security problems with the Linux kernel, which means that if you do not upgrade your kernel (and rather fast at that), your server could get "rooted", or cracked/hacked into. The second reason, and possibly equally important, is if you have hardware that, with your current kernel, doesn't work completely or at all. The third reason is for bug fixes that you need (i.e. an experimental kernel feature has finally matured). The last, and least important, is that when you upgrade your kernel, you also custom compile it, which makes the server run faster. If you don't have any of these reasons for upgrading your kernel, don't bother. Before planning to upgrade the kernel, you should know your hardware in the server or workstation that you are using, as you will be selecting which hardware to include support for. You should download the Linux kernel and copy it to /usr/src (this is tradition, plus it is handy if you need to re-compile it again to add support for a new piece of hardware). You should then extract it (assuming you have the .tar.gz package) by using the following commands:
gunzip linux-version.tar.gz
tar -xvf linux-version.tar
Make sure to replace version with the version number. Once the source is extracted, you should use the make utility to specify options you want enabled in your kernel. There are three different ways to do this:
make config   Simple text-only list of questions, which is impossible to start over from the beginning if you mess up.
make menuconfig   Text-based menu for selecting options needed quickly and accurately.
make xconfig   GUI-based menu for selecting options needed.
I would recommend using menuconfig (requires Ncurses). The reason that I think menuconfig is better is due to the fact that under most circumstances, GUI on a server doesn't exist, and that config is a little too verbose and long for the beginner. However, since menuconfig requires Ncurses (which may not be available on your system), I will walk you through the vanilla make config. Make menuconfig, and make xconfig are very similar, the only differences between these three are the interfaces. Thus, we will begin by entering:
make config
The first option asks you to prompt for development/incomplete drivers. You can safely say no here. The next option (I am using this tutorial for 2.4.19, so there may be a few differences by the time you read this tutorial) asks you if you wish to enable Pluggable Module Support. This is a must, so select Y here. The next prompt asks if you wish to set version information on kernel modules, select Y here. The next prompt asks if you wish to enable loadable module support, select Y here. If at any time you wish to know more about an option, you may enter I or any other character (besides N,Y, or M) to see the description for this feature. The next prompt asks which CPU your system uses. Since my server in question is a Pentium 200 MMX, I will enter Pentium-MMX as the descriptor. Make sure that you select the correct processor, in most circumstances, the kernel will *NOT* work with a different processor other than what is specified. If you are unsure, you may enter 386, and it will work on all x86-based processors. The next option, Machine Check Exception, is an early-warning system that detects heating problems, etc. If you have Machine Check Exception on your motherboard, by all means say Y here. Toshiba laptop support is in most circumstances not needed, unless of course you are installing the kernel on a Toshiba laptop, so say N at the Toshiba laptop support option. The same goes for Dell. The next option, enabling Intel IA32 CPU microcode support, is not needed in most circumstances, and must be used with a special driver (enter I for details). The next option, Model-specific register support, should be enabled on SMP-machines only. The next option, CPU information support, is also not needed on most systems, so say N here. The next option, high memory support, allows you to specify the limit you want the server to recognize pertaining to RAM. The default, off, is fine for most systems, but if you have a really high amount of RAM, you may wish to select the 4GB or 64GB limit. The next option, Math emulation, is only useful on systems that are older, and do not have a Math co-processor built into the CPU. Say N here unless you have a 386 or 486 that doesn't have a math co-processor. The next option, Memory Type Range Register support, is only useful if this server or workstation is planning on, or is currently running the X-Windows system, and is using either an AGP or PCI bus. I do not run X-Windows on a server, so I will select N here. The next option, SMP support, is only useful if you run multiple processors on your system. Most people will select N here. The APIC support option is useful if you have a processor with a local APIC. If you have no clue what this is, select N here. The next option, Networking support, is rather a redundant question if you ask me, who would want to disable networking on a Linux system? Select Y here. The next option, PCI support, is also rather a no-brainer, unless your system has no PCI cards in it. Select N or Y here. If you enabled PCI support, the access mode should be Any, and you should enable the PCI device name database.
EISA support under most circumstances, should be set to N, unless you have EISA slots on your system. The next option, MCA support, is also rather easy. If you have MCA slots on your system, select Y, otherwise select N. Hotplug support is very useful if you use USB, PCMCIA, or other hot-pluggable devices. Select Y or N here. The next question, System V IPC, is essential under most circumstances, select Y here. BSD Process Accounting, allows details such as creation time, owning user, memory usage, etc to be written after a process exits. Most systems will not require this, so you may safely select N here. Sysctl support is in my opinion essential, unless you are limited in memory, as it adds 8 KB to the kernel. The next option, Kernel core support, should be ELF. For backwards compatibility, you will also want to add support for the a.out binaries, in addition to ELF. Support for MISC binaries can be made into a module, so select M here. Power Management support allows the computer to go to sleep, and other useless tasks (unless you are using a laptop). Select N here unless you use a laptop.
Memory Technology Device support is useful only if you plan on accessing flash RAM, or similar devices. If you do plan on including support, make it a module. Parallel Support is a trivial question. If you want to use your Parallel port, select M here, and to the following questions. Plug and Play support, the next option, is useful in most circumstances. If you have P-n-P hardware, select M. Then, select M if your P-n-P hardware is ISA. The next option, Normal PC floppy disk support, is needed in most circumstances. Select M here. The next option, XT hard disk support, is only useful if you use an older XT hard drive. Select M or N here. The next option, SMART2 support, is useful only if you plan on using a Compaq Smart Array controller. The next option, Loopback device support, is not required. Select N here, and to network block device support. The next option, RAM disk support, I would recommend if you are using a high volume web server, or similar server, that retrieves the same files 90% of the time. This allows you to allocate RAM space to use as a filesystem. I recommend this in the above situation, because RAM is faster than a hard drive, no matter what kind ;). The next prompt, if you selected to enable RAM disks, requests the default RAM disk size. The size must be inputted in bytes, usually 10000 (or approximately. 10 MB) is enough. The next option, Multiple devices driver support, is for only RAID and LVM devices. Select Y if you use either of these devices, N if you don't. The next option, the Packet Socket, shouldn't be an option, select Y here. On the next question (if you selected Y), you should select Y to mmapped IO, as it results in faster communication. The next option, Netlink device emulation, is not needed, ans will soon be removed from the next versions of the Linux kernel. I recommend that you select N here. The next option, Network packet filtering, I would *HIGHLY* recommend that you select Y, as it enables the Linux system to perform packet filtering (as in a firewall). The debugging feature of network packet filtering, isn't required, or really recommended, but the choice is of course yours. The next option, Socket Filtering, isn't required or really needed, so select N here. The next option, Unix domain sockets, should be enabled, so enter either M or Y here. The next option, TCP/IP networking, is a must, select Y here. The next few options, multicasting and advanced router, are useful only if you are making this system a router. Kernel level autoconfiguration is not necessary. Also, tunneling and GRE tunnels over IP is also not necessary. TCP Explicit Congestion Notification support, is however useful, so you might want to enable that option. Simply put, TCP Explicit Congestion Notification allows the system to notify you when your bandwidth is getting seriously crunched. TCP syncookie support is also extremely useful, in that it allows protection against some TCP SYN attacks, enter I to read more about it, and how to enable it.
Connection Tracking is essential if you want to use this system to masquerade connections, and for use as a router. Enter M here or Y if you need this, and also to IP tables support. IP chains support is *HIGHLY* recommended, as it allows backwards compatibility to the kernel, in that ipchains (2.2 kernels used this as a packet filter) can use the new kernel. Ipfwadm support is not recommended, this is a highly obsolete packet filter. The next option, 802.1Q VLAN support, is only needed if you wish to create a 802.1Q VLAN interface, press I to view more information on this. The next option, the IPX protocol, is not needed in the Linux environment, as it is a Netware protocol. However, if you need it on your network, select Y here. The next option, Appletalk, is designed to where Linux clients/servers can communicate effectively with Appletalk clients/servers. The same goes with DECnet Support, as it is a Compaq protocol. The next option, 802.1d Ethernet Bridging, is mostly only useful for a router, where you would want to create an ethernet bridge across multiple devices. Select Y, M, or N here, as appropriate. The next option, QoS queuing, allows the kernel to decide which packets going outbound are of the most importance, and should be sent first, etc. This option requires a client utility as well, select Y or N here, as appropriate.
The packet generator is useful only in extreme network debugging and analysis, you should say N, Y, or M here, as appropriate. Press I to view the details. The next option, Linux telephony support, is in most circumstances not needed, as this pertains to a telephony card (*NOT* a modem). The next option, ATA/IDE/MFM/RLL support, is needed in most circumstances, so select M here *UNLESS* you have 100% SCSI hardware, and no IDE hardware, then you may select N. The next option, Enchanced IDE support, should be enabled, so enter M here, unless you are again using 100% SCSI hardware. The next option, Use old disk-only driver on primary interface, is not recommended, as you are not allowed to have an IDE CD-ROM on the primary controller with this option. However, if you are using ancient hardware, select Y here. The next option, Include IDE/ATA-2 Disk support, should be made a module, so enter M here. The next few options will allow you to select tape IDE drive support, as well as CD-ROM and floppy support, select Y,M,and N here as applicable. The next section will allow you to use special chipset fixes (for bugs) present on certain chipsets. Pay attention to these, but in most circumstances, the chipset fixes are not needed. The next section pertains to SCSI support, specify here if you want to enable it, and in the following sections, the logging facility you desire to use, and the drivers you desire to use for your hardware. The next section pertains to Network device support, enable this. The following sections will enable certain drivers to be used, and protocols to be used for the network. Answer these questions as they pertain to you, press I if you are unsure about an option.
After the networking section, you are asked if you wish to support non-SCSI/ATA/IDE CD-ROM drives. Most of the time, you will say N here, but you may require this feature if your CD-ROM drive is, for instance, connected to the CD-ROM interface on your soundcard. The next option, Input Core Support, is for USB-based Human Interface Devices, which you will likely not need. The next option, Virtual Terminal, is essential, so select Y here, and for Support for console on virtual terminal. The next option, Standard/generic (8250/16550 and compatible UARTs) serial support, is not needed in most circumstances, unless you have a serial device. The next option allows support of Non-standard serial ports, select Y here if you need this support. The next option, Unix98 PTY Support, is essential, enter Y here. The next option, Maximum number of Unix98 PTYs in use, is a very useful option. This allows X amount of users to connect to your server (as in a login session). You can specify anywhere from 0-2048 here, choose a number that you feel is necessary. I2C support, the next option, is a serial bus protocol developed by Phillips. Unless you need this option, select N here. The next section will present you with options on mice, select the proper mouse interface for your system here. The next option, QIC-02 tape support, is for non-SCSI tape drives that require this. The next section, Watchdog Cards, allows, via a special hardware card installed in the system, to monitor hardware temperature, etc. Select Y here if you have this hardware, or N here if you don't. If you have a floppy tape device, then select Y at the Ftape option, otherwise select N here. The next option, AGP Support, is useful only if you have an AGP card, and wish to use the X-Windows system. Also, you should enable Direct Rendering Manager.
The next option allows you to select ACP Modem support, which is a Winmodem. If you have this modem, select Y here. The next section is on multimedia devices, such as Video for Linux (allows you to use a webcam and the like). Answer these questions as applicable. The next section is on File Systems, select which file systems (definitely the ext2 file system, as well as the ext3 file system) you need support of. Also, you should enable the /proc file system, as well as /dev/pts file system (for Unix98 PTYs). The next option (after all of the file system options) is to allow the standard VGA text console. Select Y here on 99.9% of all circumstances. However, the next option, Video mode selection support, is not needed. The next section is on sound card support/drives, select the appropriate driver if you wish to enable sound. The next section is for USB support, enable this if you need USB support on your system. The next option is for Bluetooth subsystem support, you probably do not need this. The last section is on Kernel hacking, you probably also do not need this.
Congratulations, you're done with the configuration! The next phase is a rather simple one, although a rather long one on slower systems. As root, issue the following commands:
make dep
make clean
make modules
make modules_install
make bzImage
Alternatively, you may specify all the make targets on one line, as this:
make dep clean modules modules_install bzImage
These commands compile the Linux kernel, make sure that all dependencies are met, etc, then create a compressed kernel image (the kernel decompresses itself at boot). Once the kernel has been created, you should edit your /etc/lilo.conf file to include the new kernel. A sample /etc/lilo.conf file might look similar the the following:

root=/dev/hda3
default=Linux
image=/boot/vmlinuz
label=Linux
read-only

This file must be modified to allow the new kernel to boot. Place the following line s in your /etc/lilo.conf file:

image=/usr/src/linux/arch/i386/boot/bzImage
label=new
read-only
If you extracted the source in a directory other than /usr/src, modify this so that it matches. Also, if your directory is not named linux that the source resides in, modify this as well. If you have an architecture other than i386, specify it at the i386 part. Now, we will save these lines, and run lilo as below:
/sbin/lilo -v
/sbin/lilo -R new
This will tell lilo to perform two actions, the first being to update the boot sector, and the second being to enable the system to automatically boot into the label 'new', for one time only. This is useful for remote upgrades, and when you are just too lazy to walk to the end of the room and select the proper label at boot. Once this has all been done, you are ready to test out the kernel. Use the following command to restart your system:
shutdown -r now
This will cleanly restart the system, and load the new kernel. If some piece of hardware doesn't work, go back through the configuration stages, and the make stages, you may leave the lilo configuration file as-is until you are 100% sure that all of your hardware is working. To make the new kernel the default, go back into the source directory for the kernel, and type one last make command:
make install
Once this is complete, your new linux kernel will be fully installed, and you can remove the 'new' section in your configuration file, or simply leave it for future upgrades. Compiling and installing the Linux kernel is probably one of the hardest tasks to perform, and it is also one of the most rewarding (for speed and security) tasks. You can subscribe to the Linux kernel mailing list by following the directions at: http://kernel.org/pub/linux/docs/lkml/.

Appendix A: Common Linux Commands


Listed below is an essential reference to some of the more common Linux commands. These commands are, in my opinion, absolutely necessary:


/bin:

chmod: Change file attributes, accepts numeric or character strings.
chown: Changes file ownership, to owner:group.
cp: Copies files.
date: Displays system date.
dd: Makes images and writes images, very useful when making boot floppies, or entire backups of a filesystem.
df: Shows difference between files.
egrep: Similar to grep, in the exception that it searches for case-sensitive strings, and is faster than grep.
grep: Searches for strings, is not case-sensitive.
gunzip: Used to decompress .gz files.
gzip: Used to create .gz files.
hostname: Displays the system's hostname (i.e. localhost).
kill: Used to kill a stray process, or a process that is hanging up. The pid is required.
killall: Kills all instances of a process, by name. Pid is not required, as it kills all processes that match a string.
ls: Lists files in a given directory.
lspci: Useful to probe hardware, displays all card IDs on the PCI bus.
mkdir: Creates a given directory.
more: Used to view files or output longer than a screenful of output.
mount: Used to mount filesystems, remote and local.
mv: Used to move files.
netstat: Used to display all connections to a system, including listening connections.
ping: Used to determine if a host is up, among other uses.
ps: Displays system processes.
pwd: Displays working directory (directory you are currently in).
rm: Removes files.
rmdir: Removes directories.
sleep: Tells the system to "sleep", or idle for x amount of minutes or seconds.
su: Used to switch users, default is root.
tar: Used to create a tar archive.
touch: Creates an empty file.
umount: Used to unmount a previously mounted directory or device.


/sbin:

fdisk: Used to create/destroy partitions.
halt: Quick way to halt the system.
ifconfig: Shows all network interfaces, and their current configuration.
ifup/ifdown: Used to bring interfaces up or down.
insmod: Used to insert a kernel module.
ipchains: Packet-filtering firewall.
lilo: Used to update the Linux Loader boot record.
mkfs: Used to create a file system on a partition.
mkswap: Used to create a swap file system on a partition.
route: Displays network packet route.
start-stop-daemon: Used to start or stop a daemon, this is mostly used in /etc/init.d and /etc/rc.d scripts.


/usr/sbin:

addgroup/adduser: Creates group or user.
delgroup/deluser: Deletes group or user.


For more information about these commands, enter:
man command
Remember that these directories specified may vary from distribution to distribution, and may also not be in your system path. You can add them using the following command (using the BASH shell):
export PATH=$PATH:/usr/sbin:/sbin

Appendix B: Continued Reading


Below is a list of resources that, in my opinion, any serious administrator should read.

Security in the Unix Environment : A tutorial on how to properly secure a Unix/Linux system.
A Black-Hat Guide to Unix and Linuux : A tutorial on the basics of what Black-Hat "hackers" will do when elusively portscanning your servers/networks.
openssh.org : This site has a great deal of information on Open SSH, including tutorials, specifications, and security announcements.
apache.org : This site had tutorials, security announcements, and much more for the Apache Web Server.
samba.org : This site includes tutorials, and more on the Samba SMB server.
nfs.sourceforge.net : This site includes client, server, and troubleshooting tutorials for the NFS server.