Ubuntu Linux comes very well configured and secured out of the box, but you can almost always make a car run a little bit faster. Likewise, we can usually find ways to tweak a server to our liking.
In the last installment of this series, Installing Linux, we installed all necessary components of Ubuntu Linux. Now we can proceed with configuring and securing this Ubuntu installation. We'll discuss the steps in this tip.
Because the Ubuntu Server Install CD will probably not always be sitting in the server's CD-ROM drive, we need to tell Ubuntu to look elsewhere for subsequent updates. (The CD will not contain the latest packages from Ubuntu anyway.) To remove the CD media from the update sequence, we will have to comment out its entry in the file sources.list. Type:
sudo vi /etc/apt/sources.list
Find any entry line that begins with "deb cdrom" and comment out the line by prefixing the line with a "#" (pound) character. At this point, you must decide whether or not you will be pulling updates for this server from the main Ubuntu mirrors or a local apt repository. If you need to further edit the file to point to a local apt repository, do so now.
Save the file and exit the editor.
Now let's take a look at the networking settings you'll want to configure.
If you have additional NICs in your server, it is time to configure them. To do this, we will have to edit the file /etc/network/interfaces.
sudo vi /etc/network/interfaces
Before we modify the file, it should resemble this:
The stanza that starts with "auto eth2" and ends with "dns-nameservers" should be copied in its entirety. Yours may not read eth2; if it doesn't, it will most likely be eth0 or eth1. Regardless, once the stanza is copied and pasted beneath (or above) the existing one, we need to make some changes to the copy.
The copy still says "eth2". Wherever it says "eth2" in the copy, you should change this to be one of the NIC IDs that you wrote down during the server installation. For example, in the following screenshot I changed the copied "eth2" to "eth0".
If you notice, I also changed the comment above the original stanza from "The primary network interface" to "The management network interface". I also changed the comment on the copy to "The VMs network interface".
You should repeat the process of copying the original stanza for each NIC the server has. The number of NICs the server has (or at least has drivers for) is the same number of NIC IDs that you recorded in the installation. All additional NICs will be dedicated to the VMs, so when you make copies, you can change their comments to "The VMs network interface" as well. Only the original NIC will be dedicated to managing the server and VMware; the rest of the NICs will be dedicated to the VMs themselves.
Once all the NICs are configured, save and exit the file. To verify that the changes we made are correct, restart networking on the server by typing:
sudo /etc/init.d/networking restart
This command may take a long time since you should not have any network cables connected. If you do not receive any errors, then everything is okay. If you do receive errors, you should go back and check the file to see if you mistyped anything. If you cannot figure out what is wrong, you may always e-mail me at akutz at lostcreations dot com.
We need to modify the /etc/hosts file so the server has a fully qualified domain name. Edit the hosts file by typing:
Your hosts file will look similar to the following screenshot:
The difference between your hosts file and mine is that I have already added a FQDN for my server. To do this, look at the second line in my file. Before the host name, "vms02", I added the FQDN of the server, "vms02.lostcreations.com". Add your server's FQDN to the file, and save and exit the file.
You can confirm that your server has a FQDN by typing the following in the console:
This will return you server's FQDN.
If you have access to a dedicated syslog server, go ahead and instruct this server to send all of its log entries of debug level to that server. We do this by editing the file0 /etc/syslog.conf:
sudo vi /etc/syslog.conf
Add this line anywhere in the file:
Save the file and exit. Now all debug entries will get shuttled to the syslog server, in case you need to diagnose a problem with this server and cannot log into it.
Ubuntu Server ships with a number of services that a VMware server does not need. If the server will not be using a service, then that service does not need to be started at boot. Two of the services that I disable are alsa-utils and pcmciautils. You may find others that you wish to disable. You can see a list of services by listing the contents of /etc/init.d.
The file /etc/init.d/alsa-utils is kind enough to tell us how to disable it. To disable alsa-utils, per the file, "rename the "S50alsa-utils" symbolic link in /etc/rcS.d/ to "K50alsa-utils"". This will prevent alsa-utils from starting on boot. To stop the service now, type:
sudo /etc/init.d/alsa-utils stop
To disable pcmciautils, rename the "S13pcmciautils" symbolic link in /etc/rcS.d/ to "S87pcmciautils". This will prevent pcmciautils from starting on boot. To stop the service now, type:
sudo /etc/init.d/pcmciautils stop
Although Ubuntu Linux is a secure operating system, we can do a few things to decrease the external attack vectors.
Host.deny and hosts.allow
The hosts.deny and hosts.allow files allow us to configure which remote hosts can talk to any open port on this server if the process that opened that port has support for tcp wrappers. For example, the ssh daemon supports tcp wrappers so it will respect the ACLs defined by the hosts.deny and hosts.allow file. The Apache Web server, on the other hand, does not (by default) support tcp wrappers; therefore, the hosts.deny and hosts.allow files have no impact on which clients can access ports that the Apache process opens.
I practice explicit access control, which means that I explicitly deny all access and explicitly grant access. To explicitly deny access, edit the /etc/hosts.deny file with:
sudo vi /etc/hosts.deny
Add this line to the end of the file:
Save the file and exit. At this point, if your server were connected to the network, no remote client would be able to access any port that was opened by a process that supports tcp wrappers. This is because you have explicitly denied all clients.
Now you need to explicitly allow some clients. To do this, edit the file /etc/hosts.allow with:
sudo vi /etc/hosts.allow
Allow all remote connections to certain clients by adding the following lines to the end of the file:
ALL:CLIENT_HOSTNAME_1, CLIENT_HOSTNAME_2, CLIENT_IP_ADDRESS_1, *.CLIENT.DOMAIN.COM
Save the file and exit. As you can see, you can add entries to the file by host name and ip address -- of even domain names with wild cards in them. To learn more about the hosts access control list files, type the following at the shell:
The man page that appears will describe the formats of both the hosts.deny and hosts.allow files (hint, they're the same format).
At this point, all remote clients are denied access to your server's ports that have been spawned by processes that support tcp wrappers, except for those clients you have explicitly allowed. And because the only open port at the moment is 22 for the sshd process and because the sshd supports tcp wrappers, if your server were on the network, only the explicitly allowed clients in the hosts.allow file would be able to connect to the server via ssh.
Beside hosts access file, another way to really lock down the ssh daemon is to restrict clients to using public key authentication.
Please be sure you want to do this. If you do enable this, then you will not be able to log into this server remotely with ssh with a passphrase. You will be required to have a public key. If you are unsure of this step, please read the documentation on ssh and public key authentication at sial.org.
To restrict the ssh daemon to public key authentication, edit /etc/ssh/sshd_config with:
sudo vi /etc/ssh/sshd_config
Find the line:
# PasswordAuthentication yes
…and change it to disallow password authentication:
We also need to tell the ssh daemon that it should only listen on the management interface NIC. Find the line:
# ListenAddress 0.0.0.0
…and replace it with
…where MGMT_NIC_IP is the IP of the management network interface. Changing this setting means that the ssh daemon will not listen on the NICs dedicated to the VMs.
Save the file and exit. Restart the ssh daemon by typing:
sudo /etc/init.d/ssh restart
Now the ssh daemon will only accept public key authentication and is listening for incoming connections only on the management interface NIC.
To prevent unauthorized access to the server, we will set up iptables so that only traffic we specify is allowed. We will set these rules in /etc/rc.local so that they are enabled at boot time. Edit /etc/rc.local with:
sudo vi /etc/rc.local
Copy and paste the following iptables rules into the file, replacing MGMT_NIC_IP with the IP address of the server's management network interface.
- --- BEGIN COPY --- # # INPUT # # allow all incoming traffic from the management interface NIC # as long as it is a part of an established connection iptables -I INPUT 1 -j ACCEPT -d MGMT_NIC_IP -m state --state RELATED,ESTABLISHED # allow all ssh traffic to the management interface NIC iptables -I INPUT 2 -j ACCEPT -p TCP -d MGMT_NIC_IP --destination-port 22 # allow all VMware MUI HTTP traffic to the management interface NIC iptables -I INPUT 3 -j ACCEPT -p TCP -d MGMT_NIC_IP --destination-port 8222 # allow all VMware MUI HTTPS traffic to the management interface NIC iptables -I INPUT 4 -j ACCEPT -p TCP -d MGMT_NIC_IP --destination-port 8333 # allow all VMware Authorization Daemon traffic to the management interface NIC iptables -I INPUT 5 -j ACCEPT -p TCP -d MGMT_NIC_IP --destination-port 902 # reject all other traffic to the management interface NIC iptables -I INPUT 6 -j REJECT -d MGMT_NIC_IP --reject-with icmp-port-unreachable # # OUTPUT # # allow all outgoing traffic from the management interface NIC # if it is a part of an established connection iptables -I OUTPUT 1 -j ACCEPT -s MGMT_NIC_IP -m state --state RELATED,ESTABLISHED # allow all DNS queries from the management interface NIC iptables -I OUTPUT 2 -j ACCEPT -s MGMT_NIC_IP -p UDP --destination-port 53 # reject all other traffic from localhost iptables -I OUTPUT 3 -j REJECT -s 127.0.0.1 --reject-with icmp-port-unreachable # reject all other traffic from the management interface NIC iptables -I OUTPUT 4 -j REJECT -s MGMT_NIC_IP --reject-with icmp-port-unreachable - --- END COPY ---
Once you've copied and pasted the iptables into /etc/rc.local, load them by typing:
sudo /etc/init.d/rc.local start
To verify that the iptables are loaded, type:
sudo iptables –L
You will see the iptables listed in the shell. Please keep in mind that this iptables list is a fairly restrictive set -- but only with regards to the management interface NIC. This iptables ruleset does not affect the other NICs in the server, the NICs dedicated to the VMs, at all.
If you have a remote console session to the server via ssh and you cannot ping some server or you cannot ssh into another server, remember that if you want to do any of those things and almost anything else, you will have to edit the iptables ruleset. For example, this ruleset does not take into account the apt servers that you will fetching updates from. You will have to make outbound exceptions for them above rule number 3 in the OUTPUT chain or else you will receive a "connection refused" error when you try to connect to them with apt.
At this point, it is safe to go ahead and plug in the server's Ethernet cables. Once that is completed, if all of the network information was inputted correctly, the server should be able to talk on the network.
In the next installment of this series, we'll look at how to secure VMware Server, fix a nagging bug in Ubuntu and how to monitor and back up the server.
About the author: Andrew Kutz is deeply embedded in the dark, dangerous world of virtualization. Andrew is an avid fan of .NET, open source, Terminal Services, coding and comics. He is a Microsoft Certified Solutions Developer (MCSD) and a SANS/GIAC Certified Windows Security Administrator (GCWN). Andrew graduated from the University of Texas at Austin with a BA in Ancient History and Classical Civilization and currently lives in Austin, TX with his wife Mandy and their two puppies, Lucy and CJ.