Apache: Difference between revisions

From Lolly's Wiki
Jump to navigationJump to search
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 3: Line 3:
== Create certificate ==
== Create certificate ==
===Simple script===
===Simple script===
<source lang=Shell scripts>
<syntaxhighlight lang=bash>
#!/bin/bash
#!/bin/bash


Line 51: Line 51:
IFS=${OLD_IFS}
IFS=${OLD_IFS}
printf "Put this in your Apache config:\n\n\tSSLCertificateFile    %s\n\tSSLCertificateKeyFile %s\n\n" "${CRT}" "${KEY}"
printf "Put this in your Apache config:\n\n\tSSLCertificateFile    %s\n\tSSLCertificateKeyFile %s\n\n" "${CRT}" "${KEY}"
</source>
</syntaxhighlight>


===Adjust the OpenSSL default values===
===Adjust the OpenSSL default values===
Set the country, etc. to values that match your needs:
Set the country, etc. to values that match your needs:
<source lang=bash>
<syntaxhighlight lang=bash>
# vi /etc/ssl/openssl.cnf
# vi /etc/ssl/openssl.cnf
</source>
</syntaxhighlight>


===Generate key===
===Generate key===
<source lang=bash>
<syntaxhighlight lang=bash>
# openssl ecparam -genkey -name secp256r1 | openssl ec -aes256 -out server.de.ec-key
# openssl ecparam -genkey -name secp256r1 | openssl ec -aes256 -out server.de.ec-key
read EC key
read EC key
Line 67: Line 67:
Enter PEM pass phrase:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
</source>
</syntaxhighlight>


If you don't need a password protected encrypted key file, you can remove the encryption like this:
If you don't need a password protected encrypted key file, you can remove the encryption like this:


<source lang=bash>
<syntaxhighlight lang=bash>
# openssl ec -in server.de.ec-key -out server.de.ec-key
# openssl ec -in server.de.ec-key -out server.de.ec-key
read EC key
read EC key
Enter PEM pass phrase:
Enter PEM pass phrase:
writing EC key
writing EC key
</source>
</syntaxhighlight>


===Issue certificate===
===Issue certificate===
<source lang=bash>
<syntaxhighlight lang=bash>
# openssl req -new -x509 -sha256 -key server.de.ec-key -out server.de-wildcard.pem -days 1825 -nodes
# openssl req -new -x509 -sha256 -key server.de.ec-key -out server.de-wildcard.pem -days 1825 -nodes


Line 96: Line 96:
Common Name (e.g. server FQDN or YOUR name) []:*.server.de
Common Name (e.g. server FQDN or YOUR name) []:*.server.de
Email Address [ssl@server.de]:
Email Address [ssl@server.de]:
</source>
</syntaxhighlight>


===View certificate===
===View certificate===
<source lang=bash>
<syntaxhighlight lang=bash>
# openssl x509 -text -noout -in server.de-wildcard.pem
# openssl x509 -text -noout -in server.de-wildcard.pem
Certificate:
Certificate:
Line 127: Line 127:
     Signature Algorithm: ecdsa-with-SHA256
     Signature Algorithm: ecdsa-with-SHA256
         ...
         ...
</source>
</syntaxhighlight>


==Configuring Apache==
==Configuring Apache==
=== Serving mp4 media files ===
=== Serving mp4 media files ===
If your media files are on a network filesystem like CIFS or NFS you should disable memory mapping (EnableMMAP Off) to avoid corrupted data at the client side and allow seeking inside the video.
If your media files are on a network filesystem like CIFS or NFS you should disable memory mapping (EnableMMAP Off) to avoid corrupted data at the client side and allow seeking inside the video.
<source lang=apache>
<syntaxhighlight lang=apache>
<Directory /var/www/media-files>
<Directory /var/www/media-files>
         Options -Indexes
         Options -Indexes
Line 144: Line 144:
         EnableMMAP Off
         EnableMMAP Off
</Directory>
</Directory>
</source>
</syntaxhighlight>


=== SSL configuration ===
=== SSL configuration ===
/etc/apache2/mods-available/ssl.conf
/etc/apache2/mods-available/ssl.conf
<source lang=apache>
<syntaxhighlight lang=apache>
<IfModule mod_ssl.c>
<IfModule mod_ssl.c>
...
...
Line 155: Line 155:
...
...
</IfModule>
</IfModule>
</source>
</syntaxhighlight>


<source lang=apache>
<syntaxhighlight lang=apache>
<VirtualHost ssl.server.de:443>
<VirtualHost ssl.server.de:443>
     # ...
     # ...
Line 217: Line 217:
     </IfModule>
     </IfModule>
</VirtualHost>
</VirtualHost>
</source>
</syntaxhighlight>


===SSLLabs A+ with all 100%===
===SSLLabs A+ with all 100%===
'''If you consider to take this snippet be warned. Old clients have no chance to reach the server.'''
'''If you consider to take this snippet be warned. Old clients have no chance to reach the server.'''
<source lang=apache>
<syntaxhighlight lang=apache>
<VirtualHost ssl.server.de:443>
<VirtualHost ssl.server.de:443>
   ...
   ...
Line 249: Line 249:
   ...
   ...
</VirtualHost>
</VirtualHost>
</source>
</syntaxhighlight>


==Client certificates==
==Client certificates==


<source lang=apache>
<syntaxhighlight lang=apache>
   #
   #
   ## <ClientCertificate>
   ## <ClientCertificate>
Line 276: Line 276:
   ## </ClientCertificate>
   ## </ClientCertificate>
   #
   #
</source>
</syntaxhighlight>


==ApacheTop==
==ApacheTop==


Top of all sites on your host:
Top of all sites on your host:
<source lang=bash>
<syntaxhighlight lang=bash>
# ls  /var/log/apache2/*.log | xargs -n 1 echo -f | xargs apachetop
# ls  /var/log/apache2/*.log | xargs -n 1 echo -f | xargs apachetop
</source>
</syntaxhighlight>

Latest revision as of 14:59, 25 November 2021


Create certificate

Simple script

#!/bin/bash

BASE_SUBJECT='/C=DE/ST=Hamburg/L=Hamburg/O=MyOrg/OU=IT'
BASEDIR=/etc/apache2
DAYS=$[ 5 * 365 ]
KEY_DIR=${BASEDIR}/ssl.key
CRT_DIR=${BASEDIR}/ssl.crt

if [ $# -eq 0 ]
then
  printf "usage: $0 <webserver-name> [<alias1> <alias2>...]\n"
  exit 1
fi  

CN=$1
declare -a subject_alt_names;
for i in ${*}
do
  subject_alt_names=( ${subject_alt_names[*]} "DNS:${i}")
done
echo ${subject_alt_names[*]}

SHORT=${CN%%.*}
KEY=${KEY_DIR}/${SHORT}.key
CRT=${CRT_DIR}/${SHORT}.crt

OLD_IFS=${IFS}
IFS=","
openssl req \
	-new \
	-days ${DAYS} \
	-newkey rsa:4096bits \
	-sha512 \
	-x509 \
	-nodes \
	-out ${CRT} \
	-keyout ${KEY} \
	-subj "${BASE_SUBJECT}/CN=${CN}" \
	-reqexts SAN \
	-extensions SAN \
	-config <( 
          cat /etc/ssl/openssl.cnf
          printf "[ext]\nbasicConstraints=CA:FALSE,pathlen:0\n[SAN]\n%s\n" \
            "${subject_alt_names:+subjectAltName = ${subject_alt_names[*]}}"
         )
IFS=${OLD_IFS}
printf "Put this in your Apache config:\n\n\tSSLCertificateFile    %s\n\tSSLCertificateKeyFile %s\n\n" "${CRT}" "${KEY}"

Adjust the OpenSSL default values

Set the country, etc. to values that match your needs:

# vi /etc/ssl/openssl.cnf

Generate key

# openssl ecparam -genkey -name secp256r1 | openssl ec -aes256 -out server.de.ec-key
read EC key
using curve name prime256v1 instead of secp256r1
writing EC key
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:

If you don't need a password protected encrypted key file, you can remove the encryption like this:

# openssl ec -in server.de.ec-key -out server.de.ec-key
read EC key
Enter PEM pass phrase:
writing EC key

Issue certificate

# openssl req -new -x509 -sha256 -key server.de.ec-key -out server.de-wildcard.pem -days 1825 -nodes

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) [DE]:
State or Province Name (full name) [Hamburg]:
Locality Name (eg, city) [Hamburg]:
Organization Name (eg, company) [My Site]:
Organizational Unit Name (eg, section) [Sub]:
Common Name (e.g. server FQDN or YOUR name) []:*.server.de
Email Address [ssl@server.de]:

View certificate

# openssl x509 -text -noout -in server.de-wildcard.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: ... (0x...)
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=DE, ST=Hamburg, L=Hamburg, O=My Site, OU=Sub, CN=*.server.de/emailAddress=ssl@server.de
        Validity
            Not Before: Apr 16 09:35:02 2015 GMT
            Not After : Apr 14 09:35:02 2020 GMT
        Subject: C=DE, ST=Hamburg, L=Hamburg, O=My Site, OU=Sub, CN=*.server.de/emailAddress=ssl@server.de
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    ...
                ASN1 OID: prime256v1
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                ...
            X509v3 Authority Key Identifier: 
                keyid:...

            X509v3 Basic Constraints: 
                CA:TRUE
    Signature Algorithm: ecdsa-with-SHA256
         ...

Configuring Apache

Serving mp4 media files

If your media files are on a network filesystem like CIFS or NFS you should disable memory mapping (EnableMMAP Off) to avoid corrupted data at the client side and allow seeking inside the video.

<Directory /var/www/media-files>
        Options -Indexes

        AllowOverride None
        Require all granted

        <IfModule mod_mime>
          AddType video/mp4 .mp4
        </IfModule>
        EnableMMAP Off
</Directory>

SSL configuration

/etc/apache2/mods-available/ssl.conf

<IfModule mod_ssl.c>
...
        SSLUseStapling On
        SSLStaplingCache      "shmcb:${APACHE_RUN_DIR}/stapling_cache(128000)"
...
</IfModule>
<VirtualHost ssl.server.de:443>
    # ...
  
    SSLEngine On
    # Do this only if you are sure you have no old clients
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    # If you need to support old clients use this instead
    # SSLProtocol all -SSLv2 -SSLv3 -TLSv1

    SSLCompression off
    SSLHonorCipherOrder On

    # Do this only if you are sure you have no old clients
    SSLCipherSuite      HIGH:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!AES256+RSA:!AES128:!ADH:!EXP:!SSLv2:!SSLv3:!MEDIUM:!LOW:!NULL:!aNULL

    # If you need to support old clients use this instead
    # SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:HIGH:!DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4:!SSLv2:!SSLv3


    SSLCertificateFile      /etc/letsencrypt/live/ssl.server.de/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/ssl.server.de/privkey.pem

    SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire

    # Generate DH parameters with
    # # openssl dhparam -out /etc/ssl/certs/dhparam_4096.pem 4096
    SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam_4096.pem"
    SSLOpenSSLConfCmd ECDHParameters Automatic
    SSLOpenSSLConfCmd Curves secp521r1:secp384r1:prime256v1

    SetEnvIfNoCase Referer ^https://ssl\.server\.de keep_cookies
    RequestHeader unset Cookie env=!keep_cookies

    <IfModule mod_headers.c>
      # https://kb.sucuri.net/warnings/hardening/headers-x-content-type
      Header set X-Content-Type-Options nosniff

      # https://kb.sucuri.net/warnings/hardening/headers-x-frame-clickjacking
      Header append X-FRAME-OPTIONS "SAMEORIGIN"

      # https://kb.sucuri.net/warnings/hardening/headers-x-xss-protection
      Header set X-XSS-Protection "1; mode=block"

      # Strict Transport Security
      Header always set Strict-Transport-Security "max-age=31556926;"

      # Public Key Pins
      Header always set Public-Key-Pins "max-age=5184000; pin-sha256=\"...\"; pin-sha256=\"...\"; includeSubDomains"
    </IfModule>

    
    <IfModule mod_rewrite.c>
      RewriteEngine On

      # https://kb.sucuri.net/warnings/hardening/http-trace HTTP Trace Method 
      RewriteCond %{REQUEST_METHOD} ^TRACE 
      RewriteRule .* - [F]
    </IfModule>
</VirtualHost>

SSLLabs A+ with all 100%

If you consider to take this snippet be warned. Old clients have no chance to reach the server.

<VirtualHost ssl.server.de:443>
  ...
  # SSL parameters
  SSLEngine On
  SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  SSLCipherSuite  DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA
  SSLHonorCipherOrder on
  SSLUseStapling on
  SSLCompression off
  SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
  SSLCertificateFile      /etc/letsencrypt/live/ssl.server.de/fullchain.pem
  SSLCertificateKeyFile   /etc/letsencrypt/live/ssl.server.de/privkey.pem
  SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"
  SSLOpenSSLConfCmd ECDHParameters Automatic
  SSLOpenSSLConfCmd Curves secp521r1:secp384r1:prime256v1
  <IfModule mod_headers.c>
    # Add security and privacy related headers
    Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
    Header always set Strict-Transport-Security "max-age=31556926; includeSubDomains; preload"
    Header always set X-Frame-Options SAMEORIGIN
    Header always set X-Content-Type-Options nosniff
    Header set X-XSS-Protection "1; mode=block"
    Header set X-Robots-Tag "none"
    SetEnv modHeadersAvailable true
  </IfModule>
  ...
</VirtualHost>

Client certificates

  #
  ## <ClientCertificate>
  #
  SSLVerifyClient none
  SSLCACertificateFile "/var/log/apache2/conf/ca.crt"
  SSLCARevocationFile  "/var/log/apache2/conf/crl.pem"
  SSLCARevocationCheck chain

  CustomLog "/var/log/apache2/logs/ssl_user.log" \
          "%t %h Serial=%{SSL_CLIENT_M_SERIAL}x User=%{SSL_CLIENT_S_DN_CN}x \"%r\" %b"

  <Location />
    SSLVerifyClient      require
    SSLVerifyDepth       10
    SSLOptions           +FakeBasicAuth
    SSLRequireSSL
    SSLRequire       %{SSL_CLIENT_S_DN_O}  eq "Your Organization" \
                 and %{SSL_CLIENT_S_DN_OU} in {"AllowedOU1","AllowedOU2"}
  </Location>
  #
  ## </ClientCertificate>
  #

ApacheTop

Top of all sites on your host:

# ls  /var/log/apache2/*.log | xargs -n 1 echo -f | xargs apachetop