Building a secure web server with CentOS 5, part 2

Posted on 05.Jan 2010 by in LAMP, Linux, Web Hosting

Part 1Part 2Part 3Troubleshooting

Part 2: Configuring the Server

Configuring CentOS

  • Edit /etc/hosts and /etc/sysconfig/network with hostnames
  • Install Packages

Example of /etc/hosts:

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost
67.34.32.11 www.mydomain.com

Example of /etc/sysconfig/network

NETWORKING=yes
HOSTNAME=www.mydomain.com

Installing Packages

# yum -y install httpd openssl-devel openssl mod_ssl vsftpd rpm-build rpm-devel autoconf automake lynx gcc
# yum -y install mysql mod_auth_mysql mysql-devel mysql-server
# yum -y install mod_python python python-devel
# yum -y install perl mod_perl mod_perl-devel openssl-perl perl-Convert-ASN1 perl-Date-Calc perl-DateManip perl-HTML-Parser perl-libwww-perl perl-CPAN perl-DBD-MySQL perl-XML-Parser
# yum -y install php-devel php php-domxml php-gd php-mbstring php-mysql php-ncurses php-pear
# yum -y install webalizer
# yum -y install sendmail sendmail-cf


Creating Directory Structure

All websites will be held in /home/.sites/. The first site that needs to be created is the _default site, which will be used as this servers default website.

# mkdir /home/.sites
# cd /home/.sites
# mkdir _default
# cd _default
# mkdir logs private cgi-bin web
# cd web
# mkdir stats

Now change the ownership of these directories to adminftp as follows:

# cd /home/.sites
# chown adminftp _default -R

Configure the required system services sto start at boot:

# chkconfig httpd on
# chkconfig mysqld on
# chkconfig vsftpd on
# chkconfig sshd on

Configuring Apache

Apache runs as the httpd service, and it’s configuration file is contained in /etc/httpd/conf. To run in a ‘virtual’ hosting environment, we will now configure the httpd.conf file. But first things first, lets backup the httpd.conf file!

# cd /etc/httpd/conf
# cp httpd.conf httpd.conf.backup

Now edit httpd.conf (vi /etc/httpd/conf/httpd.conf) and make the following changes (substituting mydomain.com for your own domain).

The first section should be inside the httpd.conf file by default, so you just need to search for each line. You can easily do this using Vi by typing a forward slash then the keyword followed by enter (E.g. /ServerAdmin) and this will skip to that section if it is found. A bit like using Find in Windows.

ServerAdmin admin@mydomain.com
ServerName www.mydomain.com:80
NameVirtualHost *:80
DirectoryIndex index.html index.htm index.html.var

Next, skip to the very bottom of the httpd.conf file and you should see something similar to this:

<VirtualHost *:80>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot /www/docs/dummy-host.example.com
ServerName dummy-host.example.com
ErrorLog logs/dummy-host.example.com-error_log
CustomLog logs/dummy-host.example.com-access_log common
</VirtualHost>

Make sure that this section isn’t commented out (with #) on each line, and then change the ServerAdmin, DocumentRoot, ServerName, ErrorLog and CustomLog . See the following example:

<VirtualHost *:80>
ServerAdmin admin@mydomain.com
DocumentRoot /home/.sites/_default/web
ServerName www.mydomain.com
ScriptAlias /cgi-bin/ /home/.sites/_default/cgi-bin/
ErrorLog /home/.sites/_default/logs/error_log
TransferLog /home/.sites/_default/logs/access_log

Options FollowSymLinks
Options +Includes
AllowOverride All
</VirtualHost>

You can host multiple websites by adding further VirtualHost sections, and each website is identified using the ServerName line. If your website has multiple domain names (E.g. www.mydomain.com www.mydomain.net mydomain.biz) then just add each one on a new line after ServerName with ServerAlias.

Save and exit the httpd.conf file and then restart the httpd service.

# /etc/init.d/httpd restart

Configuring VSFTP

VSFTP stands for Very Secure File Transfer Protocol. However using the installation defaults isn’t actually that secure as it allows anonymous access and doesn’t restrict which users can access the servers FTP service. In order to harden the security of VSFTP, several configuration changes must be made. Please note that some of these lines may be commented out by default, with a #, so remember to remove this if required.

# vi /etc/vsftpd/vsftpd.conf

anonymous_enable=NO
xferlog_file=/var/log/vsftpd.log
idle_session_timeout=600
nopriv_user=nobody
ascii_upload_enable=YES
ftpd_banner= **** WARNING - Your actions are being logged ****

pam_service_name=vsftpd
userlist_enable=YES
listen=YES
tcp_wrappers=YES
chroot_local_user=YES
userlist_deny=NO

Next, we need to configure vsftpd.userlist and specify which users can FTP to the server. This compliments the userlist_deny setting in vsftpd.conf. When set to NO, this makes the vsftpd.userlist file a list of users that ARE allowed to log in.

# vi /etc/vsftpd/user_list

Remove all of the users that are listed in this file by default, and add ONLY the users that require access to the FTP server.

Configuring MySQL

MySQL is configured using /etc/my.cnf, but prior to any configuration this configuration file has only the bare minimum required to start the MySQL daemon. However there are 5 templates that we can base the configuration on; my-huge.cnf, my-innodb-heavy-4G.cnf, my-large.cnf, my-medium.cnf, and my-small.cnf. These are each configured depending on the RAM and the priority that MySQL has on this server.

We will use my-medium.cnf as this has been based on a web server where MySQL is not the primary role of the server but could have frequent use. If you are hosting a few sites with light use then use my-small.cnf.

# cd /usr/share/doc/mysql-server-
# cp my-medium.cnf /etc/my.cnf

Once this has overwritten my.cnf, the mysqld service must be restarted.

# /etc/init.d/mysqld restart

Now the root password for MySQL must be set using the following command. Do NOT use the same root password as the Linux root password.

# mysqladmin -u root password

Setting up phpMyAdmin

Administration of MySQL is carried out using phpMyAdmin which is a free open source software package licensed under the GNU. Nearly all hosting providers use this, and is pretty much the de-facto standard these days.

1) Download phpMyAdmin,
2) Extract the contents to a directory called phpMyAdmin (case sensitive)
3) Transfer the phpMyAdmin directory to /home/.sites/_default/web (Use FTP and login using the user you setup previously, as described in the Configuring FTP using VSFTPD section).

Now we need to configure the confic.inc.php file as follows:

# vi /home/.sites/_default/web/phpMyAdmin/config.inc.php

Look for:

$cfg['Servers'][$i]['auth_type'] = 'config’;

Change ‘config’ to ‘http’ then restart MySQL.

# /etc/init.d/mysqld restart

You should now be able to log into phpMyAdmin by going to http://www.mydomain.com/phpMyAdmin. Log on using ‘root’ and the password you specified for MySQL. You will now be presented with the phpMyAdmin web control panel. By default, MySQL contains a test database which is not required, so as a security measure, this needs to be deleted. To do this, click on ‘Databases’, then tick test. Click ‘Drop’ and then click ‘Yes’ to confirm.

When you are ready proceed to part 3.

Thanks for reading! Please comment or Tweet this page (see below)


Tags , , , , , , , , , , , , ,

45 Responses

  1. Keyser Soze says:

    I have followed your steps above but when i loggin with ftp i have only access to:

    /home//

    And not to:
    /home/.sites/_default

    How can i change this per user?

  2. Keyser Soze says:

    thnx man it worked. Realy great job this tutorial ;-)

  3. newtocentos says:

    i did all the configuration from steps 1 to 2. but i can’t go into http://www.mydomain.com/phpMyAdmin. any idea how to fix it?

  4. buzzknow says:

    great tutz!

    i just bought some new VPS, and now i want to learn make it up :D

    this is y first time …. lol

    thanks

  5. scyllar says:

    This article is great, but i have a small issue with this:

    “Now change the ownership of these directories to adminftp as follows…”

    I don’t have the adminftp user on my system, can you explain it? Or maybe “ftp” I assume?

    Sorry this may sound funny because I am newbie on linux. Thank you very much.

    • Ray Heffer says:

      Hi Scyllar,

      In part 1 of the guide you created a user for SSH access under the section ‘Add Default Accounts’, so you can replace adminftp with the username you used for that. If it is the FTP username you are using for a website you are creating then the username will be the same as the one added at the start of part 3.

      I will update the guide to make this a bit easier to follow. Good luck!

      Ray

  6. declan says:

    Thanks for the tutorial. ServerName gets mentioned twice while editing httpd.conf. Are one of those under the section? Could the # symbols be commented out of that section? I’m a bit confused. thanks!

  7. declan says:

    the comment form ditched some of my comment. The above should read under the “VirtualHost *:80″ section

  8. declan says:

    also for the scriptalias substitution, should quotes be omitted as per your tutorial?

  9. Arturas says:

    I just found your tutorial and it really looks great, but I’m still a noob and it’s not very clear on how to config the httpd.conf file.

    I’ve tried finding the places where these commands are mentioned and substituting them, but that didn’t work out since there are a few or directoryroot and options commands – i ended up getting an error when trying to start httpd – can’t find file or directory /home/.sites/_default/logs/error_log

    I then tried overwriting the file from backup and trying all over again. I started substituting these commands:
    ServerAdmin admin@mydomain.com
    ServerName http://www.mydomain.com:80
    NameVirtualHost *:80
    DirectoryIndex index.html index.htm index.html.var

    and these:
    Options FollowSymLinks
    Options +Includes
    AllowOverride All

    into the most MAIN places i could find (don’t know how to better explain this.)

    and inserting this:
    ServerAdmin admin@mydomain.com
    DocumentRoot /home/.sites/_default/web
    ServerName http://www.mydomain.com
    ScriptAlias /cgi-bin/ /home/.sites/_default/cgi-bin/
    ErrorLog /home/.sites/_default/logs/error_log
    TransferLog /home/.sites/_default/logs/access_log

    into a virtual host container at the bottom and uncommenting it.

    But now, when trying to start httpd, it just says FAILED without any errors whatsoever. I tried running httpd -e DEBUG but it just shows a bunch of modules loaded – no errors or anything like that.

    It would be very much appreciated if you could give some clearer instructions on how to do this. Thank you in advance.

  10. Rob says:

    Hello, could you be some more specific about editing the httpd.conf
    wich section goes where

    thnx very much

  11. Ray Heffer says:

    I can certainly clarify the httpd.conf configuration. The following section should already be there by default, but will need updating to reflect your details (E.g. domain name)

    ServerAdmin admin@mydomain.com
    ServerName http://www.mydomain.com:80
    NameVirtualHost *:80
    DirectoryIndex index.html index.htm index.html.var

    In regards to the next section on editing httpd.conf, I’ve updated the post above with more detail and explanation as it wasn’t that clear!

    Let me know how you get on.

    Ray

  12. brentos says:

    Great tutorial so far!!!

    I have just edited the httpd.conf file
    but when I try to restart httpd, I get the following error:

    Stopping httpd: [FAILED]
    Starting httpd: Syntax error on line 994 of /etc/httpd/conf/httpd.conf:
    AllowOverride not allowed here

    which corresponds to the last line of the VirtualHost setup

    Any thoughts ?

    I’m running a VPS so I’m guessing it is something my hosting company is blocking ?!?! Is there some way to go around this or correct this?

    Thanks in advance for all of your time, effort, and talent.

    • brentos says:

      I commented out the AloowOverride All line
      and was able to restart the http daemon

      Then I uploaded a file to the home/.site/_default/web folder
      and was able to access it from my browser so everything appears to be working ok.

      It would still be great to know if I should do something about the Override line.

      Thanks a ton.

    • Ray Heffer says:

      Hi,

      In regards to the error starting httpd, just double check for typo’s in the httpd.conf file. If it works when commenting the AllowOverride All line out, and it’s not a typo then make sure it is within the VirtualHost section.

      Ray

      • brentos says:

        Here’s the end of the httpd.conf file:

        ServerAdmin admin@mysite.com
        DocumentRoot /home/.sites/_default/web
        ServerName http://www.mysite.com
        ScriptAlias /cgi-bin/ /home/.sites/_default/cgi-bin/
        ErrorLog /home/.sites/_default/logs/error_log
        TransferLog /home/.sites/_default/logs/access_log
        Options FollowSymLinks
        Options +Includes
        # AllowOverride ALL

        Found this earlier in the file :

        Options FollowSymLinks
        AllowOverride None

        is AllowOverride recursive or would this only apply to the root ?

      • brentos says:

        I had this thread : http://www.mail-archive.com/mirrors@apache.org/msg01647.html that says the AllowOverride directive has to be “inside of a , , or container.”

        So I added this to the end of the httpd.conf file and now everything works:

        Options FollowSymLinks
        Options +Includes
        AllowOverride All

        killed the following error:

        Stopping httpd: [FAILED]
        Starting httpd: Syntax error on line 994 of /etc/httpd/conf/httpd.conf:
        AllowOverride not allowed here

        Thanks for all of your help Ray.
        Great tutorial

      • Gummi says:

        Hey there,

        I just can´t seem to get rid if the error regarding AllowOverride All. I always get the message:
        Starting httpd: Syntax error on line 994 of /etc/httpd/conf/httpd.conf:
        AllowOverride not allowed here
        [FAILED]

        Here below is my virtualhost section:

        ServerAdmin admin@****.is
        DocumentRoot /home/.sites/_default/web
        ServerName www.***.com
        ScriptAlias /cgi-bin/ /home/.sites/_default/cgi-bin/
        ErrorLog /home/.sites/_default/logs/error_log
        TransferLog /home/.sites/_default/logs/access_log
        Options FollowSymLinks
        Options +Includes
        AllowOverride All

        Any thoughts on how I can get rid of this, I´m not fully understanding how the comments below fixed this issue.

  13. brentos says:

    Re: editing /etc/vsftpd/user_list

    “Remove all of the users that are listed in this file by default, and add ONLY the users that require access to the FTP server.”

    should we also remove root?

  14. brentos says:

    One last question…

    what are your thoughts about your method of setting up a secure server versus setting up a chroot jail or a virtual container using something like OpenVZ?

    or is it not possible to set up a chroot jail or OpenVZ container when your account is already a VPS account???

    Thanks again.

    • Ray Heffer says:

      Hi,

      If you are already running a VPS then they will probably be using Xen or OpenVZ for the virtualization platform. Using a chroot jail on a VPS is certainly possible, that is what we’re doing here with VSFTP. In the vsftpd.conf file make sure you have chroot_local_user=YES.

      Apache can run in a chroot jail, but I don’t cover that in my guides. Here is a great article on that for CentOS: http://bit.ly/mG5x

      Ray

  15. brentos says:

    I’m back again :\

    I got everything set up and all seems well… EXCEPT…

    I can’t login into the server with any of the user accounts.

    checked the vsftpd.conf file, as well as the user_list to make sure that the proper users were allowed, which they were.

    any ideas?

    Thanks again.

    • Ray Heffer says:

      Double check that your vsftpd.conf file contains the following lines:

      userlist_enable=YES
      chroot_local_user=YES
      userlist_deny=NO

      Good luck with the server build, let me know how you get on!

      Ray

      • brentos says:

        Thanks your fast responses

        Here’s the relevant lines from my vsftpd.conf file:

        listen=YES
        pam_service_name=vsftpd
        userlist_enable=YES
        tcp_wrappers=YES

        The following two lines were not in my vsftpd.conf file at all so I just added them at the end of the file.

        chroot_local_user=YES
        userlist_deny=NO

        Was their absense an indication that I may be using a different version of vsftp ?

        Here’s a couple commented lines that are in my file that may do the same as what you are talking about:

        # You may specify an explicit list of local users to chroot() to their home
        # directory. If chroot_local_user is YES, then this list becomes a list of
        # users to NOT chroot().
        #chroot_list_enable=YES
        #chroot_list_file=/etc/vsftpd/chroot_list

        I might try to uncomment them as is, and then just create a blank file for chroot_list, that way everybody gets chrooted.

        Thanks again for all of your help

  16. Matt Provost says:

    Hello I am a little new when it comes to this kind of stuff so I’m having what is probably just a very simple error

    when I try to start the httpd I get the following error:

    “Starting httpd: Warning: DocumentRoot [/home/.sites/_default/web] does not exist”

    I know that this shouldn’t be happening because I followed the tutorial to the letter so far and I was even able to cd to the “/home/.sites/_default/web” directory

    any suggestions?

  17. Bart Darlington says:

    I’m seeing the same problem as Matt Provost above…tells me that /web doesn’t exist even though I can copy and paste the path in the error message after a “cd” command and get there.

    • Brian Ernesto says:

      Still looking into the issue Here is a step that was missing from this tutorial that was in the old one:

      Add Default Accounts

      Before proceeding with any of the steps below, first create an account that will be used to log in to this server. Next, we will create a special FTP account called adminftp, that can be used to access the /.sites directory.

      # adduser sysop
      # passwd sysop

      # adduser -s /sbin/nologin adminftp
      # passwd adminftp

      Next we need to change the home directory of the adminftp account. This will allow us to use this account to access all folders in the /.sites directory.

      # vi /etc/passwd

      Change the home directory from /home/adminftp to /home/.sites.

      • Tim D says:

        Brian or Ray,
        I added the the adminftp (actually I used a slightly diff name) but when I log in via SFTP with Filezilla I still get the errors when trying to upload the “phpMyAdmin” folder. “mkdir….. declined” .

        Do you know what I need to do to change the user permissions so that this folder can be uploaded?

  18. Brian Ernesto says:

    Here is a little bit more that was missing:

    ServerAdmin admin@mydomain.com
    DocumentRoot /home/.sites/_default/web
    ServerName http://www.mydomain.com
    ScriptAlias /cgi-bin/ /home/.sites/_default/cgi-bin/
    ErrorLog /home/.sites/_default/logs/error_log
    TransferLog /home/.sites/_default/logs/access_log

    Options FollowSymLinks
    Options +Includes
    AllowOverride All

    At the very end of the configuration file add the following line. Make sure you include the # otherwise it will not work.

    # END

  19. Brian Ernesto says:

    Got it.. damn SELINUX

    vi /etc/sysconfig/selinux
    and change it to disabled then reboot.

    Now if I can just get FTP to work.

  20. Philipp Burch says:

    Hi Ray, hi Brian,

    thanks for this great Tutorial Ray. It saved me a lot of time searching for good options to configure my server. Or to configure the server which I will have in a few days, to be exactly ;)

    @Brian:

    I’ve run into the same problem of being not able to change the DocumentRoot into the home folder. I’ve read posts which advised to disable SELinux completely (just as you did above), but that doesn’t seem to be a good idea for a “secure web server”. Passwords are inconvenient as well, but would you simply leave them blank because of this?
    Anyway, I’ve stumbled across this nice introduction to SELinux:
    http://wiki.centos.org/HowTos/SELinux
    Section “5.1 Relabeling Files” almost exactly states what to do in this case: Change the security context of the folder (.sites) and its subfolders so that Apache (httpd) is permitted to access them.

    So all I had to do to get it working was issueing the following commands:

    # chcon -Rv –type=httpd_sys_content_t /home/sites/
    # semanage fcontext -a -t httpd_sys_content_t “/home/sites(/.*)?”

    (I prefer unhidden folders, so that’s why “sites” doesn’t start with a period here.)

    The first command recursively changes the security context of all folders and files in /home/sites to httpd_sys_content_t. The second makes this change permanent, should you ever need to “relabel” the filesystem.

    Best regards,
    Philipp

  21. Tim D says:

    Ray,
    Everything has gone great. The only problems that I ran into on step 1 was “perl-CPAN” did not install. Will research that later.

    My main issue is that I am trying to upload phpMyAdmin. I setup a username and password as instructed in the steps. I am able to connect via SFTP using Filezilla. But I keep getting “mkdir …… declined ” in the Filezilla progress window. I had actually created the directory while in SSH but then I logged back in and deleted the folder in case the problem was that I created the folder as root and trying to upload as .

    Any ideas on what is wrong here? Thanks again for this awesome tutorial.

  22. Tim D says:

    Is it not possible to just use “wget” command and download the file (I did that already) and then unzip it on the server? I tried but I don’t know how to properly format the “tar” command. Maybe you can let me know if this would be possible. Thanx.

  23. e0s says:

    Starting httpd: Syntax error on line 994 of /etc/httpd/conf/httpd.conf:
    AllowOverride not allowed here
    [FAILED]

    I have AllowOverride in the virtualhost section and it is telling me it is not allowed here?

  24. ivi0708 says:

    while trying to restart the httpd service it shows me [FAILED] whith no error description. I tried what the above commentors did but it doesn’t work to me.

    need help

  25. Rick Lemon says:

    Just remember to also do this:

    chcon -R -t httpd_sys_content_t /home/.sites

    in CentOS 6 to fix the SELinux issues.

Leave a Reply