Dynamic DocumentRoot ขึ้นอยู่กับ SSL (Client Auth.)

Sep 12 2020

ปัจจุบันฉันใช้การรับรองความถูกต้อง SSL ของไคลเอ็นต์เพื่อปกป้องเนื้อหาที่ละเอียดอ่อน ผู้ใช้จะต้องนำเข้าใบรับรองไปยังเบราว์เซอร์ที่เราสร้างขึ้นโดยใช้ OpenSSL เมื่อผู้ใช้เยี่ยมชมเว็บไซต์เราจะเปลี่ยนเส้นทางไปยังหน้า 403 ที่กำหนดเองหากพวกเขาไม่มีใบรับรองในเบราว์เซอร์หรือพวงกุญแจของระบบปฏิบัติการ ทำได้โดยใช้การกำหนดค่า 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>

ฉันต้องการจะก้าวไปอีกขั้นและแนะนำเงื่อนไขบางประการในการโหลด DocumentRoot เฉพาะหากมีใบรับรองอยู่หรือ DocumentRoot อื่นหากไม่มีใบรับรองไคลเอ็นต์

โดยสรุป: website.com

  • ผู้ใช้ A เข้าชมด้วย Client SSL ให้บริการ website.com จาก / var / www / has_ssl
  • ผู้ใช้ B เข้าชมโดยไม่มีไคลเอนต์ SSL ให้บริการ website.com จาก / var / www / no_ssl

ฉันสามารถใช้%{SSL:SSL_CLIENT_S_DN_CN} =""เพื่อเปลี่ยนเส้นทางไปยังเส้นทางหากว่างเปล่า แต่ฉันไม่แน่ใจว่าจะเขียน DocumentRoot ใหม่ตามใบรับรองที่มีอยู่ได้อย่างไร

ฉันดิ้นรนกับเรื่องนี้มาสองสามวันแล้ว ขอความช่วยเหลือหรือคำแนะนำใด ๆ

คำตอบ

2 MrWhite Sep 12 2020 at 06:17

AFAIK คุณไม่สามารถตั้งค่าDocumentRoot. อย่างไรก็ตามคุณสามารถเขียนคำขอภายในโดยใช้ mod_rewrite ได้ในลักษณะเดียวกับที่คุณส่งคืนการตอบกลับ 403 เมื่อไม่ได้ตั้งค่า SSL ของไคลเอ็นต์

ตัวอย่างเช่นหากคุณตั้งค่า:

DocumentRoot /var/www

จากนั้นเขียนคำขอทั้งหมด/var/www/has_sslภายในอีกครั้งเมื่อประสบความสำเร็จหรือ/var/www/no_sslอย่างอื่น

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]

ในการป้องกันการเข้าถึงโดยตรงไปยังไดเร็กทอรีย่อย/no_sslหรือ/has_sslไดเร็กทอรีย่อยคุณสามารถใช้การเปลี่ยนเส้นทางภายนอกก่อนการเขียนซ้ำด้านบนที่ลบไดเร็กทอรีย่อยออกจากคำขอ ตัวอย่างเช่น:

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