DoD Public Key Enablement (PKE) Quick Reference Guide Securing Apache HTTP with mod_ssl for Linux Contact: PKE_Support@disa.mil URL: https://www.us.army.mil/suite/page/474113 This guide provides instructions for conguring Apache HTTP Server using mod_ssl. This conguration guide assumes the Apache HTTP server, mod_ssl, wget, and openssl are installed. It is highly recommended that Apache HTTP server be set to FIPS Mode. FIPS Mode requires Apache, openssl, and mod_ssl to be built from source. Instructions for building Apache, openssl, and mod_ssl in FIPS mode can be found at http://www.openssl.org/docs/ps/. The steps of this conguration guide should be completed by an administrator account. The following steps are designed for Red Hat Enterprise Linux 5.2, and would have to be tailored for other Linux distributions. 1. Verify HTTP, mod_ssl, wget, and openssl are installed. Note: If any component is not installed, install the component before continuing. Each of the following commands are bolded below. Desired output should be similar to httpd-2.2.3-11.el5_1.3, mod_ssl-2.2.3-11.el5_1.3, wget-1.10.2-7.el5, and openssl-0.9.8b-10.el5. There may be a slight variation in version numbers. rpm -qa grep httpd httpd-2.2.3-11.el5_1.3 rpm -qa grep mod_ssl mod_ssl-2.2.3-11.el5_1.3 rpm -qa grep wget wget-1.10.2-7.el5 rpm -qa grep openssl openssl-0.9.8b-10.el5 2. Create the folder /etc/pki/tls/private/. mkdir p /etc/pki/tls/private/ 3. Create a 1024-bit RSA private key for the Apache server (will be Triple-DES encrypted and PEM formatted). An example of a certicate signing request can be found on page 2 of this document. openssl genrsa -des3 -out /etc/pki/tls/private/dodserverkey.key 1024 4. Backup this server.key le and the pass-phrase entered, in a secure location. The details of this RSA private key by using the following command: openssl rsa -noout -text -in /etc/pki/tls/private/dodserverkey.key Page 1 of 15 4/10/2009
5. Create a Certicate Signing Request (CSR) with the server RSA private key (the output will be PEM formatted). NOTE: An openssl.cnf le must be specied if not in the current path openssl req -new -key /etc/pki/tls/private/dodserverkey.key -out /etc/pki/tls/private/dodserver-pkcs10.csr -cong /etc/pki/tls/openssl.cnf 6. Enter the Fully Qualied Domain Name of the server when OpenSSL prompts for the "CommonName", i.e. when a CSR is generated for a website which will be later accessed via https://www.foo.mil/, enter "www.foo.mil" here. The details of this CSR by using the following command: openssl req -noout -text -in /etc/pki/tls/private/dodserver-pkcs10.csr Example 1: Certicate Signing Request (CSR) Example. Page 2 of 15 4/10/2009
7. Open your web browser and enter the appropriate URL below: https://ca-17.c3pki.chamb.disa.mil/ or https://ca-18.c3pki.den.disa.mil/ (Check with your LRA or RA if you do not know your organization s primary site.) Select Request a Server Certicate. Select Regular SSL Server Enrollment from the Certicate Prole Name list, as shown. 8. A) Select PKCS10 for the Certicate Request Type. B) Copy the Certicate Request into the text box. C) Insert your contact information in the Requestor Name, Requestor Email Address, and Requestor Phone Number text boxes. D) Click Submit. Page 3 of 15 4/10/2009
9. The Certicate Prole window is displayed with your request ID. Provide your RA/LRA with this request ID and any additional forms required by your organization s policy. Note: The RA needs this information to complete the process. 10. Once your certicate has been signed (Approved by you Registration Authority) go to the CA and download the signed server certicate. Save the resulting certicate in Base64 (PEM) format at /etc/pki/tls/certs/dodservercert.cer. 11. Create the folder /etc/pki/tls/certs/ca_certs/. mkdir p /etc/pki/tls/certs/ca_certs/ 12. Navigate to the folder /etc/pki/tls/certs/ca_certs/. cd /etc/pki/tls/certs/ca_certs/ 13. Download the DoD Certicates from http://dodpki.c3pki.chamb.disa.mil or http://dodpki.c3pki.den.disa.mil using wget. Note: There are two les that need to be downloaded. rel3_dodroot_1024.p7b and rel3_dodroot_2048.p7b. To congure your system to use ECA Certicates see Appendix: ECA wget http://dodpki.c3pki.chamb.disa.mil/rel3_dodroot_1024.p7b wget http://dodpki.c3pki.chamb.disa.mil/rel3_dodroot_2048.p7b wget http://dodpki.c3pki.den.disa.mil/rel3_dodroot_1024.p7b wget http://dodpki.c3pki.den.disa.mil/rel3_dodroot_2048.p7b 14. Convert rel3_dodroot_1024.p7b and rel3_dodroot_2048.p7b to pem le format. openssl pkcs7 inform DER outform PEM in rel3_dodroot_1024.p7b out rel3_dodroot_1024.pem print_certs openssl pkcs7 inform DER outform PEM in rel3_dodroot_2048.p7b out rel3_dodroot_2048.pem print_certs Page 4 of 15 4/10/2009
15. Concatenate rel3_dodroot_1024.p7b and rel3_dodroot_2048.p7b to a single pem le. cat *.pem > alldodcerts.pem Note: It is extremely important to verify the authenticity of certicates of the Certicate Authority prior to installation to prevent installing undesired certicates. Use the script gensha1ngerprints.sh from Appendix: gensha1ngerprints.sh to complete the verication process. 16. Run getsha1ingerprints.sh to generate the SHA1 ngerprints. bash /etc/pki/tls/ca_certs/getsha1ngerprints.sh alldodcerts.pem 17. Compare the SHA1 ngerprint of each CA with the SHA1 ngerprint on https://crl.disa.mil/. Go to Appendix: Comparing SHA1 Fingerprints for an example. 18. Create the folder /etc/pki/tls/crls/. mkdir p /etc/pki/tls/crls/ 19. Create getcrl.sh in /etc/pki/tls/crls/. Note: getcrl.sh is an automated CRL download script that can be found in the Appendices section of this document under Appendix: getcrl.sh. 20. Run getcrl.sh by using the following command. bash /etc/pki/tls/crls/getcrl.sh 21. Schedule getcrl.sh to run nightly by using the following command. crontab -e 22. Add the following line to crontab to automatically run the getcrl script everyday at 3AM. In the editor press i to start inserting text. Note: getcrl.sh needs to run every night to pull the latest CRLs. 00 3 * * * /etc/pki/tls/crls/getcrl.sh >> /var/log/getcrl.log 23. Save and Exit crontab by pressing the ESC button and then typing :wq Note: It is extremely important to verify the CRLs are up to date because if the CRLs are expired mod_ssl will deny all clients with certicates from the CA with the expired CRL. Page 5 of 15 4/10/2009
24. Navigate to the httpd conf directory. cd /etc/httpd/conf/ 25. Open httpd.conf with a text editor. vi httpd.conf 26. Verify Include conf.d/*.conf is not commented out or missing. If Include conf.d/*.conf is not present add in the Load cong les from the cong directory section shown here. Load cong les from the cong directory "/etc/httpd/conf.d". Include conf.d/*.conf 27. Save Changes (if made) and Exit httpd.conf. 28. Navigate to the conf.d directory. cd /etc/httpd/conf.d/ 29. Open ssl.conf with a text editor. Note: There are several lines within this le that need to be edited. vi ssl.conf 30. Remove or comment out the default SSLRandomSeed and add the SSLRandomSeed value for the startup le and connect le. SSLRandomSeed startup le:/dev/urandom 256 SSLRandomSeed connect builtin SSLRandomSeed startup le:/dev/random 512 SSLRandomSeed connect le:/dev/random 512 SSLRandomSeed connect le:/dev/urandom 512 SSLRandomSeed startup le:/dev/urandom 1024 SSLRandomSeed connect le:/dev/urandom 1024 Page 6 of 15 4/10/2009
31. Verify SSLEngine is set to on. If SSLEngine is set to off, then remove or comment out the SSLEngine off and added SSLEngine on. SSL Engine Switch: Enable/Disable SSL for this virtual host. SSLEngine off SSLEngine on 32. Remove or comment out the default SSLProtocol and add the SSLProtocol value SSL Protocol support: List the enable protocol levels with which clients will be able to connect. Disable SSLv2 access by default: SSLProtocol all -SSLv2 SSLProtocol +SSLv3 +TLSv1 33. Remove or comment out the default SSLCipherSuite and add the SSLCipherSuite value :-ALL:3DES:+SHA1:+SHA:+SSLv3:+TLSv1:!MD5:!DH:!MEDIUM:!LOW:!SSLv2:!NULL SSL Cipher Suite: List the ciphers that the client is permitted to negotiate. See the mod_ssl documentation for a complete list. SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW SSLCipherSuite 3DES:AES:SHA1:SHA:SSLv3:TLSv1:!DES:!MD5:!DH:!MEDIUM:!LOW:!SSLv2:!NULL 34. Remove or comment out the default Server Certicate and add the DoD Issued Server Certicate by location. Server Certicate: Point SSLCerticateFile at a PEM encoded certicate. If the certicate is encrypted, then you will be prompted for a pass phrase. Note that a kill -HUP will prompt again. A new certicate can be generated using the genkey(1) command. SSLCerticateFile /etc/pki/tls/certs/localhost.crt SSLCerticateFile /etc/pki/tls/certs/dodservercert.cer 35. Remove or comment out the default Server Certicate Private Key and add the DoD Issued Server Certicate Private Key by location. Server Private Key: If the key is not combined with the certicate, use this directive to point at the key le. Keep in mind that if you've both a RSA and a DSA private key you can congure both in parallel (to also allow the use of DSA ciphers, etc.) SSLCerticateKeyFile /etc/pki/tls/private/localhost.key SSLCerticateKeyFile /etc/pki/tls/private/dodserverkey.key Page 7 of 15 4/10/2009
36. Remove or comment out the default Server Certicate Chain. Server Certicate Chain: Point SSLCerticateChainFile at a le containing the concatenation of PEM encoded CA certicates which form the certicate chain for the server certicate. Alternatively the referenced le can be the same as SSLCerticateFile when the CA certicates are directly appended to the server certicate for convinience. SSLCerticateChainFile /etc/pki/tls/certs/server-chain.crt 37. Remove or comment out the default Certicate Authority File and add the Certicate Authority File Created in Step 3 by location. Certicate Authority (CA): Set the CA certicate verication path where to nd CA certicates for client authentication or alternatively one huge le containing all of them (le must be PEM encoded) SSLCACerticateFile /etc/pki/tls/certs/ca-bundle.crt SSLCACerticateFile /etc/pki/tls/certs/ alldodcerts.pem 38. Under the Certicate Authority section, add the Revocation Path /etc/pki/tls/crls/. Certicate Authority (CA): Set the CA certicate verication path where to nd CA certicates for client authentication or alternatively one huge le containing all of them (le must be PEM encoded) SSLCACerticateFile /etc/pki/tls/certs/ca-bundle.crt SSLCACerticateFile /etc/pki/tls/certs/alldodcerts.pem SSLCARevocationPath /etc/pki/tls/crls/ 39. Change SSLVerifyClient to require and verify SSLVerifyDepth is 3 or higher. Client Authentication (Type): Client certicate verication type and depth. Types are none, optional, require and optional_no_ca. Depth is a number which species how deeply to verify the certicate issuer chain before deciding the certicate is not valid. SSLVerifyClient require SSLVerifyDepth 10 Page 8 of 15 4/10/2009
40. Verify SSLOptions is set to +StrictRequire. If SSLOptions is not set to +StrictRequire, then remove or comment out the SSLOptions and added SSLOptions +StrictRequire. SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire <Files ~ "\.(cgi shtml phtml php3?)$"> SSLOptions +StdEnvVars </Files> <Directory "/var/www/cgi-bin"> SSLOptions +StdEnvVars </Directory> SSLOptions +StrictRequire 41. Save Changes and Exit ssl.conf. 42. The httpd service needs to be restarted before changes from httpd.conf and ssl.conf can take effect. service httpd restart The Apache Web Server should now be congured for SSL using mod_ssl. Appendices Appendix: New DoD CA Certicates The DoD PKI will occasionally add new CAs to issue certicates. When new CAs goes online the new CA certicates need to be added to the server so users with certicates from the new CAs are able to authenticate to the web servers. Remove alldodcerts.pem that was created in Step 15. Then Repeat Steps 12-15 to add the CAs to the server. Appendix: ECA Certicates The ECA program was created for subscribers that need to conduct business with the U.S. Government. If this webserver needs to provide access to users who have ECA certicates follow the steps with in this Appendix. NOTE: Unless there is a need to provide access to ECA users, it is not recommended that the steps outlined in this appendix be performed. Page 9 of 15 4/10/2009
1. Download the ECA Certicates from http://dodpki.c3pki.chamb.disa.mil or http://dodpki.c3pki.den.disa.mil using wget. wget http://dodpki.c3pki.chamb.disa.mil/dodeca.p7b wget http://dodpki.c3pki.den.disa.mil/dodeca.p7b 2. Convert dodeca.p7b to pem le format. openssl pkcs7 inform DER outform PEM in dodeca.p7b out dodeca.pem print_certs 3. Concatenate dodeca.p7b, rel3_dodroot_1024.p7b, and rel3_dodroot_2048.p7b to a single pem le. cat *.pem > alldodcerts.pem Note: After completing this Appendix return to Step 17 and complete the rest of this guide. Appendix: gensha1ngerprints.sh 1. Create the script gensha1ngerprints.sh in /etc/pki/tls/certs/ca_certs/ vi gensha1ngerprints.sh 2. Add the following text to gensha1ngerprints.sh!/bin/bash DISA PKE Engineering Support pke_support@disa.mil Author: Brannon Biehl Date: October 2008 Contributors: Jeff Hensley, DoD PKE Engineering This script generates the SHA1 ngerprints for pem formatted pkcs11 les. This script is designed to be used with https://crl.disa.mil to compare the ngerprints of the CA Certicates. if [[ -z "$1" ]]; then echo Please specify a.pem le as a command line argument. echo Usage: $0 [pem le] exit 1 pkcs7le=$1 if [[ -n `grep "subject=" $1` ]]; then Page 10 of 15 4/10/2009
rm -f /tmp/tmpcert*.tmp awk '/subject=/{n++}{print > "/tmp/tmpcert" n ".tmp"}' $pkcs7le cd /tmp for a in `ls /tmp/tmpcert*.tmp`; do casubject=`cat $a grep "subject="` openssl x509 -inform PEM -outform DER -in $a -out "$a.der" echo -e "$casubject \n SHA1:`sha1sum $a.der`" done rm -f /tmp/tmpcert*.tmp rm -f /tmp/tmpcert*.tmp.der else echo ERROR: Invalid le. Please read the documentation on how to create an echo input le for $0 from a PKCS7 le. 3. Save gensha1ngerprints.sh by pressing Esc, typing :wq and then pressing Enter :wq Appendix: Comparing SHA1 Fingerprints gensha1ngerprints.sh DoD CLASS 3 Root CA s Fingerprint subject=/c=us/o=u.s. Government/OU=DoD/OU=PKI/CN=DoD CLASS 3 Root CA SHA1:10f193f340ac91d6de5f1edc006247c4f25d9671 /tmp/tmpcert1.tmp.der https://crl.disa.mil DoD CLASS 3 Root CA s Fingerprint Page 11 of 15 4/10/2009
Appendix: getcrl.sh 1. Create the script getcrl.sh in /etc/pki/tls/crls/ vi getcrl.sh 2. Add the following text to getcrl.sh!/bin/bash CRL retrieval script for Apache HTTP Server with mod_ssl DISA PKE Engineering <dod_support at disa.mil> Date: April 9, 2009 Version: 1.11 Website: https://www.us.army.mil/suite/page/474113 Installation: Make sure you dos2unix this script before running it Execution: Execute by running "bash getcrls.sh" Usage: No arguments are required Result: Current DOD CRLs NOTE: This script copies CRLs to a default destination specied by SSLCARevocationPath. This location will be different depending on which version of linux and/or apache you are running. Use the mod_ssl directive "SSLCARevocationPath" to specify this location. For more information see: http://www.modssl.org/docs/2.8/ssl_reference.htmltoc15 NOTICE: This script should NOT be run more frequently than every 24 hours due to bandwidth constraints and the DODs CRL update frequency. RECOMMENDATION: Schedule this script to run nightly from 2AM to 5AM. Add the following cron entry with "crontab -e" (remove the comment character) 0 3 * * * /path/to/apache-crl/script/getcrls.sh > /var/log/httpd/getcrls.log 2>&1 If you are seeing ERRORs that wget or openssl don't exist on the system when running these scripts as a cronjob - wget or openssl are probably installed in a non-default path and you will need to include a path declaration in the front of your cron declarations. By default the cron path is /usr/bin:/bin The folder specied in the Apache SSLCARevocationPath Directive for CRLs. This is typically can be found in the /etc/httpd/conf.d/ssl.conf le. Do not place a trailing / after the path. SSLCARevocationPath=/etc/pki/crls Page 12 of 15 4/10/2009
begin CRLdistributionPoints block Include all CRL Distribution Points here. HTTP and HTTPS only. Every URL will be downloaded. Beware of multiple queries for the same CRL unless absolutely necessary. mod_ssl will not check a CRL if the CRL doesn't exist. Be very careful of this! it is RECOMMENDED that allcrls.zip is downloaded for DoD CRLs because it will include all future CA CRLs. NOTE: a trailing " \" is required after each entry that appears on a new line CRLdistributionPoints="\ http://crl.disa.mil/getcrlzip?all+crl+zip \ " Add additional CRLdistributionPoints if necessary https://local.crlcaching.server/getcrlzip?all+crl+zip \ end CRLdistributionPoints block echo " Running $1 at `date` " Check if binaries exist. This is important when running as cron check4binaries () { if! command -v $1>/dev/null 2>&1; then echo ERROR: $1 is not installed or is not in the path. exit 1 } check4binaries check4binaries openssl check4binaries gunzip check4binaries unzip check4binaries wget Create SSLCARevocationPath if it doesn't exist if! [[ -d $SSLCARevocationPath ]]; then mkdir -p $SSLCARevocationPath cd $SSLCARevocationPath for request in $CRLdistributionPoints; do tmpurl=${request*/} crlfilename="`echo -n $tmpurl sed 's/[getcrlzip,getcrl,+?]//g'`" echo Pulling $request CRL: Saving as $crlfilename Page 13 of 15 4/10/2009
if [[ -f "$crlfilename" ]]; then mv -f $crlfilename $crlfilename.prev > /dev/null 2>&1 Pull CRL wget -nv --output-document=$crlfilename --tries=5 --no-check-certicate "$request" If new CRL was not found then put the old one back in place if [[! -f "$crlfilename" ]]; then mv -f $crlfilename.prev $crlfilename > /dev/null 2>&1 Check if in gzip format if gunzip -t $crlfilename>/dev/null 2>&1; then echo $crlfilename is a valid gzip archive else gunzip CRL after download mv $crlfilename $crlfilename.crl.gz> /dev/null 2>&1 gunzip -d -f $crlfilename.crl.gz mv $crlfilename $crlfilename.crl> /dev/null 2>&1 Check if resulting le is in zip format if unzip -tq $crlfilename.crl>/dev/null 2>&1; then echo $crlfilename is a valid zip archive unzip after download mv $crlfilename.crl $crlfilename.zip> /dev/null 2>&1 unzip -joq $crlfilename.zip done Convert all CRLs to PEM format for a in $( ls *.crl ); do openssl crl -in $a -inform DER -outform PEM -out $a; done Create allcrls.pem if using the mod_ssl SSLCARevocationFile directive. NOTE: You can comment this line out if using the SSLCARevocationPath directive. mv -f allcrls.pem allcrls.pem.bak 2> /dev/null cat *.crl > allcrls.pem Create hashes for the SSLCARevocationPath directive for tcrl in *.crl do crlhash=`openssl crl -in $tcrl -inform PEM -hash -noout`.r0 crlnextupdate=`openssl crl -in $tcrl -inform PEM -nextupdate -noout` echo -e "hash=$crlhash $crlnextupdate $tcrl" Page 14 of 15 4/10/2009
done if [! -L $crlhash ]; then ln -s $tcrl $crlhash 3. Save getcrl.sh by pressing Esc, typing :wq and then pressing Enter :wq Additional Resources: DoDPKE site on DKO at https://www.us.army.mil/suite/page/474113 For questions or comments regarding Public Key Enablement (PKE), please submit information to: pke_support@disa.mil Page 15 of 15 4/10/2009