Monday, August 6, 2012

Creating Certificate Authorities and self-signed SSL certificates


Following is a step-by-step guide to creating your own CA (Certificate Authority) -- and also self-signed SSL server certificates -- with openssl on Linux. Self-signing is the simpler route to take, but making one's own CA allows the signing of multiple server certificates using the same CA and involves only a few extra steps.

After using openssl to generate the necessary files, you'll need to integrate them into Apache. This process differs between Linux distros and versions of Apache. Additional references exist at the end of this document. My instructions for Setting up SSL: Debian and Apache 2 are kept most current, and will carry you through to completion.

Making a homemade CA or self-signed certificate will cause the client web browser to prompt with a message whether to trust the certificate signing authority (yourself) permanently (store it in the browser), temporarily for that session, or to reject it. The message "web site certified by an unknown authority... accept?" may be a business liability for general public usage, although it's simple enough for the client to accept the certificate permanently.

Whichever route you take, you'll save the periodic expense of paying a recognized signing authority. This is purely for name recognition -- they've paid the major browser producers to have their CA pre-loaded into them. So if you're on a budget, have a special need or small audience, this may be useful.

Before you start
You need Apache and openssl. Compiling them from source, handling dependencies, etc. is beyond the scope of this document. You can consult their documentation, or go with a mainstream Linux distro that will do the preliminary work for you.

Now you need to decide whether you'll make a CA (Certificate Authority) and sign a server certificate with it -- or just self-sign a server certificate. Both procedures are detailed below.


(1A) Create a self-signed certificate.

Complete this section if you do NOT want to make a CA (Certificate Authority). If you want to make a CA, skip 1A entirely and go to 1B instead.

Some steps in this document require priviledged access, and you'll want to limit access to the cert files to all but the root user. So you should su to root and create a working directory that only root has read/write access to (for example: mkdir certwork, chmod 600 certwork). Go to that directory.

Generate a server key:

openssl genrsa -des3 -out server.key 4096

Then create a certificate signing request with it. This command will prompt for a series of things (country, state or province, etc.). Make sure that "Common Name (eg, YOUR name)" matches the registered fully qualified domain name of your box (or your IP address if you don't have one). I also suggest not making a challenge password at this point, since it'll just mean more typing for you.

The default values for the questions ([AU], Internet Widgits Pty Ltd, etc.) are stored here: /etc/ssl/openssl.cnf. So if you've got a large number of certificate signing requests to process you probably want to carefully edit that file where appropriate. Otherwise, just execute the command below and type what needs to be typed:

openssl req -new -key server.key -out server.csr

Now sign the certificate signing request. This example lasts 365 days:

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Make a version of the server.key which doesn't need a password:

openssl rsa -in server.key -out server.key.insecure
mv server.key server.key.secure
mv server.key.insecure server.key

These files are quite sensitive and should be guarded for permissions very carefully. Chown them to root, if you're not already sudo'd to root. I've found that you can chmod 000 them. That is, root will always retain effective 600 (read) rights on everything.

Now that you've just completed Step 1A, skip ahead to Step 2.

(1B) Generate your own CA (Certificate Authority).

Complete this section if you want to make a CA (Certificate Authority) and sign a server certificate with it. The steps for making a server certificate are also included here. If you'd rather one-time self-sign a server certificate, skip this step entirely and go to 1A instead.

Some steps in this document require priviledged access, and you'll want to limit access to the cert files to all but the root user. So you should su to root and create a working directory that only root has read/write access to (for example: mkdir certwork, chmod 600 certwork). Go to that directory.

In this step you'll take the place of VeriSign, Thawte, etc. You'll first build the CA key, then build the certificate itself.

The Common Name (CN) of the CA and the Server certificates must NOT match or else a naming collision will occur and you'll get errors later on. In this step, you'll provide the CA entries. In a step below, you'll provide the Server entries. In this example, I just added "CA" to the CA's CN field, to distinguish it from the Server's CN field. Use whatever schema you want, just make sure the CA and Server entries are not identical.

CA:
Common Name (CN): www.somesite.edu CA
Organization (O): Somesite
Organizational Unit (OU): Development

Server:
Common Name (CN): www.somesite.edu
Organization (O): Somesite
Organizational Unit (OU): Development

If you don't have a fully qualified domain name, you should use the IP that you'll be using to access your SSL site for Common Name (CN). But, again, make sure that something differentiates the entry of the CA's CN from the Server's CN.

openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

Generate a server key and request for signing (csr).

This step creates a server key, and a request that you want it signed (the .csr file) by a Certificate Authority (the one you just created in Step #1B above.)

Think carefully when inputting a Common Name (CN) as you generate the .csr file below. This should match the DNS name, or the IP address you specify in your Apache configuration. If they don't match, client browsers will get a "domain mismatch" message when going to your https web server. If you're doing this for home use, and you don't have a static IP or DNS name, you might not even want worry about the message (but you sure will need to worry if this is a production/public server). For example, you could match it to an internal and static IP you use behind your router, so that you'll never get the "domain mismatch" message if you're accessing the computer on your home LAN, but will always get that message when accessing it elsewhere. Your call -- is your IP stable, do you want to repeat these steps every time your IP changes, do you have a DNS name, do you mainly use it inside your home or LAN, or outside?

openssl genrsa -des3 -out server.key 4096
openssl req -new -key server.key -out server.csr

Sign the certificate signing request (csr) with the self-created Certificate Authority (CA) that you made earlier.

Note that 365 days is used here. After a year you'll need to do this again.

Note also that I set the serial number of the signed server certificate to "01". Each time you do this, especially if you do this before a previously-signed certificate expires, you'll need to change the serial key to something else -- otherwise everyone who's visited your site with a cached version of your certificate will get a browser warning message to the effect that your certificate signing authority has screwed up -- they've signed a new key/request, but kept the old serial number. There are a couple ways to rectify that. crl's (certificate revocation list) is one method, but beyond the scope of the document. Another method is for all clients which have stored the CA certificate to go into their settings and delete the old one manually. But for the purposes of this document, we'll just avoid the problem. (If you're a sysadmin of a production system and your server.key is compromised, you'll certainly need to worry.)

The command below does a number of things. It takes your signing request (csr) and makes a one-year valid signed server certificate (crt) out of it. In doing so, we need to tell it which Certificate Authority (CA) to use, which CA key to use, and which Server key to sign. We set the serial number to 01, and output the signed key in the file named server.crt. If you do this again after people have visited your site and trusted your CA (storing it in their browser), you might want to use 02 for the next serial number, and so on. You might create some scheme to make the serial number more "official" in appearance or makeup but keep in mind that it is fully exposed to the public in their web browsers, so it offers no additional security in itself.

openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

To examine the components if you're curious:

openssl rsa -noout -text -in server.key
openssl req -noout -text -in server.csr
openssl rsa -noout -text -in ca.key
openssl x509 -noout -text -in ca.crt

Make a server.key which doesn't cause Apache to prompt for a password.

Here we create an insecure version of the server.key. The insecure one will be used for when Apache starts, and will not require a password with every restart of the web server. But keep in mind that while this means you don't have to type in a password when restarting Apache (or worse -- coding it somewhere in plaintext), it does mean that anyone obtaining this insecure key will be able to decrypt your transmissions. Guard it for permissions VERY carefully.

openssl rsa -in server.key -out server.key.insecure
mv server.key server.key.secure
mv server.key.insecure server.key

These files are quite sensitive and should be guarded for permissions very carefully. Chown them to root, if you're not already sudo'd to root. I've found that you can chmod 000 them. That is, root will always retain effective 600 (read) rights on everything.

(2) Copy files into position and tweak Apache.

Some professors like to pause for a moment after a long lecture, and do a little recap. It's a good pedagogical tool, so let's do so here. If you took route 1A above, you should have four files in a working directory:

server.crt: The self-signed server certificate.
server.csr: Server certificate signing request.
server.key: The private server key, does not require a password when starting Apache.
server.key.secure: The private server key, it does require a password when starting Apache.

If you took route 1B and created a CA, you'll have two additional files:

ca.crt: The Certificate Authority's own certificate.
ca.key: The key which the CA uses to sign server signing requests.

The CA files are important to keep if you want to sign additional server certificates and preserve the same CA. You can reuse these so long as they remain secure, and haven't expired.

At a bare minimum, the following considerations must now be addressed:
  • You'll need a virtual host and document root set up for the SSL instance.
  • You'll need to turn on the SSL engine and enable/load the SSL module.
  • Apache must reference server.crt and server.key somewhere in its configuration.
  • Apache must be listening to a port for which SSL is enabled (443 is default).
The particulars differ between Linux distros and versions of Apache. I'm only able to keep the Setting up SSL: Debian and Apache 2 documentation current due to time constraints. Those steps should apply broadly to other Debian-based distros with little or no modification. Red Hat and openSUSE commentary is kept online here for historical purposes. 

                          Setting up SSL: Red Hat and Apache 1.3.x

Important Note!
This is old stuff, I've not gone through these steps on a Red Hat box since 2005-2006 or so. I used a process like this with RH 9 - FC 3 or so, and RH AS 3. I keep these instructions online for historical purposes. Be forewarned if something doesn't work...

It is (or at least was) possible to lean on Red Hat scripts to complete the openssl dirty work. Check out Red Hat's instructions: http://www.redhat.com/docs/manuals/linux/RHL-9-Manual/custom-guide/ch-httpd-secure-server.html. In fact, if you follow the steps on that URL (and if they still work), you may not need this document at all.

Perhaps you'd rather use the openssl commands natively. This document requires that you've got a signed server.crt and a server.key file available. You may have just gone through my steps on Creating Certificate Authorities and self-signed SSL certificates.

(1) Copy the server.crt and server.key files into position.

For Red Hat 9/Fedora/AS distros, you'll probably want to use the /etc/httpd/conf/ssl.crt and /etc/httpd/conf/ssl.key directories.

cp server.crt /etc/httpd/conf/ssl.crt
cp server.key /etc/httpd/conf/ssl.key

(2) Turn on the SSL engine and properly reference the server.crt and server.key files.

Make sure the engine is on and referencing the server.crt and server.key files you moved into place at an earlier step. Of course it's possible to select different directory locations for the .crt and .key files. Always make sure you manage their permissions very carefully.

You may be tweaking /etc/httpd/conf.d/httpd.conf. As I recall from years past, Red Hat did (still does?) have a separate file for SSL configuration: ssl.conf. This separate file is "included" by the main httpd.conf file for parsing by Apache at start time. So at this point you'll need to hunt around a bit to determine which file contains the appropriate settings.

SSLEngine on

SSLCertificateFile /etc/httpd/ssl.crt/server.crt
SSLCertificateKeyFile /etc/httpd/ssl.key/server.key

(3) Instruct Apache to listen to port 443.

You can listen to a different port, although 443 is the default for https. Replace the x's below with your IP or DNS name if you have one.

Listen xxx.xxx.xxx.xxx:443

Red Hat should already be loading the ssl module, have the engine turned on, and be listening to 443. But you should double-check and examine the next settings detailed below as well.

LoadModule ssl_module modules/mod_ssl.so

(4) Configure the SSL virtual host.

Various tweaks here. For example, you'll probably want to create a separate directory from which to serve ssl web pages (DocumentRoot). Perhaps /var/www/html for port 80 material, and /var/www-ssl/html for SSL delivered pages. Create those directories if they don't exist, and place a basic index.html SSL web page in it for testing purposes.

<VirtualHost _default_:443>

DocumentRoot "/var/www-ssl/html"

ServerName xxx.xxx.xxx.xxx:443

Restart apache:

cd /etc/init.d
./httpd restart

Done -- test it out.

Friday, May 4, 2012

Red Hat / CentOS VSFTPD FTP Server Configuration


Vsftpd (Very Secure FTP Daemon) is an FTP server for UNIX-like systems, including CentOS / RHEL / Fedora and other Linux distributions. It supports IPv6, SSL, locking users to their home directories and many other advanced features.
In this guide you will learn:
  1. Setup vsftpd to Provide FTP Service.
  2. Configure vsftpd.
  3. Configure Firewalls to Protect the FTP Server.
  4. Configure vsftpd with SSL/TLS.
  5. Setup vsftpd as Download Only Anonymous Internet Server.
  6. Setup vsftpd With Virtual Users and Much More.

VSFTPD offer security, performance and stability over other servers. A quick list of vsftpd features:
  1. Virtual IP configurations
  2. Virtual users
  3. Run as standalone or inetd / xinetd operation
  4. Per-user configuration
  5. Bandwidth throttling
  6. Per-source-IP configurability
  7. Per-source-IP limits
  8. IPv6 ready
  9. Encryption support through SSL integration
  10. And much more.

Install Vsftpd FTP Server

Install the vsftpd package via yum command:
# yum install vsftpd

Vsftpd Defaults

  1. Default port: TCP / UDP - 21 and 20
  2. The main configuration file: /etc/vsftpd/vsftpd.conf
  3. Users that are not allowed to login via ftp: /etc/vsftpd/ftpusers

Configure Vsftpd Server

Open the configuration file, type:
# vi /etc/vsftpd/vsftpd.conf
Turn off standard ftpd xferlog log format:
xferlog_std_format=NO
Turn on verbose vsftpd log format. The default vsftpd log file is /var/log/vsftpd.log:
log_ftp_protocol=YES
Above to directives will enable logging of all FTP transactions. Lock down users to their home directories:
chroot_local_user=YES
Create warning banners for all FTP users:
banner_file=/etc/vsftpd/issue
Create /etc/vsftpd/issue file with a message compliant with the local site policy or a legal disclaimer:
NOTICE TO USERS
Use of this system constitutes consent to security monitoring and testing.
All activity is logged with your host name and IP address.

Turn On Vsftpd Service

Turn on vsftpd on boot:
# chkconfig vsftpd on
Start the service:
# service vsftpd start
# netstat -tulpn | grep :21

Configure Iptables To Protect The FTP Server

Open file /etc/sysconfig/iptables, enter:
# vi /etc/sysconfig/iptables
Add the following lines, ensuring that they appear before the final LOG and DROP lines for the RH-Firewall-1-INPUT:
-A RH-Firewall-1-INPUT -m state --state NEW -p tcp --dport 21 -j ACCEPT
Open file /etc/sysconfig/iptables-config, enter:
# vi /etc/sysconfig/iptables-config
Ensure that the space-separated list of modules contains the FTP connection tracking module:
IPTABLES_MODULES="ip_conntrack_ftp"
Save and close the file. Restart firewall:
# service iptables restart

Tip: View FTP Log File

Type the following command:
# tail -f /var/log/vsftpd.log
Sample output:
Thu May 21 11:40:31 2009 [pid 42298] FTP response: Client "10.1.3.108", "530 Please login with USER and PASS."
Thu May 21 11:40:36 2009 [pid 42298] FTP command: Client "10.1.3.108", "USER vivekda"
Thu May 21 11:40:36 2009 [pid 42298] [vivek] FTP response: Client "10.1.3.108", "331 Please specify the password."
Thu May 21 11:40:38 2009 [pid 42298] [vivek] FTP command: Client "10.1.3.108", "PASS
"
Thu May 21 11:40:38 2009 [pid 42297] [vivek] OK LOGIN: Client "10.1.3.108"
Thu May 21 11:40:38 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "230 Login successful."
Thu May 21 11:40:38 2009 [pid 42299] [vivek] FTP command: Client "10.1.3.108", "SYST"
Thu May 21 11:40:38 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "215 UNIX Type: L8"
Thu May 21 11:40:39 2009 [pid 42299] [vivek] FTP command: Client "10.1.3.108", "PORT 10,1,3,108,162,253"
Thu May 21 11:40:39 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "200 PORT command successful. Consider using PASV."
Thu May 21 11:41:05 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "150 Ok to send data."
Thu May 21 11:41:06 2009 [pid 42299] [vivek] OK UPLOAD: Client "10.1.3.108", "/windows-7-too-many-programs.png", 8957 bytes, 6.70Kbyte/sec
Thu May 21 11:41:06 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "226 File receive OK."
Thu May 21 11:41:10 2009 [pid 42299] [vivek] FTP command: Client "10.1.3.108", "TYPE A"
Thu May 21 11:41:10 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "200 Switching to ASCII mode."
Thu May 21 11:41:11 2009 [pid 42299] [vivek] FTP command: Client "10.1.3.108", "PORT 10,1,3,108,217,96"
Thu May 21 11:41:11 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "200 PORT command successful. Consider using PASV."
Thu May 21 11:41:11 2009 [pid 42299] [vivek] FTP command: Client "10.1.3.108", "LIST"
Thu May 21 11:41:11 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "150 Here comes the directory listing."
Thu May 21 11:41:11 2009 [pid 42299] [vivek] FTP response: Client "10.1.3.108", "226 Directory send OK."

Tip: Restrict Access to Anonymous User Only

Edit the vsftpd configuration file /etc/vsftpd/vsftpd.conf and add the following:
local_enable=NO

Tip: Disable FTP Uploads

Edit the vsftpd configuration file /etc/vsftpd/vsftpd.conf and add the following:
write_enable=NO

Security Tip: Place the FTP Directory on its Own Partition

Separation of the operating system files from FTP users files may result into a better and secure system. Restrict the growth of certain file systems is possible using various techniques. For e.g., use /ftp partition to store all ftp home directories and mount ftp with nosuid, nodev and noexec options. A sample /etc/fstab enter:
/dev/sda5  /ftp          ext3    defaults,nosuid,nodev,noexec,usrquota 1 2
Disk quota must be enabled to prevent users from filling a disk used by FTP upload services. Edit the vsftpd configuration file. Add or correct the following configuration options to represents a directory which vsftpd will try to change into after an anonymous login:
anon_root=/ftp/ftp/pub

Kick Start Server


This is a quick tutorial on how to setup an Apache based Kickstart install server for provisioning Red Hat or CentOS hosts in your environment. By Kickstarting a host/s you can save time and standardize your environment by defining a configuration file that all hosts will use to perform automated installs.

1. Head over to centos.org and download the iso of the CentOS release you are interested in. I will be using CentOS 5.4 for the purposes of this tutorial.
2. Install Apache.
Check your system for Apache being installed using:
[root@kickstart kickstart]# rpm -qa |grep -i httpd
If nothing returns issue:
yum -y install httpd
This should download and install the dependencies for Apache.
3. Create a install root where we will be installing the contents of the cdrom to. I’ll be using the default document root in /var/www/html.
mkdir /var/www/html/centos5
4. Mount the iso you downloaded to a mount point.
[root@kickstart iso]# mount -o loop CentOS-5.4-i386-bin-DVD.iso /mnt
5. Copy the contents of the iso into the directory you created.
cp -ar /mnt/* /var/www/html/centos5/
6. Create a directory to house your kickstart configurations. Once again I’ll be using Apache’s default document root of /var/www/html. I will be creating a directory called ks to store my configurations.
mkdir /var/www/html/ks
7. Create the kickstart configuration file. I named my configuration ks.cfg and dropped it in the ks directory we created in step 6. Here is what I use for my kickstart profile. Very minimal config.
text
install
url --url http://192.168.3.128/centos5
lang en_US.UTF-8
keyboard us
langsupport --default=en_US.UTF-8 en_US.UTF-8
network --device eth0 --bootproto dhcp
rootpw --iscrypted $1$/KEoeArl$f5TokNUdzGIqlvRCLFWW9/
firewall --disabled
selinux --disabled
authconfig --enableshadow --enablemd5
timezone America/New_York
bootloader --location=mbr --append="console=xvc0"
#
zerombr yes
clearpart --all
part /boot --asprimary --fstype="ext3" --size=100 --bytes-per-inode=4096
part swap --asprimary --fstype="swap" --recommended --bytes-per-inode=4096
part / --asprimary --fstype="ext3" --grow --size=1 --bytes-per-inode=4096
reboot
#
%packages --nobase
authconfig
crontabs
kbd
kudzu
man
ntp
openssh-clients
openssh-server
passwd
pciutils
rootfiles
rpm
system-config-securitylevel-tui
traceroute
yum
yum-updatesd
vim-minimal
vixie-cron
which
wget
unzip
kudzu
man
ntp
openssh-clients
openssh-server
passwd
pciutils
rootfiles
rpm
system-config-securitylevel-tui
traceroute
yum
yum-updatesd
vim-minimal
vixie-cron
which
wget
unzip
sudo
%post
(
chkconfig --level 3 ip6tables off
chkconfig --level 3 kudzu off
chkconfig --level 3 netfs off
chkconfig --level 3 yum-updatesd off
#
useradd -p 'myreallycomplexpass' someuser
)  2&gt;&amp;1 | tee /root/post-install.log
8. Use the dvd you downloaded or grab a copy of the boot.iso from the install root. You can either use the install DVD iso you or use the 10MB boot.iso located in centos5/images/boot.iso I choose to use the boot.iso since its 10MB and is easily distributable.
9. Start up the Apache process
[root@kickstart images]# service httpd start
Starting httpd:                                            [  OK  ]
10. Now for the Moment of truth. Boot the system with boot.iso or install DVD. At the boot prompt enter:
linux ks=http://your_kickstart_ip/ks/ks.cfg
If all went well the system should boot and fetch the kickstart config. Then the installation will begin hands off.