These are my notes for creating a secure Apache web server using Redhat Linux. This article does not cover protection against denial-of-service attacks.
I am assuming that this is a dedicated web server where only HTTP and SSH requests are accepted by the web server. SSH is an encrypted protocol for terminal emulation and allows secure tunnelling of other protocols such as FTP, so all maintenance of the server is encrypted. Outgoing traffic will be DNS requests, mail and HTTP responses; there might be some queries to a database also.
The simplest way to implement security is to reduce the number of doors to your server. This means we should remove all unneeded network access points, especially background processes (deamons) that listen on various TCP/IP ports, leaving behind the following services:
- sshd: This is for secure VPN's and encrypted terminal connections to the server. Do not use telnet. An example configuration using MindTerm's SSH Client. We use TeraTerm's SSH client ourselves.
- httpd: this is the apache deamon.
Turn off viewing of directories and refrain from using CGI. It is important to be familiar with your scripting languages vulnerabilities (here's a good PHP article), and sanitize all GET and POST inputs. If possible, set all your web directories to read-only. Place all your code outside the web directory paths, and have only skeleton files that call the code within the web directories.
Avoid symbolic links to areas outside the web directories.
It is also important that the web server is run under a different user than the one supervising the pages. In this way an attacker who manages to leak through the web will not be able to change the pages.
- database deamons: If your database is on another server, make sure that server is only accessible from authorized machines of course.
- Sendmail will still be configured, but only for sending out-going mail using /etc/sysconfig/sendmail to deny incoming mail.
- Optional tcpwrappers: Controls and controls which hosts can access the server. This is optional if you have a minimal install like what is recommended here.
In the /etc/hosts.deny file add the following line:
ALL : ALLand in the /etc/hosts.allow file:
sshd : ALL httpd : ALL in.ftpd : 127.0.0.1note: above does not support sendmail
- Optional ftpd: makes file transfers work with standard ftp clients. Alternatively, you can use scp or WinSCP. You can control who has access by modifying the /etc/ftphosts file. I recommend you set it to allow only localhost - in other words we will use SSH tunnels to connect.
Choose good passwords for your user id's. Best are phrases which are not vulnerable to a dictionary search, and are reasonably long.
You can audit your TCP/IP ports for exposures by running
netstat -a | grep LISTEN to scan your ports. A secure site should have only ports 22 (SSH), 80 (HTTP) and 443 (SSL) exposed. This works on NT also!
Log files are another useful tool for monitoring attacks on your server. Some people suggesting the logging should be to a central secure log server, so hackers will not be able to remove traces of their intrusion so easily.
It is possible to install more sophisticated security checking with ipchains and similar technology. However there is some overhead involved in all this, and it is possible that there are bugs in these software also. Instead i prefer removing as many potential vulnerabilities as possible, and then verifying (to the best of our ability) that the remaining software is secure.
Just before your web server goes live, use TripWire to generate checksums of all files.
The remaining vulnerabilities should be software bugs. Regularly check with your Linux and software vendors for the latest security updates on your kernel, SSH, httpd, ftp etc.
You can check which ports are used by which applications using netstat:
$ netstat -ap Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 *:netbios-ssn *:* LISTEN 925/smbd tcp 0 0 *:webcache *:* LISTEN 1119/httpd tcp 0 0 *:x11 *:* LISTEN 990/X tcp 0 0 *:http *:* LISTEN 811/squid tcp 0 0 *:ssh *:* LISTEN 702/sshd tcp 0 0 *:https *:* LISTEN 1119/httpd
iptables -A OUTPUT -p tcp --dport 25 -j DROP
To display iptables rules after above change:
$iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP tcp -- anywhere anywhere tcp dpt:smtp
This is useful if your server has been hacked and used as a spam server, but you don't know (yet) which program is sending the spam. To confirm emails have been blocked, you can see with netstat (SYN_SENT indicates that the socket is actively attempting to establish a connection):
$ netstat -p | grep smtp tcp 0 1 10.1.101.53:55878 188.8.131.52:smtp SYN_SENT - tcp 0 1 10.1.101.53:55904 184.108.40.206:smtp SYN_SENT - tcp 0 1 10.1.101.53:55845 220.127.116.11:smtp SYN_SENT - tcp 0 1 10.1.101.53:55871 18.104.22.168:smtp SYN_SENT -
To block receiving smtp packets on port 25:
iptables -A INPUT -p tcp --dport 25 -j DROP
Rules created with the iptables command are stored in RAM. For rules to persist through reboot, you need to save them to the /etc/sysconfig/iptables file. To do this, as root, enter
/sbin/service iptables save
Useful Info on LinuxTCP/IP configuration files.
The bootup process on Red Hat.
Disabling root access. Securing Apache on Linux Tuning Apache for PHP.
Installation of a secure web server from SuSE's perspective.
Another Security How-To for Redhat.
Some PHP Security Resources