Apache mod_auth_digest ile Güvenli Kimlik Doğrulama

Yıllardır web sunucusu yöneten biri olarak şunu söyleyebilirim: HTTP Basic Authentication kullanıyorsanız ve bunu HTTPS olmadan yapıyorsanız, kullanıcı adı ile parolanızı açık metin olarak internete yayıyorsunuz demektir. mod_auth_digest tam da bu noktada devreye giriyor. Challenge-response mekanizmasıyla çalışan Digest Authentication, parolayı asla düz metin olarak göndermez; bunun yerine bir hash değeri üzerinden kimlik doğrulaması yapar. Bugün Apache üzerinde bu modülü nasıl kurup yapılandıracağınızı, gerçek senaryolarda nasıl kullanacağınızı ve dikkat etmeniz gereken güvenlik noktalarını ele alacağız.

mod_auth_digest Nedir ve Neden Kullanmalısınız?

HTTP Basic Authentication’da tarayıcı, kullanıcı adı ve parolayı Base64 ile encode ederek sunucuya gönderir. Base64 bir şifreleme değildir; decode etmek saniyeler alır. Ağ trafiğinizi izleyen biri bu bilgilere kolayca ulaşabilir.

Digest Authentication ise RFC 2617 ve RFC 7616 standartlarına dayanan daha güvenli bir yöntemdir. Temel mantık şu şekilde işler:

  • İstemci sunucuya bağlanır
  • Sunucu bir “nonce” (tek kullanımlık rastgele değer) gönderir
  • İstemci kullanıcı adı, parola, nonce değeri ve istenen URI’yi birleştirerek MD5 hash hesaplar
  • Bu hash değerini sunucuya gönderir
  • Sunucu aynı hesaplamayı kendi tarafında yaparak doğrular

Bu sayede parola asla ağ üzerinden geçmez. Ancak şunu da belirtmek gerekir: MD5 günümüzde kriptografik olarak zayıf kabul edilir. mod_auth_digest’i production ortamında kullanacaksanız, kesinlikle HTTPS ile birlikte kullanın. HTTPS olmadan bile Basic’ten daha iyi olsa da, modern güvenlik anlayışında HTTPS + Basic Auth veya daha güçlü mekanizmalar tercih edilir. Bunu söyledikten sonra, iç ağ uygulamaları, development ortamları ve legacy sistemler için mod_auth_digest hâlâ değerli bir araçtır.

Modülün Kurulumu ve Etkinleştirilmesi

Çoğu modern Linux dağıtımında mod_auth_digest Apache ile birlikte gelir ama varsayılan olarak etkin olmayabilir. Önce durumu kontrol edelim.

# Modülün yüklü olup olmadığını kontrol et
apache2ctl -M | grep auth_digest

# Ubuntu/Debian sistemlerde modülü etkinleştir
sudo a2enmod auth_digest

# Apache'yi yeniden başlat
sudo systemctl restart apache2

# CentOS/RHEL sistemlerde modül genellikle zaten yüklüdür
# httpd.conf veya /etc/httpd/conf.modules.d/ içinde kontrol edin
grep -r "auth_digest" /etc/httpd/conf.modules.d/

CentOS/RHEL tabanlı sistemlerde modül dosyası genellikle şu şekilde görünür:

# /etc/httpd/conf.modules.d/00-base.conf içinde şu satırın aktif olduğundan emin olun
LoadModule auth_digest_module modules/mod_auth_digest.so

# Modülün fiziksel olarak var olduğunu doğrulayın
ls -la /usr/lib64/httpd/modules/mod_auth_digest.so

Parola Dosyası Oluşturmak: htdigest Komutu

mod_auth_digest, mod_auth_basic’in kullandığı htpasswd dosyalarını kullanmaz. Bunun yerine htdigest aracıyla oluşturulan ayrı bir format kullanır. Dosya formatı şu şekildedir: kullanıcıadı:realm:HA1_hash

Burada realm kritik bir kavramdır. Realm, kullanıcıya gösterilen kimlik doğrulama alanı adıdır ve hash hesaplamasına dahil edilir. Realm değeri değişirse mevcut tüm hash’ler geçersiz hale gelir.

# Parola dosyası oluştur ve ilk kullanıcıyı ekle
# -c parametresi yeni dosya oluşturur, varsa üzerine yazar
sudo htdigest -c /etc/apache2/.htdigest "Yonetim Paneli" admin

# Mevcut dosyaya yeni kullanıcı ekle (-c KULLANMAYIN, dosyayı siler)
sudo htdigest /etc/apache2/.htdigest "Yonetim Paneli" mehmet

# Parola dosyasının içeriğini görüntüleyin
cat /etc/apache2/.htdigest
# Çıktı örneği:
# admin:Yonetim Paneli:a8c4d6e2f1b3c5d7e9f0a1b2c3d4e5f6
# mehmet:Yonetim Paneli:b7d5c3a1f9e7d5c3b1a9f7e5d3c1b9a7

# Dosya güvenliğini ayarlayın
sudo chmod 640 /etc/apache2/.htdigest
sudo chown root:www-data /etc/apache2/.htdigest

Dikkat etmeniz gereken önemli bir nokta: realm değeri Apache yapılandırmasındaki AuthName direktifiyle birebir aynı olmalıdır. Büyük/küçük harf farkı bile hash uyuşmazlığına neden olur.

Temel Apache Yapılandırması

Şimdi gerçek bir senaryo üzerinden gidelim. Diyelim ki şirket içi bir monitoring panelini parola ile korumak istiyorsunuz.

# /etc/apache2/sites-available/monitoring.conf

<VirtualHost *:443>
    ServerName monitoring.sirketiniz.com
    DocumentRoot /var/www/monitoring

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/monitoring.crt
    SSLCertificateKeyFile /etc/ssl/private/monitoring.key

    # Tüm siteyi koru
    <Directory "/var/www/monitoring">
        Options -Indexes +FollowSymLinks
        AllowOverride None

        AuthType Digest
        AuthName "Monitoring Paneli"
        AuthDigestDomain /monitoring/ https://monitoring.sirketiniz.com/
        AuthUserFile /etc/apache2/.htdigest
        Require valid-user
    </Directory>

    # Belirli bir dizini koru
    <Directory "/var/www/monitoring/admin">
        AuthType Digest
        AuthName "Yonetim Paneli"
        AuthDigestDomain /monitoring/admin/
        AuthUserFile /etc/apache2/.htdigest_admin
        Require user superadmin devops_lead
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/monitoring_error.log
    CustomLog ${APACHE_LOG_DIR}/monitoring_access.log combined
</VirtualHost>

Yapılandırmayı doğrulayıp etkinleştirin:

# Yapılandırma sözdizimini kontrol et
sudo apache2ctl configtest

# Siteyi etkinleştir
sudo a2ensite monitoring.conf

# Apache'yi yeniden yükle
sudo systemctl reload apache2

.htaccess ile Dizin Bazlı Koruma

Bazen sunucu yapılandırma dosyasına erişiminiz olmaz ya da belirli bir dizini dinamik olarak korumak istersiniz. .htaccess bu durumda kullanışlıdır. Ancak performans açısından mümkün olduğunda ana yapılandırmayı tercih edin.

Önce AllowOverride direktifini etkinleştirin:

# Apache ana yapılandırmasında veya VirtualHost bloğunda
<Directory /var/www/html>
    AllowOverride AuthConfig
</Directory>

Sonra korunmasını istediğiniz dizine .htaccess dosyası oluşturun:

# /var/www/html/gizli/.htaccess

cat > /var/www/html/gizli/.htaccess << 'EOF'
AuthType Digest
AuthName "Gizli Bolum"
AuthDigestDomain /gizli/
AuthUserFile /etc/apache2/.htdigest_gizli
AuthDigestNonceLifetime 300
Require valid-user
EOF

Burada AuthDigestNonceLifetime direktifi önemlidir. Nonce değerinin geçerlilik süresini saniye cinsinden belirtir. Varsayılan değer 300 saniyedir. Çok kısa tutarsanız kullanıcılar sık sık yeniden kimlik doğrulaması yapmak zorunda kalır; çok uzun tutarsanız replay saldırılarına karşı açık olursunuz.

Grup Bazlı Erişim Kontrolü

Gerçek dünya senaryolarında farklı kullanıcı gruplarına farklı erişim seviyeleri vermeniz gerekebilir. Bir DevOps ekibi için şöyle bir yapı kuralım:

# Grup dosyası oluştur
# /etc/apache2/digest_groups

cat > /etc/apache2/digest_groups << 'EOF'
developers: ali veli ayse
ops: mehmet fatma
admins: superadmin devops_lead
readonly: monitor_user
EOF

# Dosya izinlerini ayarla
sudo chmod 640 /etc/apache2/digest_groups
sudo chown root:www-data /etc/apache2/digest_groups
# VirtualHost yapılandırması

<VirtualHost *:443>
    ServerName devops.sirketiniz.com
    DocumentRoot /var/www/devops

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/devops.crt
    SSLCertificateKeyFile /etc/ssl/private/devops.key

    # Genel geliştirici alanı
    <Directory "/var/www/devops/builds">
        AuthType Digest
        AuthName "DevOps Portal"
        AuthDigestDomain /builds/
        AuthUserFile /etc/apache2/.htdigest_devops
        AuthGroupFile /etc/apache2/digest_groups
        Require group developers ops admins
    </Directory>

    # Sadece ops ve admin erişimi
    <Directory "/var/www/devops/deployments">
        AuthType Digest
        AuthName "DevOps Portal"
        AuthDigestDomain /deployments/
        AuthUserFile /etc/apache2/.htdigest_devops
        AuthGroupFile /etc/apache2/digest_groups
        Require group ops admins
    </Directory>

    # Sadece admin erişimi
    <Directory "/var/www/devops/config">
        AuthType Digest
        AuthName "DevOps Admin"
        AuthUserFile /etc/apache2/.htdigest_devops
        AuthGroupFile /etc/apache2/digest_groups
        Require group admins
    </Directory>

</VirtualHost>

Tüm kullanıcıları ilgili realm ile ekleyin:

# DevOps Portal realm'i için kullanıcıları ekle
for user in ali veli ayse mehmet fatma superadmin devops_lead monitor_user; do
    echo "Kullanıcı ekleniyor: $user"
    sudo htdigest /etc/apache2/.htdigest_devops "DevOps Portal" $user
done

# Admin realm için ayrıca ekle
sudo htdigest /etc/apache2/.htdigest_devops "DevOps Admin" superadmin
sudo htdigest /etc/apache2/.htdigest_devops "DevOps Admin" devops_lead

IP Adresi ile Birleştirme: Çok Katmanlı Güvenlik

Sadece şirket ağından erişim ve parola doğrulamasını birleştirmek çok daha sağlam bir güvenlik katmanı oluşturur.

<Directory "/var/www/intranet">
    AuthType Digest
    AuthName "Intranet Sistemi"
    AuthDigestDomain /
    AuthUserFile /etc/apache2/.htdigest_intranet

    # Require all ile karmaşık kurallar
    # Satisfiy direktifi Apache 2.4'te kaldırıldı, RequireAll/RequireAny kullanın

    <RequireAll>
        # Hem IP hem de kimlik doğrulama şartını zorunlu kıl
        Require ip 192.168.1.0/24 10.0.0.0/8
        Require valid-user
    </RequireAll>
</Directory>

# Alternatif: Şirket içinden direkt giriş, dışarıdan parola iste
<Directory "/var/www/raporlar">
    AuthType Digest
    AuthName "Rapor Sistemi"
    AuthUserFile /etc/apache2/.htdigest_raporlar

    <RequireAny>
        # Şirket içi ağdan parola gerekmez
        Require ip 192.168.0.0/16
        # Dışarıdan parola gerekir
        Require valid-user
    </RequireAny>
</Directory>

Performans Optimizasyonu ve Önbellek Ayarları

mod_auth_digest, mod_auth_basic’e kıyasla biraz daha fazla işlem gücü gerektirir. Nonce değerlerini takip etmek için paylaşımlı bellek kullanır. Bu ayarları doğru yapılandırmak önemlidir.

# /etc/apache2/conf-available/digest_performance.conf

# Nonce için ayrılan paylaşımlı bellek boyutu
# Her nonce yaklaşık 60 byte yer kaplar
# 1000 eş zamanlı kullanıcı için 64KB yeterlidir
AuthDigestShmemSize 64000

# Bu direktif global düzeyde ayarlanır, VirtualHost içinde kullanılamaz
# Yapılandırmayı etkinleştir
sudo a2enconf digest_performance
sudo systemctl reload apache2

# Mevcut mod durumunu ve bellek kullanımını kontrol et
apache2ctl -M | grep -E "auth|cache"

# Apache süreçlerinin bellek kullanımını izle
ps aux | grep apache2 | awk '{sum += $6} END {print "Toplam RSS: " sum/1024 " MB"}'

Günlük Yönetimi ve Sorun Giderme

Authentication sorunlarını debug ederken log seviyeleri kritik önem taşır.

# VirtualHost içinde authentication loglamasını ayrıntılı yap
<VirtualHost *:443>
    # ...

    # Sadece auth modülü için debug log
    LogLevel auth_digest:debug

    # Veya genel debug (dikkatli kullanın, logları şişirir)
    # LogLevel debug

    ErrorLog ${APACHE_LOG_DIR}/auth_error.log
    CustomLog ${APACHE_LOG_DIR}/auth_access.log "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i""
</VirtualHost>

Sık karşılaşılan sorunları ve çözümlerini inceleyelim:

# "Digest: realm mismatch" hatasını araştır
grep "realm mismatch" /var/log/apache2/auth_error.log

# htdigest dosyasındaki realm ile Apache yapılandırmasını karşılaştır
grep "AuthName" /etc/apache2/sites-enabled/*.conf
# ve
cut -d: -f2 /etc/apache2/.htdigest | sort -u

# "Digest: nonce mismatch" hatasını araştır - genellikle süre aşımı
grep "nonce mismatch" /var/log/apache2/auth_error.log

# 401 dönen istekleri listele
grep " 401 " /var/log/apache2/auth_access.log | tail -20

# Belirli bir IP'nin başarısız giriş denemelerini say
grep " 401 " /var/log/apache2/auth_access.log | 
    awk '{print $1}' | sort | uniq -c | sort -rn | head -10

Başarısız giriş denemelerini izlemek için basit bir script:

#!/bin/bash
# /usr/local/bin/auth_monitor.sh

LOG_FILE="/var/log/apache2/auth_access.log"
THRESHOLD=10
ALERT_EMAIL="[email protected]"

# Son 5 dakikadaki 401 hatalarını kontrol et
ZAMAN=$(date -d "5 minutes ago" "+%d/%b/%Y:%H:%M")

SUPHELI_IPLER=$(grep " 401 " $LOG_FILE | 
    awk -v zaman="$ZAMAN" '$4 > "["zaman {print $1}' | 
    sort | uniq -c | sort -rn | 
    awk -v esik="$THRESHOLD" '$1 >= esik {print $2 " (" $1 " deneme)"}')

if [ -n "$SUPHELI_IPLER" ]; then
    MESAJ="Dikkat! Asagidaki IP'lerden cok sayida basarisiz giris denemesi:nn$SUPHELI_IPLER"
    echo -e "$MESAJ" | mail -s "Apache Auth Uyarisi - $(hostname)" $ALERT_EMAIL
    echo -e "$MESAJ"
fi
# Script'i çalıştırılabilir yap ve cron'a ekle
chmod +x /usr/local/bin/auth_monitor.sh

# Crontab'a ekle (her 5 dakikada bir çalıştır)
echo "*/5 * * * * root /usr/local/bin/auth_monitor.sh" >> /etc/cron.d/apache_auth_monitor

Parola Yönetimi ve Bakım

Üretim ortamında kullanıcı parolalarını yönetmek için bir süreç oluşturmanız gerekir.

#!/bin/bash
# /usr/local/bin/digest_user_manager.sh
# Kullanım: ./digest_user_manager.sh [ekle|sil|listele|parola-degistir] [kullanici] [realm] [dosya]

KOMUT=$1
KULLANICI=$2
REALM=$3
DOSYA=${4:-"/etc/apache2/.htdigest"}

case $KOMUT in
    ekle)
        if [ -z "$KULLANICI" ] || [ -z "$REALM" ]; then
            echo "Kullanim: $0 ekle <kullanici> <realm> [dosya]"
            exit 1
        fi
        htdigest "$DOSYA" "$REALM" "$KULLANICI"
        echo "Kullanici '$KULLANICI' eklendi."
        ;;

    sil)
        if [ -z "$KULLANICI" ]; then
            echo "Kullanim: $0 sil <kullanici> [realm] [dosya]"
            exit 1
        fi
        # Kullanıcıyı dosyadan sil (tüm realm'lerdeki kayıtları)
        TEMP=$(mktemp)
        grep -v "^${KULLANICI}:" "$DOSYA" > "$TEMP"
        mv "$TEMP" "$DOSYA"
        chmod 640 "$DOSYA"
        chown root:www-data "$DOSYA"
        echo "Kullanici '$KULLANICI' silindi."
        ;;

    listele)
        echo "Kullanicilar ($DOSYA):"
        awk -F: '{print "  - " $1 " [" $2 "]"}' "$DOSYA" | sort
        ;;

    parola-degistir)
        htdigest "$DOSYA" "$REALM" "$KULLANICI"
        echo "Parola degistirildi."
        ;;

    *)
        echo "Kullanim: $0 [ekle|sil|listele|parola-degistir] [kullanici] [realm] [dosya]"
        exit 1
        ;;
esac

Güvenlik Sertleştirme Önerileri

mod_auth_digest kullanırken göz önünde bulundurmanız gereken güvenlik pratikleri:

  • HTTPS zorunluluğu: Digest Authentication parolayı korur ama trafiği şifrelemez. Kesinlikle SSL/TLS kullanın.
  • Parola dosyası konumu: Web root dışında tutun. /etc/apache2/ altı iyidir ama /var/www/html/ içine asla koymayın.
  • Dosya izinleri: Parola dosyaları 640 izniyle root:www-data sahipliğinde olmalı.
  • Güçlü parolalar: MD5 hash kullanıldığından parola kalitesi kritiktir. En az 16 karakter, büyük/küçük harf, rakam ve sembol içeren parolalar kullanın.
  • Realm güvenliği: Realm adını tahmin edilmesi zor yapın; “admin” veya “password” gibi adlar kullanmayın.
  • AuthDigestNonceLifetime: Production ortamında 300-600 saniye arası tutun.
  • fail2ban entegrasyonu: 401 hatalarını izleyerek brute force saldırılarını engelleyin.
  • Düzenli parola rotasyonu: En az 90 günde bir parola değişimini zorunlu kılın.

fail2ban için hızlı bir kural:

# /etc/fail2ban/filter.d/apache-digest-auth.conf

[Definition]
failregex = ^<HOST> .* ".*" 401 .*$
ignoreregex =
# /etc/fail2ban/jail.d/apache-digest.conf

[apache-digest-auth]
enabled = true
port = http,https
filter = apache-digest-auth
logpath = /var/log/apache2/auth_access.log
maxretry = 5
bantime = 3600
findtime = 600
sudo systemctl restart fail2ban
sudo fail2ban-client status apache-digest-auth

Sonuç

mod_auth_digest, doğru yapılandırıldığında iç ağ uygulamaları ve development ortamları için pratik bir kimlik doğrulama çözümü sunar. Basic Auth’un açık metin parola gönderme sorununu ortadan kaldırır ve çok katmanlı erişim kontrolü için yeterli esneklik sağlar.

Bununla birlikte gerçekçi olmak gerekir: Eğer internet üzerinden erişilen bir sistem kuruyorsanız, mod_auth_digest yerine HTTPS üzerinde Basic Auth, OAuth 2.0, veya modern SSO çözümlerine yönelmelisiniz. MD5 tabanlı hash mekanizması günümüz standartlarında kriptografik olarak güçlü değildir.

mod_auth_digest’in parladığı alan şudur: Hızlıca ayağa kaldırmanız gereken iç ağ servisleri, erişimi kısıtlı development ortamları, legacy sistem entegrasyonları ve ek güvenlik katmanı olarak IP kısıtlamasıyla birlikte kullanım. Bu senaryolarda HTTPS ile birlikte yapılandırılmış, düzgün izinlenmiş bir mod_auth_digest kurulumu sizi uzun süre idare edecektir.

Parola dosyalarını düzenli yedekleyin, log’ları izleyin ve fail2ban ile brute force korumasını aktif tutun. Bu üç önlemi aldığınızda kurulumunuz oldukça sağlam bir temele oturmuş olacaktır.

Yorum yapın