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.logve/var/log/apache2/access.log - RHEL/CentOS:
/var/log/httpd/error_logve/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/appileProxyPass /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_connectgerekir, bunu unutanlar çok olur. - Worker bağlantı havuzu: Yoğun trafikte
maxparameteresi çok düşük kalabilir.ProxyPass / http://backend/ max=50gibi 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ı
curlile 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.
