DocumentRoot dinâmico baseado em SSL (autenticação do cliente)

Sep 12 2020

Atualmente, uso a autenticação SSL do cliente para proteger conteúdo confidencial. Os usuários são obrigados a importar um certificado para seus navegadores que geramos usando OpenSSL. Quando um usuário visita o site, nós o redirecionamos para uma página 403 personalizada se ele não tiver o certificado em seu navegador ou chaveiro do sistema operacional. Isso é obtido usando a seguinte configuração do Apache.

<VirtualHost *:443>
    ServerName host.tld
    ServerAlias www.host.tld

    ServerAdmin [email protected]
    DocumentRoot /var/www/path

    ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLProtocol             all -SSLv2 -SSLv3

    SSLCertificateFile /etc/ssl/host/host.crt
    SSLCertificateKeyFile /etc/ssl/host.key
    SSLCACertificateFile /etc/ssl/cacert.pem
    SSLVerifyClient optional
    SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    SSLVerifyDepth 10
#   SSLCARevocationPath /etc/ssl/crl
    SSLCARevocationFile /etc/ssl/ca.crl
    SSLCARevocationCheck chain

    RewriteEngine        on
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond     %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
    RewriteRule     .? - [F]
    ErrorDocument 403 /403.html
    
</VirtualHost>

Eu gostaria de dar um passo adiante e apresentar algumas condicionais para carregar um DocumentRoot específico se eles tiverem o certificado presente, ou outro DocumentRoot se eles não tiverem o certificado do cliente.

Em resumo: website.com

  • O usuário A visita com SSL do cliente, serve website.com de / var / www / has_ssl
  • O usuário B visita sem SSL do cliente, serve website.com de / var / www / no_ssl

Posso usar %{SSL:SSL_CLIENT_S_DN_CN} =""para redirecionar para um caminho se estiver vazio, mas não tenho certeza de como reescrever o DocumentRoot com base na presença do certificado.

Venho lutando com isso há alguns dias. Qualquer ajuda ou sugestões são apreciadas.

Respostas

2 MrWhite Sep 12 2020 at 06:17

AFAIK você não pode definir condicionalmente o DocumentRoot. No entanto, você pode reescrever internamente a solicitação usando mod_rewrite, da mesma forma que está retornando uma resposta 403 quando o SSL do cliente não está definido.

Por exemplo, se você definir:

DocumentRoot /var/www

Em seguida, reescrever internamente todas as solicitações para /var/www/has_sslem caso de sucesso ou /var/www/no_sslnão.

RewriteEngine on

RewriteCond %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
RewriteRule ^ /no_ssl%{REQUEST_URI} [L]

RewriteCond %{SSL:SSL_CLIENT_VERIFY} =SUCCESS
RewriteRule ^ /has_ssl%{REQUEST_URI} [L]

Para evitar o acesso direto aos subdiretórios /no_sslou, /has_sslvocê pode implementar um redirecionamento externo antes das regravações acima que removem o subdiretório da solicitação. Por exemplo:

RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule ^/(no_ssl|has_ssl)(.*) /$1 [R=301,L]