Apache ile Proxy Sorunlarını Giderme

Bir production sunucusunda Apache proxy yapılandırması bozulduğunda, genellikle kullanıcılar sana “site açılmıyor” diye gelir ve sen de log dosyalarına bakarak saatlerce uğraşırsın. Bu yazıda Apache proxy sorunlarını sistematik biçimde nasıl gidereceğini, hangi log satırlarına bakman gerektiğini ve gerçek dünya senaryolarıyla karşılaştığında ne yapacağını anlatacağım.

Apache Proxy Nedir ve Neden Sorun Çıkarır?

Apache, hem forward proxy hem de reverse proxy olarak kullanılabilir. Çoğu sysadmin senaryosunda reverse proxy olarak karşımıza çıkar; yani arkasındaki bir uygulama sunucusuna (Tomcat, Node.js, Python Flask, vb.) gelen istekleri yönlendirmek için kullanılır.

Proxy sorunları genellikle şu başlıklar altında toplanır:

  • Bağlantı hataları: Backend sunucuya ulaşamama
  • Timeout sorunları: Yavaş backend yanıtları nedeniyle bağlantının kopması
  • Header sorunları: Yanlış iletilen veya kayıp header bilgileri
  • SSL/TLS sorunları: HTTPS backend’e bağlanırken sertifika doğrulama hataları
  • Rewrite/yönlendirme döngüleri: Sonsuz redirect sorunları
  • Mod_proxy modülü yüklü değil: Yapılandırma çalışmıyor ama kimse neden bilmiyor

Önce temel kontrolleri yaparak başlayalım.

Temel Kontroller: İlk Yapılması Gerekenler

Gerekli Modüllerin Aktif Olup Olmadığını Kontrol Et

Apache’de proxy işlevi birkaç farklı modüle dağılmıştır. Bunlardan herhangi biri eksikse proxy çalışmaz.

# Yüklü modülleri listele
apache2ctl -M | grep proxy

# Ya da
httpd -M | grep proxy

Çıktıda şunları görmen gerekir:

  • proxy_module: Temel proxy modülü
  • proxy_http_module: HTTP proxy desteği
  • proxy_balancer_module: Yük dengeleme desteği (kullanıyorsan)
  • proxy_wstunnel_module: WebSocket proxy desteği (gerekiyorsa)

Eğer bu modüller listelenmiyorsa, Debian/Ubuntu sistemlerde şöyle aktif edersin:

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_balancer
a2enmod lbmethod_byrequests
systemctl restart apache2

RHEL/CentOS sistemlerde ise /etc/httpd/conf.modules.d/ altındaki ilgili .conf dosyalarında #LoadModule satırlarının başındaki # işaretini kaldırman gerekir.

Yapılandırma Sözdizimini Kontrol Et

Proxy sorunlarının büyük bir kısmı basit yazım hatalarından kaynaklanır. Her değişiklikten sonra mutlaka şunu çalıştır:

apache2ctl configtest
# ya da
httpd -t

Syntax OK mesajını gördükten sonra servisi yeniden başlat. Hata görürsen o satırı düzelt.

Log Dosyalarını Okumak

Apache proxy sorunlarını gidermede en değerli araç log dosyalarıdır. Varsayılan log konumları:

  • Debian/Ubuntu: /var/log/apache2/error.log ve /var/log/apache2/access.log
  • RHEL/CentOS: /var/log/httpd/error_log ve /var/log/httpd/access_log

Log Seviyesini Artırmak

Proxy sorunlarını debug ederken varsayılan log seviyesi yeterli bilgi vermez. Geçici olarak log seviyesini artır:

# VirtualHost içine veya ana yapılandırmaya ekle
LogLevel proxy:trace2 proxy_http:trace2

Sonra logları canlı takip et:

tail -f /var/log/apache2/error.log | grep -i proxy

Bu sayede her proxy isteğinin detaylı kaydını görürsün. İşin bittikten sonra log seviyesini tekrar warn veya error‘a çekmeyi unutma, yoksa disk dolabilir.

Yaygın Hata Mesajları ve Anlamları

Log dosyalarında sık karşılaşılan proxy hatalarını ve ne anlama geldiklerini inceleyelim.

“AH01114: HTTP: failed to make connection to backend”

Bu hata, Apache’nin backend sunucuya TCP bağlantısı kuramadığını gösterir. Nedenleri:

  • Backend sunucu çalışmıyor
  • Yanlış port numarası
  • Firewall kuralı bloklıyor
  • Backend yalnızca localhost’ta dinliyor ama farklı IP’den bağlanmaya çalışıyorsun

“AH00898: Error reading from remote server”

Backend sunucuya bağlantı kuruldu ama yanıt alınamadı. Genellikle backend çöktüğünde veya timeout dolduğunda görürsün.

“AH01084: pass request body failed”

POST isteklerinde request body iletilirken sorun çıktı. Büyük dosya yüklemelerinde veya yavaş bağlantılarda karşılaşılır.

Gerçek Dünya Senaryosu 1: Node.js Uygulamasına Reverse Proxy

Diyelim ki bir Node.js uygulaması 3000 portunda çalışıyor ve Apache üzerinden yayına almaya çalışıyorsun. Kullanıcılar “502 Bad Gateway” hatası alıyor.

İlk kontrol: Node.js gerçekten çalışıyor mu?

# Portu dinleyen process var mı?
ss -tlnp | grep 3000
# ya da
netstat -tlnp | grep 3000

# Doğrudan bağlantı test et
curl -v http://localhost:3000

Eğer curl çalışıyorsa sorun Apache yapılandırmasındadır. Yapılandırma şöyle olmalı:

# /etc/apache2/sites-available/myapp.conf
<VirtualHost *:80>
    ServerName myapp.example.com

    ProxyPreserveHost On
    ProxyRequests Off

    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    # Header düzeltmeleri
    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s

    ErrorLog ${APACHE_LOG_DIR}/myapp_error.log
    CustomLog ${APACHE_LOG_DIR}/myapp_access.log combined
</VirtualHost>

ProxyRequests Off satırı kritik; bunu unutursan Apache bir open proxy haline gelir ve kötü niyetli kişiler sunucunu spam göndermek için kullanabilir.

ProxyPreserveHost On ise Host header’ının orijinal değerini backend’e iletir. Bu özellikle Node.js uygulamalarında virtual hosting kullanılıyorsa önemlidir.

Gerçek Dünya Senaryosu 2: Tomcat ile AJP Proxy

Java uygulamalarında Tomcat genellikle AJP connector üzerinden Apache ile haberleşir. AJP ile ilgili sorunlarda farklı bir yaklaşım gerekir.

# AJP modülünü kontrol et
apache2ctl -M | grep ajp

# Modülü aktif et
a2enmod proxy_ajp

Yapılandırma örneği:

<VirtualHost *:80>
    ServerName java-app.example.com

    ProxyRequests Off
    ProxyPreserveHost On

    ProxyPass / ajp://localhost:8009/
    ProxyPassReverse / ajp://localhost:8009/

    # AJP timeout değerleri
    ProxyTimeout 300

    ErrorLog ${APACHE_LOG_DIR}/tomcat_error.log
    CustomLog ${APACHE_LOG_DIR}/tomcat_access.log combined
</VirtualHost>

Önemli not: Apache 2.4.51 ve sonrasında AJP bağlantıları için Secret parametresi gerekebilir. Eğer “AH01076: address family not supported by protocol” gibi bir hata görüyorsan, Tomcat tarafında da server.xml içinde AJP connector’ının doğru yapılandırıldığından emin ol.

Tomcat tarafında AJP portunu kontrol et:

# Tomcat'in 8009 portunu dinleyip dinlemediğine bak
ss -tlnp | grep 8009

# Tomcat loglarına bak
tail -100 /opt/tomcat/logs/catalina.out

Timeout Sorunları ve Çözümleri

Proxy timeout sorunları özellikle uzun süren işlemlerde (rapor oluşturma, büyük dosya işleme, vb.) karşımıza çıkar. Log’da şunu görürsün:

AH00957: HTTP: attempt to connect to 127.0.0.1:8080 (localhost) failed

veya

Timeout when reading response headers from daemon process

Timeout değerlerini şöyle ayarlayabilirsin:

<VirtualHost *:80>
    ServerName slowapp.example.com

    ProxyRequests Off

    # Bağlantı kurma timeout'u (saniye)
    ProxyTimeout 600

    # Keep-alive bağlantı timeout'u
    ProxyPass / http://localhost:8080/ timeout=600 keepalive=On

    ProxyPassReverse / http://localhost:8080/

    ErrorLog ${APACHE_LOG_DIR}/slowapp_error.log
    CustomLog ${APACHE_LOG_DIR}/slowapp_access.log combined
</VirtualHost>

Ayrıca ana Apache yapılandırmasındaki genel timeout değerlerini de kontrol et:

grep -i timeout /etc/apache2/apache2.conf
grep -i timeout /etc/httpd/conf/httpd.conf

Timeout 300 gibi bir değer görürsen ve uygulamanın daha uzun sürdüğünü biliyorsan bu değeri artır.

HTTPS Backend Sorunları

Backend sunucu HTTPS kullanıyorsa proxy_http_module yeterli olmaz, mod_ssl de gerekir. Sık karşılaşılan hata:

SSL Proxy requested for ... but not enabled

Bu hatayı gidermek için:

a2enmod ssl

Ve yapılandırmaya şunu ekle:

<VirtualHost *:443>
    ServerName frontend.example.com

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

    ProxyRequests Off
    ProxyPreserveHost On

    # Backend SSL sertifikasını doğrulama (self-signed için kapatılabilir)
    SSLProxyEngine On
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off

    ProxyPass / https://backend-server:8443/
    ProxyPassReverse / https://backend-server:8443/

    ErrorLog ${APACHE_LOG_DIR}/ssl_proxy_error.log
    CustomLog ${APACHE_LOG_DIR}/ssl_proxy_access.log combined
</VirtualHost>

Dikkat: SSLProxyVerify none production’da önerilmez. Kendi CA’nızla imzalı sertifikalar kullanıyorsanız, CA sertifikasını Apache’ye tanıtarak doğrulama yapmanız daha güvenlidir:

SSLProxyVerify require
SSLProxyCACertificateFile /etc/ssl/certs/internal-ca.crt

Yük Dengeleme Sorunları

Birden fazla backend sunucuyla yük dengeleme yapıyorsun ve bazı sunucular devre dışı kalıyor olabilir. Log’da şunu görürsün:

AH01181: proxy: BALANCER: (balancer://mycluster). All workers are in error state

Bu durumda tüm worker’ların durumunu kontrol etmek için balancer-manager’ı etkinleştir:

<Location /balancer-manager>
    SetHandler balancer-manager
    Require ip 192.168.1.0/24
</Location>

<Proxy "balancer://mycluster">
    BalancerMember http://backend1:8080 loadfactor=1
    BalancerMember http://backend2:8080 loadfactor=1
    ProxySet lbmethod=byrequests
</Proxy>

ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/

Balancer manager’a tarayıcıdan erişerek hangi worker’ların hata durumunda olduğunu görebilir ve “Disable” butonu ile devre dışı bırakıp tekrar aktif edebilirsin. Bunu production’da yalnızca güvenli ağdan erişilebilir hale getir.

Worker’ları komut satırından sıfırlamak için Apache’yi graceful restart yapabilirsin:

apache2ctl graceful
# ya da
systemctl reload apache2

Header Sorunları ve X-Forwarded-For Yapılandırması

Uygulamalar zaman zaman gerçek kullanıcı IP’sini göremez çünkü tüm istekler Apache’nin IP’sinden geliyor gibi görünür. Bunu düzeltmek için:

# mod_remoteip aktif et
a2enmod remoteip

# Yapılandırmaya ekle
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1

# Proxy tarafında header ekle
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
RequestHeader set X-Forwarded-Proto "%{REQUEST_SCHEME}s"

mod_headers modülünün de aktif olduğundan emin ol:

a2enmod headers

Redirect Döngüsü Sorunları

Bazen “Too many redirects” hatasıyla karşılaşırsın. Bu genellikle HTTPS yönlendirmesi yapılandırırken oluşur. Şu senaryoyu düşün: Apache 80’den 443’e yönlendiriyor, ama backend de kendi içinde yönlendirme yapıyor.

Bunu gidermek için backend’e hangi protokolün kullanıldığını söyle:

<VirtualHost *:443>
    ServerName myapp.example.com
    SSLEngine On

    # Backend'e HTTPS üzerinden geldiğini bildir
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

<VirtualHost *:80>
    ServerName myapp.example.com
    Redirect permanent / https://myapp.example.com/
</VirtualHost>

Uygulama içindeyse (Laravel, Django, Rails gibi) genellikle TRUSTED_PROXIES veya benzeri bir ayar bulunur; onu da doğru yapılandırmak gerekir.

Pratik Debug Araçları

curl ile Manuel Test

# Proxy üzerinden istek gönder ve tüm header'ları gör
curl -v -H "Host: myapp.example.com" http://localhost/api/test

# Redirect'leri takip et
curl -vL http://myapp.example.com/

# POST isteği test et
curl -v -X POST -d '{"test":"data"}' 
  -H "Content-Type: application/json" 
  http://myapp.example.com/api/endpoint

tcpdump ile Paket Analizi

Gerçekten ne gönderilip alındığını görmek istiyorsan:

# Apache ile backend arasındaki trafiği izle
tcpdump -i lo -A port 8080

# Belirli bir host'a giden trafiği filtrele
tcpdump -i eth0 -A host backend-server and port 443

Apache Status Modülü

a2enmod status

# Yapılandırmaya ekle
<Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1
</Location>

ExtendedStatus On

Ardından curl http://localhost/server-status ile aktif proxy bağlantılarını ve bunların durumunu görebilirsin.

Sık Yapılan Yapılandırma Hataları

  • ProxyPass sıralaması: Daha spesifik path’ler önce gelmelidir. /api/ genel /‘den önce tanımlanmalıdır.
  • Trailing slash tutarsızlığı: ProxyPass /app http://backend/app ile ProxyPass /app/ http://backend/app/ farklı davranır. Genellikle her ikisinde de trailing slash kullanmak daha güvenlidir.
  • AllowCONNECT modülü: HTTPS tünelleme için mod_proxy_connect gerekir, bunu unutanlar çok olur.
  • Worker bağlantı havuzu: Yoğun trafikte max parameteresi çok düşük kalabilir. ProxyPass / http://backend/ max=50 gibi artırabilirsin.
  • KeepAlive çakışması: Apache tarafında KeepAlive açık ama backend kapalıysa bağlantı sorunları çıkar. Her iki tarafı tutarlı yapılandır.

Log Analizi ile Sorun Kaynağı Tespiti

Erişim loglarından proxy performansını analiz etmek için:

# 502 hatalarını say
grep " 502 " /var/log/apache2/access.log | wc -l

# En çok 502 veren URL'leri bul
grep " 502 " /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20

# Belirli zaman dilimindeki hataları filtrele
awk '/[25/Jan/2024/ && / 502 /' /var/log/apache2/access.log

# Backend yanıt sürelerini analiz et (CustomLog'a %D eklenmiş olmalı)
awk '{print $NF}' /var/log/apache2/access.log | sort -n | tail -20

Yanıt sürelerini loglamak için CustomLog formatını güncelle:

LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %D" combined_with_time
CustomLog ${APACHE_LOG_DIR}/access.log combined_with_time

%D mikrosaniye cinsinden işlem süresini verir. Yüksek değerler backend yavaşlığına işaret eder.

Sonuç

Apache proxy sorunları çoğunlukla sistematik bir yaklaşımla hızlıca çözülür. Şu sırayı takip et:

  • Önce modüllerin yüklü olduğunu doğrula
  • Yapılandırma sözdizimini kontrol et
  • Log seviyesini geçici olarak artır ve log’ları oku
  • Backend’e doğrudan bağlantıyı curl ile test et
  • Header’ların doğru iletildiğinden emin ol
  • Timeout değerlerini uygulamanın ihtiyacına göre ayarla

En sık yapılan hata, log’lara bakmadan tahmine dayalı değişiklikler yapmaktır. Bir değişiklik yap, test et, log’a bak; sonra bir sonraki adıma geç. Bu döngüyü takip ettiğinde proxy sorunlarını genellikle 15-20 dakika içinde çözersin.

Production’da yapılandırma değişikliği yaparken mutlaka önce apache2ctl configtest çalıştır ve değişiklikleri bir versiyon kontrol sisteminde (git gibi) tut. Gece yarısı “site çöktü” çağrısı aldığında en son çalışan yapılandırmaya geri dönebilmek paha biçilmez.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir