Apache tls — различия между версиями

Материал из pNp Wiki
Перейти к: навигация, поиск
(Включение TLS в Apache)
(Создание сертификата при помощи cli)
 
(не показано 9 промежуточных версий этого же участника)
Строка 3: Строка 3:
 
==== Предварительные требования ====
 
==== Предварительные требования ====
 
* Виртуальная машина с двумя сетевыми интерфейсами
 
* Виртуальная машина с двумя сетевыми интерфейсами
* Установленные пакеты: <code>bash-completion</code>, <code>policycoreutils</code>, <code>policycoreutils-python</code>, <code>policycoreutils-devel</code>, <code>setroubleshoot-server</code>, <code>httpd</code>, <code>httpd-manual</code>, <code>elinks</code>, <code>curl</code>, <code>perl</code>, <code>openssl</code>, <code>mod-ssl</code>
+
* Установленные пакеты: <code>bash-completion</code>, <code>policycoreutils</code>, <code>policycoreutils-python</code>, <code>policycoreutils-devel</code>, <code>setroubleshoot-server</code>, <code>httpd</code>, <code>httpd-manual</code>, <code>elinks</code>, <code>curl</code>, <code>perl</code>, <code>openssl</code>, <code>mod-ssl</code>, <code>rng-tools</code>
  
 
== Включение TLS в Apache ==
 
== Включение TLS в Apache ==
 
Установим <code>mod_ssl</code>
 
Установим <code>mod_ssl</code>
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
[root@vm-01 ~]# yum install -y mod_ssl
+
[root@vm-01 ~]# yum install -y mod_ssl crypto-utils
 
</syntaxhighlight>
 
</syntaxhighlight>
 
После инсталляции пакета, у нас появился файл <code>/etc/httpd/conf.d/ssl.conf</code> в котором указываются настройки защищенного  
 
После инсталляции пакета, у нас появился файл <code>/etc/httpd/conf.d/ssl.conf</code> в котором указываются настройки защищенного  
соединения для вебсервера. Нам нужно дописать в него параметр <code>-SSLv3</code>:
+
соединения для вебсервера. Нам нужно дописать в него параметр <code>-SSLv3</code> в секцию <code>SSLProtocol</code>:
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
 +
#  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
 +
</syntaxhighlight>
 +
Далее следует создать сертификат. Сделать это можно несколькими способами:
 +
 +
==== Создание сертификата из командной строки ====
 +
Помнить все ключи для openssl не обязательно, достаточно поглядеть в имеющихся <code>Makefile</code>'ах:
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
Посмотрим содержимое <code>/etc/pki/tls/certs/Makefile</code>:
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
Для создания <code>crt</code> сертификата нам подойдет нижняя строка, с небольшой модификацией:
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
Проверим наличие нужных файлов:
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
==== Создание сертификата при помощи утилиты genkey ====
 +
Для ускорения получения случайных данных, следует запустить утилиту <code>rngd</code>:
 +
<syntaxhighlight lang="bash">
 +
[root@vm-01 ~]# rngd -r /dev/urandom
 +
</syntaxhighlight>
 +
После чего, запустить интерактивную утилиту <code>genkey</code> и, ответив на некоторые вопросы, получить сертификат и ключ:
 +
<syntaxhighlight lang="bash">
 +
[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 ~]#
 +
</syntaxhighlight>
 +
Проверим наличие нужных файлов:
 +
<syntaxhighlight lang="bash">
 +
[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 ~]#
 +
</syntaxhighlight>
 +
 +
Можно посмотреть содержимое сертификата:
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
  
 +
==== Настройка виртуального хоста с поддержкой TLS ====
 +
Возьмем из файла <code>/etc/httpd/conf.d/ssl.conf</code> секцию <code>VirtualHost</code>
 +
<syntaxhighlight lang="bash">
 +
[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>                                 
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
И модифицируем собственные настройки в файле <code>/etc/httpd/conf.d/vm-01.conf</code>, приведя его к следующему виду:
 +
<syntaxhighlight lang="bash">
 +
# 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>
 +
</syntaxhighlight>
 +
 +
Проверяем синтаксис конфигурационного файла:
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
Пропишем имя сервера в файл <code>/etc/hosts</code>
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
И, немного поправим стартовую страницу:
 +
<syntaxhighlight lang="bash">
 +
[root@vm-01 httpd]# printf "Hello world.\n$(date)\n" > /content/index.html
 +
[root@vm-01 httpd]#
 +
</syntaxhighlight>
 +
 +
==== Запуск ====
 +
Запускаем сервис:
 +
<syntaxhighlight lang="bash">
 +
[root@vm-01 certs]# systemctl restart httpd
 +
[root@vm-01 certs]# systemctl is-active httpd
 +
active
 +
[root@vm-01 certs]#
 +
</syntaxhighlight>
 +
==== Проверка ====
 +
Пропишем имя сервера в файл <code>/etc/hosts</code>
 +
<syntaxhighlight lang="bash">
 +
[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]#
 +
</syntaxhighlight>
 +
С виртуальной машины <code>vm-02</code> обратимся к странице при помощи утилиты <code>curl</code>:
 +
<syntaxhighlight lang="bash">
 +
[root@vm-02 ~]# curl --insecure "https://vm-01.example.com/"
 +
Hello world.
 +
Wed Jan 31 11:19:20 MSK 2018
 +
[root@vm-02 ~]#
 +
</syntaxhighlight>
 +
 +
== Ссылки ==
 +
[https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html Apache SSL Howto]<br />
 +
[https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-web_servers#s2-apache-mod_ssl Setting Up an SSL Server]

Текущая версия на 12:08, 31 января 2018

Конфигурирование 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