Dynamiczne DocumentRoot oparte na SSL (uwierzytelnianie klienta)

Sep 12 2020

Obecnie używam uwierzytelniania SSL klienta do ochrony poufnych treści. Użytkownicy muszą zaimportować do swoich przeglądarek certyfikat, który wygenerowaliśmy przy użyciu OpenSSL. Gdy użytkownik odwiedza witrynę, przekierowujemy go na niestandardową stronę 403, jeśli nie ma certyfikatu w swojej przeglądarce lub pęku kluczy systemu operacyjnego. Osiąga się to za pomocą następującej konfiguracji 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>

Chciałbym pójść o krok dalej i wprowadzić pewne warunki, aby załadować określony DocumentRoot, jeśli mają obecny certyfikat, lub inny DocumentRoot, jeśli nie mają certyfikatu klienta.

Podsumowując: website.com

  • Odwiedziny użytkownika A z klientem SSL, obsługuj witrynę website.com z / var / www / has_ssl
  • Odwiedziny użytkownika B bez klienta SSL, obsługuj witrynę internetową.com z / var / www / no_ssl

Mogę użyć %{SSL:SSL_CLIENT_S_DN_CN} =""do przekierowania do ścieżki, jeśli jest pusta, ale nie jestem pewien, jak przepisać DocumentRoot na podstawie obecności certyfikatu.

Walczę z tym od kilku dni. Każda pomoc lub wskazówki są mile widziane.

Odpowiedzi

2 MrWhite Sep 12 2020 at 06:17

AFAIK, nie możesz warunkowo ustawić pliku DocumentRoot. Możesz jednak wewnętrznie przepisać żądanie za pomocą mod_rewrite, w podobny sposób, w jaki zwracasz odpowiedź 403, gdy klient SSL nie jest ustawiony.

Na przykład, jeśli ustawisz:

DocumentRoot /var/www

Następnie wewnętrznie przepisz wszystkie żądania /var/www/has_sslna sukces lub w /var/www/no_sslinny sposób.

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]

Aby zapobiec bezpośredniemu dostępowi do podkatalogów /no_ssllub /has_ssl, można zaimplementować przekierowanie zewnętrzne przed powyższym przepisaniem, które usuwa podkatalog z żądania. Na przykład:

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