Apache tls

Материал из pNp Wiki
Перейти к: навигация, поиск

Конфигурирование Apache. Конфигурация TLS

Предварительные требования

  • Виртуальная машина с двумя сетевыми интерфейсами
  • Установленные пакеты: bash-completion, policycoreutils, policycoreutils-python, policycoreutils-devel, setroubleshoot-server, httpd, httpd-manual, elinks, curl, perl, openssl, mod-ssl, rng-tools

Включение TLS в Apache

Установим mod_ssl

[root@vm-01 ~]# yum install -y mod_ssl crypto-utils

После инсталляции пакета, у нас появился файл /etc/httpd/conf.d/ssl.conf в котором указываются настройки защищенного соединения для вебсервера. Нам нужно дописать в него параметр -SSLv3 в секцию SSLProtocol:

#   SSL Protocol support:
# List the enable protocol levels with which clients will be able to
# connect.  Disable SSLv2 access by default:
SSLProtocol all -SSLv2 -SSLv3

Далее следует создать сертификат. Сделать это можно несколькими способами:

Создание сертификата из командной строки

Помнить все ключи для openssl не обязательно, достаточно поглядеть в имеющихся Makefile'ах:

[root@vm-01 certs]# rpm -ql openssl | head 
/etc/pki/CA
/etc/pki/CA/certs
/etc/pki/CA/crl
/etc/pki/CA/newcerts
/etc/pki/CA/private
/etc/pki/tls/certs/Makefile
/etc/pki/tls/certs/make-dummy-cert
/etc/pki/tls/certs/renew-dummy-cert
/etc/pki/tls/misc/CA
/etc/pki/tls/misc/c_hash
[root@vm-01 certs]#

Посмотрим содержимое /etc/pki/tls/certs/Makefile:

[root@vm-01 certs]# cat /etc/pki/tls/certs/Makefile 
UTF8 := $(shell locale -c LC_CTYPE -k | grep -q charmap.*UTF-8 && echo -utf8)
SERIAL=0
DAYS=365
KEYLEN=2048
TYPE=rsa:$(KEYLEN)

.PHONY: usage
.SUFFIXES: .key .csr .crt .pem
.PRECIOUS: %.key %.csr %.crt %.pem

usage:
	@echo "This makefile allows you to create:"
	@echo "  o public/private key pairs"
	@echo "  o SSL certificate signing requests (CSRs)"
	@echo "  o self-signed SSL test certificates"
	@echo
	@echo "To create a key pair, run \"make SOMETHING.key\"."
	@echo "To create a CSR, run \"make SOMETHING.csr\"."
	@echo "To create a test certificate, run \"make SOMETHING.crt\"."
	@echo "To create a key and a test certificate in one file, run \"make SOMETHING.pem\"."
	@echo
	@echo "To create a key for use with Apache, run \"make genkey\"."
	@echo "To create a CSR for use with Apache, run \"make certreq\"."
	@echo "To create a test certificate for use with Apache, run \"make testcert\"."
	@echo
	@echo "To create a test certificate with serial number other than zero, add SERIAL=num"
	@echo "You can also specify key length with KEYLEN=n and expiration in days with DAYS=n"
	@echo
	@echo Examples:
	@echo "  make server.key"
	@echo "  make server.csr"
	@echo "  make server.crt"
	@echo "  make stunnel.pem"
	@echo "  make genkey"
	@echo "  make certreq"
	@echo "  make testcert"
	@echo "  make server.crt SERIAL=1"
	@echo "  make stunnel.pem SERIAL=2"
	@echo "  make testcert SERIAL=3"

%.pem:
	umask 77 ; \
	PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
	PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
	/usr/bin/openssl req $(UTF8) -newkey $(TYPE) -keyout $$PEM1 -nodes -x509 -days $(DAYS) -out $$PEM2 -set_serial $(SERIAL) ; \
	cat $$PEM1 >  $@ ; \
	echo ""    >> $@ ; \
	cat $$PEM2 >> $@ ; \
	$(RM) $$PEM1 $$PEM2

%.key:
	umask 77 ; \
	/usr/bin/openssl genrsa -aes128 $(KEYLEN) > $@

%.csr: %.key
	umask 77 ; \
	/usr/bin/openssl req $(UTF8) -new -key $^ -out $@

%.crt: %.key
	umask 77 ; \
	/usr/bin/openssl req $(UTF8) -new -key $^ -x509 -days $(DAYS) -out $@ -set_serial $(SERIAL)

TLSROOT=/etc/pki/tls
KEY=$(TLSROOT)/private/localhost.key
CSR=$(TLSROOT)/certs/localhost.csr
CRT=$(TLSROOT)/certs/localhost.crt

genkey: $(KEY)
certreq: $(CSR)
testcert: $(CRT)

$(CSR): $(KEY)
	umask 77 ; \
	/usr/bin/openssl req $(UTF8) -new -key $(KEY) -out $(CSR)

$(CRT): $(KEY)
	umask 77 ; \
	/usr/bin/openssl req $(UTF8) -new -key $(KEY) -x509 -days $(DAYS) -out $(CRT) -set_serial $(SERIAL)
[root@vm-01 certs]#

Для создания crt сертификата нам подойдет нижняя строка, с небольшой модификацией:

[root@vm-01 certs]# /usr/bin/openssl req -new -nodes -x509 -days 365 -out /etc/pki/tls/certs/vm-01.example.com.crt -keyout /etc/pki/tls/private/vm-01.example.com.key 
Generating a 2048 bit RSA private key
........................................+++
........................................+++
writing new private key to '/etc/pki/tls/private/vm-01.example.com.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:RU
State or Province Name (full name) []:Moscow
Locality Name (eg, city) [Default City]:Moscow
Organization Name (eg, company) [Default Company Ltd]:Horns and Hoofs
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:vm-01.example.com
Email Address []:
[root@vm-01 certs]#

Проверим наличие нужных файлов:

[root@vm-01 certs]# ls -lahi /etc/pki/tls/certs/vm-01.example.com.crt 
57343108 -rw-r--r--. 1 root root 1.3K Jan 31 10:00 /etc/pki/tls/certs/vm-01.example.com.crt
[root@vm-01 certs]# ls -lahi /etc/pki/tls/private/vm-01.example.com.key 
34004217 -rw-r--r--. 1 root root 1.7K Jan 31 10:00 /etc/pki/tls/private/vm-01.example.com.key
[root@vm-01 certs]#

Создание сертификата при помощи утилиты genkey

Для ускорения получения случайных данных, следует запустить утилиту rngd:

[root@vm-01 ~]# rngd -r /dev/urandom

После чего, запустить интерактивную утилиту genkey и, ответив на некоторые вопросы, получить сертификат и ключ:

[root@vm-01 ~]# genkey vm-01.example.com
/usr/bin/keyutil -c makecert -g 2048 -s "CN=vm-01.example.com, O=Horns and Hoofs, L=Moscow, ST=Moscow, C=RU" -v 1 -a -z /etc/pki/tls/.rand.28431 -o /etc/pki/tls/certs/vm-01.example.com.crt -k /etc/pki/tls/private/vm-01.example.com.key
cmdstr: makecert

cmd_CreateNewCert
command:  makecert
keysize = 2048 bits
subject = CN=vm-01.example.com, O=Horns and Hoofs, L=Moscow, ST=Moscow, C=RU
valid for 1 months
random seed from /etc/pki/tls/.rand.28431
output will be written to /etc/pki/tls/certs/vm-01.example.com.crt
output key written to /etc/pki/tls/private/vm-01.example.com.key


Generating key. This may take a few moments...

Made a key
Opened tmprequest for writing
/usr/bin/keyutil Copying the cert pointer
Created a certificate
Wrote 1682 bytes of encoded data to /etc/pki/tls/private/vm-01.example.com.key 
Wrote the key to:
/etc/pki/tls/private/vm-01.example.com.key
[root@vm-01 ~]#

Проверим наличие нужных файлов:

[root@vm-01 ~]# ls -lahi /etc/pki/tls/certs/vm-01.example.com.crt 
57343139 -rw-r-----. 1 root root 1.2K Jan 31 12:02 /etc/pki/tls/certs/vm-01.example.com.crt
[root@vm-01 ~]# ls -lahi /etc/pki/tls/private/vm-01.example.com.key 
34004250 -r--------. 1 root root 1.7K Jan 31 12:02 /etc/pki/tls/private/vm-01.example.com.key
[root@vm-01 ~]#

Можно посмотреть содержимое сертификата:

[root@vm-01 certs]# openssl x509 -in /etc/pki/tls/certs/vm-01.example.com.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 14504393413317360002 (0xc949f4f63b4bf982)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=RU, ST=Moscow, L=Moscow, O=Horns and Hoofs, CN=vm-01.example.com
        Validity
            Not Before: Jan 31 07:00:26 2018 GMT
            Not After : Jan 31 07:00:26 2019 GMT
        Subject: C=RU, ST=Moscow, L=Moscow, O=Horns and Hoofs, CN=vm-01.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:dd:e1:1a:35:39:ae:11:1f:d1:69:80:a5:9d:53:
                    ae:6e:e2:33:2c:f3:6c:a6:00:48:fc:8b:ce:95:a9:
                    3c:7e:47:0e:b7:1e:d0:5e:84:5b:4c:55:dd:ee:c7:
                    e5:cc:7c:a0:3b:a9:b2:96:da:5e:88:c0:c4:4a:d5:
                    4c:50:29:0d:97:ce:fa:6b:59:47:91:c1:97:1e:71:
                    78:d5:1b:47:fd:97:53:a6:cc:5c:c6:77:26:67:b0:
                    cf:8e:cd:f0:4f:26:d1:b2:41:22:ef:3e:82:1f:4f:
                    8c:c5:64:78:91:00:7a:02:a0:89:50:16:7b:4b:ad:
                    27:3f:8d:de:b3:01:e9:db:df:ec:02:b7:7b:d0:93:
                    08:7e:4e:42:c5:ec:c8:fa:88:89:92:fd:d0:fa:7d:
                    2f:3a:02:ec:9f:67:7c:19:4d:d2:a5:86:fb:e9:c7:
                    ca:af:39:2f:7b:12:b5:31:56:5c:21:94:e2:57:bd:
                    2f:b1:cc:e7:29:b9:94:0e:bb:1b:4f:b6:5c:19:1e:
                    df:7c:12:d6:74:a7:4a:0a:61:e8:24:a6:34:12:e6:
                    2c:31:88:72:38:b2:8a:85:d4:0b:e7:81:95:52:09:
                    e2:ec:9b:59:a7:cb:00:c7:14:11:ae:ed:10:c3:7a:
                    bf:d9:de:24:68:0a:7d:b8:4b:1d:80:22:15:b0:64:
                    5c:6f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                0D:85:9C:7A:6D:B2:E7:EF:26:A7:E6:A3:05:33:A4:05:4C:36:BF:56
            X509v3 Authority Key Identifier: 
                keyid:0D:85:9C:7A:6D:B2:E7:EF:26:A7:E6:A3:05:33:A4:05:4C:36:BF:56

            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         ae:bb:57:86:46:e8:42:a5:33:50:8e:f5:5e:3e:c0:eb:68:aa:
         b9:3a:7e:4c:be:ba:0e:13:1d:5a:ed:13:c5:26:08:4a:99:5a:
         d4:1f:18:22:d7:e1:12:50:e8:1a:44:5b:7d:0b:dd:e6:04:29:
         4a:c1:ed:b9:4b:e0:56:34:77:0f:61:2f:40:90:a7:fa:82:b0:
         a1:7a:9a:ea:4f:5f:f8:c2:bb:7f:3a:2d:23:bc:92:95:5a:a5:
         bf:d2:e2:74:d2:8f:78:fe:90:dc:92:d6:e4:2f:42:5e:2b:e3:
         55:85:76:a9:bb:2a:0c:5a:c9:80:5a:fe:e4:ae:37:7c:31:54:
         7a:32:4d:c3:7c:2c:13:db:32:37:59:d3:50:6c:ee:83:3c:c1:
         4e:71:4f:a6:73:08:52:4c:97:45:0f:ca:02:82:8b:09:4f:00:
         b6:d5:7b:51:6d:b9:42:eb:24:ae:2d:4e:57:c8:53:3e:cd:17:
         32:00:ae:bb:98:8c:ff:eb:db:fb:5e:d3:7f:e0:93:1f:44:59:
         97:5c:f7:65:76:b1:97:6d:c2:3e:21:49:6e:3d:7e:57:b3:cb:
         b4:3b:d4:13:31:f1:7a:c0:2c:5c:5a:44:d5:0e:45:e4:bf:e7:
         f8:5e:13:35:b2:0a:fd:22:57:6a:a9:f1:5e:e9:11:fc:dc:f0:
         60:1f:0f:58
[root@vm-01 certs]#

Настройка виртуального хоста с поддержкой TLS

Возьмем из файла /etc/httpd/conf.d/ssl.conf секцию VirtualHost

[root@vm-01 certs]# grep "^[^#]" /etc/httpd/conf.d/ssl.conf 
Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost _default_:443>
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

И модифицируем собственные настройки в файле /etc/httpd/conf.d/vm-01.conf, приведя его к следующему виду:

# Virtual Hosts
#
# Required modules: mod_log_config

# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at 
# <URL:http://httpd.apache.org/docs/2.4/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.

#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
<VirtualHost *:443>
    ServerAdmin webmaster@vm-01.example.com
    DocumentRoot "/content"
    ServerName vm-01.example.com
    ServerAlias www.vm-01.example.com

    LogLevel warn
    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3
    SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
    SSLCertificateFile /etc/pki/tls/certs/vm-01.example.com.crt
    SSLCertificateKeyFile /etc/pki/tls/private/vm-01.example.com.key

    ErrorLog "/var/log/httpd/vm-01.example.com-error_log"
    CustomLog "/var/log/httpd/vm-01.example.com-access_log" common
    ScriptAlias /cgi-bin/ "/content/dynamic"
	<Directory "/content">
    		AllowOverride None
    		# Allow open access:
    		Require all granted
	</Directory>
	<Directory "/content/private">
		AuthType basic
		AuthName "Private area! Restricted access"
		AuthUserFile "/etc/httpd/passwd"
		AuthGroupFile "/etc/httpd/group"
    		Require group webmasters
	</Directory>
	<Directory "/content/dynamic">
		Options ExecCGI  
		SSLOptions +StdEnvVars
		AddHandler cgi-script .cgi .pl
		AllowOverride None
		Require all granted
	</Directory>
</VirtualHost>

Проверяем синтаксис конфигурационного файла:

[root@vm-01 certs]# httpd -t
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.122.158. Set the 'ServerName' directive globally to suppress this message
Syntax OK
[root@vm-01 certs]#

Пропишем имя сервера в файл /etc/hosts

[root@vm-01 httpd]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.1 vm-01.example.com

[root@vm-01 httpd]#

И, немного поправим стартовую страницу:

[root@vm-01 httpd]# printf "Hello world.\n$(date)\n" > /content/index.html
[root@vm-01 httpd]#

Запуск

Запускаем сервис:

[root@vm-01 certs]# systemctl restart httpd
[root@vm-01 certs]# systemctl is-active httpd
active
[root@vm-01 certs]#

Проверка

Пропишем имя сервера в файл /etc/hosts

[root@vm-01 httpd]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.1 vm-01.example.com

[root@vm-01 httpd]#

С виртуальной машины vm-02 обратимся к странице при помощи утилиты curl:

[root@vm-02 ~]# curl --insecure "https://vm-01.example.com/"
Hello world.
Wed Jan 31 11:19:20 MSK 2018
[root@vm-02 ~]#

Ссылки

Apache SSL Howto
Setting Up an SSL Server