Securing a Linux Webserver for Public Access

Securing a linux webserver for public access

This article has some of the best ways to lock things down:

http://www.petefreitag.com/item/505.cfm

Some highlights:

  • Make sure no one can browse the directories
  • Make sure only root has write privileges to everything, and only root has read privileges to certain config files
  • Run mod_security

The article also takes some pointers from this book:

Apache Securiy (O'Reilly Press)

As far as distros, I've run Debain and Ubuntu, but it just depends on how much you want to do. I ran Debian with no X and just ssh'd into it whenever i needed anything. That is a simple way to keep overhead down. Or Ubuntu has some nice GUI things that make it easy to control Apache/MySQL/PHP.

Best way to keep files on web server secure

If you are using Apache you could restrict access to specific files by adding an .htaccess file in the web root:

<Files create_db.txt>
Order allow, deny
Deny from all
</ Files>

The Files section above would restrict access for all users to the create_db.txt file.

Running nginx the same could be achieved by adding the following to your configuration:

location ^~ /create_db.txt {
deny all;
}

Like stated in the other answer you really should consider moving the file to a directory outside of your webroot. Of course the webserver must be able to access this folder. This can be done by setting the correct permission on the folder and perhaps by changing the owner to that of the webserver. Something like this:

mkdir -m 755 -p /path/outside/webroot
mv create_db.txt /path/outside/webroot
chown -R <user>:<group> /path/outside/webroot

Securing a simple Linux server that holds a MySQL database?

A famous man once said "security is a process, not a product."

So you have a db server that should ONLY listen to one other server for db connections and you have the specific IP for that one other server. There are several layers of restriction you can put in place to accomplish this

1) Firewall

If your MySQL server is fortunate enough to be behind a firewall, you should be able to block out all connections by default and allow only certain connections on certain ports. I'm not sure how you've set up your db server, or whether the other server that wants to access it is on the same LAN or not or whether both machines are just virtual machines. It all depends on where your server is running and what kind of firewall you have, if any.

I often set up servers on Amazon Web Services. They offer security groups that allow you to block all ports by default and then allow access on specific ports from specific IP blocks using CIDR notation. I.e., you grant access in port/IP combination pairs. To let your one server get through, you might allow access on port 3000 to IP address 101.432.xx.xx.

The details will vary depending on your architecture and service provider.

2) IPTables

Linux machines can run a local firewall (i.e., a process that runs on each of your servers itself) called iptables. This is some powerful stuff and it's easy to lock yourself out. There's a brief post here on SO but you have to be careful. It's easy to lock yourself out of your server using IPtables.Keep in mind that you need to permit access on port 22 for all of your servers so that you can login to them. If you can't connect on port 22, you'll never be able to login using ssh again. I always try to take a snapshot of a machine before tinkering with iptables lest I permanently lock myself out.

There is a bit of info here about iptables and MySQL also.

3) MySQL cnf file

MySQL has some configuration options that can limit any db connections to localhost only - i.e., you can prevent any remote machines from connecting. I don't know offhand if any of these options can limit the remote machines by IP address, but it's worth a look.

4) MySQL access control via GRANT, etc.

MySQL allows you very fine-grained control over who can access what in your system. Ideally, you would grant access to information or functions only on a need-to-know basis. In practice, this can be a hassle, but if security is what you want, you'll go the extra mile.

To answer your questions:

1) YES, you should definitely try and limit access to your DB server's MySQL port 3000 -- and also port 22 which is what you use to connect via SSH.

2) Aside from ones mentioned above, your limiting of PHPMyAdmin to only your IP address sounds really smart -- but make sure you don't lock yourself out accidentally. I would also strongly suggest that you disable password access for ssh connections, forcing the use of key-pairs instead.You can find lots of examples on google.

Secure Apache Site Permissions

Apache has it's own user and group (www-data or others according to the distribution it's runnin on). To achieve what you want, you need to create a user for each virtualhost and make sure apache can read/write file/folders owned by this new user for example putting apache group into the new user's group (or the other way around, according to how you want to handle permissions).

The logic "behind" is exactly the same you use to handle linux users and group permissions.

Best way to sandbox Apache on Linux

Chroot jails can be really insecure when you are running a complete sandbox environment. Attackers have complete access to kernel functionality and for example may mount drives to access the "host" system.

I would suggest that you use linux-vserver. You can see linux-vserver as an improved chroot jail with a complete debian installation inside. It is really fast since it is running within one single kernel, and all code is executed natively.

I personally use linux-vserver for seperation of all my services and there are only barely noticeable performance differences.

Have a look at the linux-vserver wiki for installation instructions.

regards, Dennis

Apache Webserver security and optimization tips

Basic

  1. Be sure to have the latest stable version installed. Running old or unstable version of Apache could expose your system to security flaws or untested solutions
  2. Be sure only the intended requests are actually processed. You should consider who has to access the web resources exposed by Apache and how.
  3. Avoid running Apache as root. This is a must.
  4. Handle your logs. Logs tend to become bigger and bigger; consider to setup logrotate or to clean your log periodically.
  5. Monitor Apache health with a monitoring system. I like to couple munin and monit, both easy to setuo and to maintain. Nagios and others are worth a look.
  6. If Apache is serving web apps (i.e. PHP, Perl, Rails) be sure the requests are handled by the right module in the right order.
  7. Write a nice 404 and 500 message. Sooner or later your visitors will catch an error.
  8. Stop and restart Apache, so you can be sure both the shoutdown and start procedure is working flawlessy.
  9. Use mod_security

Security

  1. Protect Apache against DOS.
  2. Load only the modules really needed.
  3. Monitor your log to figure out if something strange is happening.

Performance

  1. If you are compiling Apache from source code, be sure to use MPM (Multi-Processing Modules).
  2. Load only the modules really needed.
  3. Check the MaxClients setting so that your server does not spawn so many children it starts swapping.
  4. Use the mod_deflate module, it provides the DEFLATE output filter that allows output from your server to be compressed before being sent to the client over the network.

Securing a web server with local MySQL database

If you're using Amazon EC2 then you should make use of their security groups to lock down your MySQL server and ensure that no external access to it is possible.

Application servers have an internal non-routing 10.x type IP that should be used for access control, and any external IPs, like your home network, should be specifically whitelisted if VPN access or SSH tunnelling is not practical, as those two are far easier to secure.

Be absolutely sure that no credentials, configuration files, or keys are stored anywhere in your web root. That is, should you accidentally misconfigure your application server in the worst possible way, with directory indexes turned on and everything, it's not possible to snag anything critical.

You might also want to specifically exclude the downloading of *.inc in case you make a mistake. The idea here is to set up a number of safeguards you'd have to break before things go horribly awry. A single-mistake failure situation is always the result of bad planning.

Above all else, be extremely vigilant about proper SQL escaping to avoid SQL injection bugs as no amount of firewall security on your MySQL server will help you when someone can drive a truck through a mistake in your code and have free reign on the server. It's recommended to thoroughly audit any SQL interfacing code you've written before going live with it.

Be sure to have a proper deployment procedure that uses a version control system. If you ever have an intrusion it's very easy to roll back to a known-good version of the code if you have one. The 1990s style "throw files at server with FTP" deployment approach is hazardous at the best of times and fatal to your business when it goes wrong. Use version control or you're living on borrowed time.



Related Topics



Leave a reply



Submit