Zaufane proxy
Gdy OxPHP działa za reverse proxy (Kubernetes Ingress, Cloudflare, AWS ALB, nginx), każde żądanie przychodzi z adresu IP proxy. Bez konfiguracji zaufanych proxy ograniczanie liczby żądań, rejestrowanie dostępu oraz $_SERVER['REMOTE_ADDR'] widzą adres IP proxy zamiast rzeczywistego klienta.
Konfiguracja
# Comma-separated CIDR list
TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
# Shorthand: all RFC-1918 + loopback + link-local (IPv4 and IPv6)
TRUSTED_PROXIES="private"
# Keywords and CIDRs combine in one list
TRUSTED_PROXIES="private,cloudflare,100.64.0.0/10"Każdy wpis rozdzielony przecinkami to CIDR, pojedynczy adres IP (jeden host) albo jedno ze słów kluczowych private i cloudflare, zapisane dowolną wielkością liter. Wpis, który nie jest żadnym z nich, powoduje błąd przy starcie.
Gdy zmienna nie jest ustawiona, OxPHP ignoruje wszystkie nagłówki przekierowania. To bezpieczne ustawienie domyślne.
Jak to działa
Gdy żądanie przychodzi z zaufanego adresu IP, OxPHP analizuje nagłówki przekierowania w kolejności priorytetów:
Forwarded(RFC 7239) — ustandaryzowany nagłówekX-Forwarded-For/X-Forwarded-Proto/X-Forwarded-Host/X-Forwarded-Port— faktyczny fallback
Jeśli obecny jest nagłówek Forwarded, nagłówki X-Forwarded-* są ignorowane.
Wydobywanie adresu IP klienta
OxPHP stosuje algorytm rightmost-non-trusted (skrajnie prawy niezaufany) — to samo podejście, którego używają nginx (real_ip_recursive on), Caddy, Traefik i Apache:
X-Forwarded-For: 203.0.113.50, 172.16.1.1, 10.0.0.5
TCP peer: 10.0.0.1 (trusted)
Walk right-to-left:
10.0.0.5 → trusted → skip
172.16.1.1 → trusted → skip
203.0.113.50 → NOT trusted → client IPZapobiega to podszywaniu się przez doklejanie wartości z lewej strony. Atakujący może dodać fałszywe adresy IP po lewej stronie, ale skrajnie prawy niezaufany adres IP został ustawiony przez ostatnie zaufane proxy w łańcuchu.
Wpis może zawierać port: 203.0.113.50:4711 lub [2001:db8::1]:4711 — w tej postaci niektóre load balancery zapisują go w X-Forwarded-For (między innymi Azure Application Gateway). Gdy adres klienta pochodzi z takiego wpisu, jego port staje się REMOTE_PORT.
Przejście zatrzymuje się na wpisie bez adresu lub takim, którego nie da się sparsować jako adresu IP (pusty element, unknown, zaciemniony identyfikator RFC 7239), oraz na linii nagłówka, której OxPHP nie potrafi odczytać jako tekstu (na przykład zawierającej bajt spoza ASCII). Nic na lewo od tego punktu nie jest używane, bo ta część łańcucha może pochodzić wyłącznie od klienta. Adresem klienta jest skrajnie prawy niezaufany wpis na prawo od tego punktu. Jeśli wszystkie wpisy tam są zaufane, jest nim skrajnie lewy z nich; jeśli nie ma tam żadnego wpisu, adres nie jest przepisywany i pozostaje adresem łączącego się peera, łącznie z portem.
X-Forwarded-For: 198.51.100.9, unknown, 10.0.0.5
TCP peer: 10.0.0.1 (trusted)
Walk right-to-left:
10.0.0.5 → trusted → skip
unknown → does not parse → stop
198.51.100.9 → never reached
Client IP: 10.0.0.5 (every entry right of the stop is trusted → the leftmost of them)Ze słowem kluczowym cloudflare żądanie, którego łańcuch przekazywania pokazuje, że przyszło z węzła brzegowego Cloudflare, bierze zamiast tego adres klienta z nagłówka CF-Connecting-IP. Zobacz Za CDN i load balancerem platformy.
Co się zmienia
Gdy TRUSTED_PROXIES jest skonfigurowane, a łączący się adres IP jest zaufany:
| Komponent | Bez zaufanych proxy | Z zaufanymi proxy |
|---|---|---|
$_SERVER['REMOTE_ADDR'] |
IP proxy | Rzeczywisty IP klienta; IP proxy, gdy nagłówki przekierowania nie dają żadnego adresu |
$_SERVER['REMOTE_PORT'] |
Port źródłowy proxy | Port klienta z wpisu ip:port w Forwarded lub X-Forwarded-For, w przeciwnym razie 0; port peera, gdy adres nie jest przepisywany |
$_SERVER['HTTPS'] |
Na podstawie konfiguracji TLS OxPHP | Z Forwarded: proto= lub X-Forwarded-Proto |
$_SERVER['REQUEST_SCHEME'] |
http lub https z TLS |
Z przekazanego protokołu |
$_SERVER['SERVER_NAME'] |
Z nagłówka Host |
Z Forwarded: host= lub X-Forwarded-Host |
$_SERVER['SERVER_PORT'] |
Z nagłówka Host |
Z X-Forwarded-Port, w przeciwnym razie port z X-Forwarded-Host / Forwarded: host=, w przeciwnym razie 443/80 |
| Ograniczanie liczby żądań | Na IP proxy | Na IP klienta |
| Dziennik dostępu | IP proxy | Rzeczywisty IP klienta |
Gdy adres klienta jest przepisywany, REMOTE_PORT jest portem źródłowym klienta, jeśli wpis, z którego pochodzi adres, go zawiera — węzeł Forwarded: for="ip:port" zgodny z RFC 7239 albo wpis ip:port w X-Forwarded-For — a w przeciwnym razie 0. Portu nie da się zrekonstruować, więc jest zerowany zamiast zgadywany. Adres wzięty z CF-Connecting-IP również nie ma portu, więc REMOTE_PORT wynosi wtedy także 0. Gdy nagłówki nie dają adresu klienta i adres nie jest przepisywany, jak opisano w sekcji Wydobywanie adresu IP klienta, REMOTE_PORT pozostaje portem łączącego się peera.
Sieci private
Skrót private obejmuje:
| Sieć | Opis |
|---|---|
10.0.0.0/8 |
Prywatna klasy A |
172.16.0.0/12 |
Prywatna klasy B |
192.168.0.0/16 |
Prywatna klasy C |
127.0.0.0/8 |
Loopback |
169.254.0.0/16 |
Link-local |
::1/128 |
IPv6 loopback |
fc00::/7 |
IPv6 unique local |
fe80::/10 |
IPv6 link-local |
Współdzielona przestrzeń adresowa (100.64.0.0/10, RFC 6598) nie należy do private. Jeśli Twój load balancer łączy się z tego zakresu, wpisz go obok słowa kluczowego: TRUSTED_PROXIES="private,100.64.0.0/10".
Sieci cloudflare
Słowo kluczowe cloudflare dodaje zakresy węzłów brzegowych, które Cloudflare publikuje pod adresem cloudflare.com/ips: 15 zakresów IPv4 i 7 zakresów IPv6, według stanu opublikowanego 2026-10-05. Lista jest wkompilowana w OxPHP i zmienia się tylko wraz z wydaniem OxPHP. Gdy lista Cloudflare zmieni się wcześniej:
- Nowy zakres. Wpisz go obok słowa kluczowego:
TRUSTED_PROXIES="private,cloudflare,<new range>". Wpisany zakres liczy się jako jedno z Twoich własnych proxy, a nie jako węzeł brzegowy Cloudflare, więc żądania przechodzące przez niego biorą adres według reguły rightmost-non-trusted, a nie zCF-Connecting-IP, dopóki któreś wydanie nie doda tego zakresu do słowa kluczowego. - Wycofany zakres. Nie da się go odjąć od słowa kluczowego. Aby pozbyć się go, zanim zrobi to wydanie OxPHP, wpisz zakresy, którym nadal ufasz, jako CIDR-y zamiast używać słowa kluczowego. Oznacza to też rezygnację z odczytywania
CF-Connecting-IP, które jest powiązane ze słowem kluczowym.
Za CDN i load balancerem platformy
Typowe wdrożenie umieszcza CDN przed load balancerem platformy hostingowej:
client → Cloudflare → load balancer → OxPHPPrzy TRUSTED_PROXIES=private zaufany jest tylko load balancer. Skrajnie prawym niezaufanym adresem w X-Forwarded-For jest wtedy węzeł brzegowy Cloudflare, który połączył się z load balancerem, i każde żądanie wygląda na pochodzące z Cloudflare — w REMOTE_ADDR, w dzienniku dostępu, w ograniczaniu liczby żądań i w atrybucie spana client.address. Zaufaj obu przeskokom:
TRUSTED_PROXIES="private,cloudflare"Jeśli load balancer łączy się z adresu spoza zakresów private, wpisz również jego zakres: TRUSTED_PROXIES="private,100.64.0.0/10,cloudflare".
Ze słowem kluczowym cloudflare OxPHP ustala adres klienta w trzech krokach:
- 1Przejście przez własne proxy. Zaczynając od łączącego się peera, OxPHP przechodzi w lewo przez łańcuch przekazywania (
Forwarded, jeśli jest obecny, w przeciwnym razieX-Forwarded-For), mijając Twoje własne proxy: zakresyprivatei wpisane przez Ciebie CIDR-y. Adres należący do zakresów Cloudflare liczy się jako Cloudflare, nawet jeśli go wpisałeś. - 2Szukanie przeskoku przez Cloudflare. Jeśli pierwszy przeskok, który nie jest jednym z Twoich własnych proxy, jest adresem Cloudflare, żądanie przyszło przez Cloudflare, a adresem klienta jest nagłówek
CF-Connecting-IP. Nagłówek musi wystąpić dokładnie raz i zawierać poprawny adres IP. - 3W przeciwnym razie rightmost-non-trusted. Jeśli żądanie nie przyszło przez Cloudflare albo
CF-Connecting-IPjest nieobecny, powtórzony lub błędny, stosowana jest reguła rightmost-non-trusted, przy czym zakresy Cloudflare liczą się jako zaufane.
Przeskok, na którym przejście się zatrzymuje, to łączący się peer albo adres zapisany przez jedno z Twoich własnych proxy. Klient, który łączy się z load balancerem bezpośrednio, nie może więc sprawić, by OxPHP odczytał CF-Connecting-IP wysłany przez niego samego: load balancer zapisuje w tym miejscu własny adres klienta, a adres Cloudflare, który klient wpisał dalej w lewo, nigdy nie zostanie osiągnięty. Podobnie jak reguła rightmost-non-trusted, opiera się to na tym, że Twoje proxy utrzymują nagłówek, który czyta OxPHP — dopisują adres, który się z nimi połączył, zamiast przepuszczać wartość klienta bez zmian.
Twoje proxy muszą utrzymywać także Forwarded. OxPHP czyta go w pierwszej kolejności, przed X-Forwarded-For, a Cloudflare przekazuje go dalej w takiej postaci, w jakiej wysłał go odwiedzający, bo nie jest to jeden z nagłówków ustawianych przez Cloudflare. Load balancer, który utrzymuje tylko X-Forwarded-For, musi więc usuwać Forwarded z żądania. Jeśli przepuszcza ten nagłówek, każdy klient — przez Cloudflare czy nie — wybiera adres, który widzi OxPHP, ze słowem kluczowym cloudflare lub bez niego.
CF-Connecting-IP nie jest odczytywany także wtedy, gdy przejście zatrzyma się, zanim dotrze do adresu Cloudflare — na wpisie bez adresu lub takim, którego nie da się sparsować, albo na linii, której OxPHP nie potrafi odczytać jako tekstu, jak opisano w sekcji Wydobywanie adresu IP klienta. Na wpis, który jedno z Twoich proxy umieszcza w osobnej linii, nie wpływa nieczytelna linia wysłana wcześniej przez klienta. Wpis, który proxy zapisuje w tej samej linii co tekst wysłany przez klienta, przepada razem z tą linią: przejście zatrzymuje się tam, a adres pochodzi z tego, co Twoje proxy zapisały na prawo od tej linii, albo pozostaje adresem łączącego się peera — nigdy z niczego, co wysłał klient.
Cloudflare dopisuje do X-Forwarded-For adres tego, kto się z nim połączył, więc dla zwykłego odwiedzającego oba nagłówki wskazują tego samego klienta. Mogą się jednak różnić dla żądań, które Cloudflare Workers wysyłają do Twojego serwera źródłowego (origin), bo one również wychodzą z adresów Cloudflare, niezależnie od tego, które konto jest właścicielem Workera. Dokumentacja nagłówków HTTP Cloudflare nie mówi, co takie żądanie może nieść w X-Forwarded-For. O CF-Connecting-IP mówi: Worker może wybrać jego wartość tylko dla żądania do nazwy hosta we własnej strefie; dla nazwy hosta w innej strefie Cloudflare nagłówek zawiera stały adres 2a06:98c0:3600::103, a dla nazwy hosta spoza Cloudflare jest to adres klienta, którego Worker nie może zmienić.
Zaufanie zakresom Cloudflare nadal oznacza zaufanie wszystkiemu, co wychodzi z sieci Cloudflare, a nie tylko Twojej strefie. Jeśli adres klienta wpływa na decyzję dotyczącą bezpieczeństwa, spraw, by serwer źródłowy przyjmował ruch wyłącznie z Twojej strefy, za pomocą środków, jakie oferuje Twoja platforma.
Bezpieczeństwo
- Bezpieczne ustawienie domyślne — bez
TRUSTED_PROXIESżadne nagłówki przekierowania nie są przetwarzane - Walidacja CIDR — nieprawidłowe wartości w
TRUSTED_PROXIESpowodują błąd przy starcie - Odporność na podszywanie — algorytm rightmost-non-trusted ignoruje wartości doklejone przez atakującego
- Żądania z niezaufanych adresów IP mają swoje nagłówki przekierowania całkowicie ignorowane
Prompty dla Twojego agenta
Te prompty zakładają agenta z podłączonym serwerem MCP dokumentacji OxPHP — sam przeczyta strony, których potrzebuje.
Skonfiguruj zaufane proxy dla mojego wdrożenia OxPHP. Przeczytaj stronę `security/trusted-proxies` przez serwer MCP dokumentacji OxPHP.
Ustal na podstawie moich plików infrastrukturalnych, co stoi przed aplikacją, a potem podaj mi dokładną konfigurację i powiedz mi, co każda wartość dopuszcza oraz co pozwoliłaby klientowi podrobić, gdyby była ustawiona źle.Zobacz też
- Ograniczanie liczby żądań — ograniczanie liczby żądań per IP używa rozwiązanego adresu IP klienta
- Rejestrowanie dostępu — pole
remote_ippokazuje rozwiązany adres IP klienta - Dokumentacja konfiguracji — wszystkie zmienne środowiskowe