nginx real_ip_header ve X-Forwarded-For yanlış görünüyor


58

HTTP başlığının wikipedia açıklaması X-Forwarded-For:

X-Yönlendirilmiş İçin: müşteri1, proxy1, proxy2, ...

Direktifin nginx belgeleri real_ip_header, kısmen şöyledir:

Bu yönerge, değiştirilen IP adresini aktarmak için kullanılan başlığın adını belirler.
X-Forward-For durumunda, bu modül , X-Forwarded-For başlığındaki son ipi değiştirmek için kullanır. [Vurgu madeni]

Bu iki açıklama birbiriyle çelişkili görünmektedir. Senaryomuzda, X-Forwarded-Forbaşlık tam olarak tanımlandığı gibidir - müşterinin "gerçek" IP adresi en soldaki giriştir. Aynı şekilde, nginx davranışı kullanmaktır sağ , açıkça, sadece bizim proxy sunucuları biridir - -En değer.

Benim anlayışım X-Real-IPolmasıdır sözde belirlemek için kullanılacak gerçek - istemci IP adresi değil vekil. Bir şey mi eksik veya bu nginx'te bir hata mı?

Ve bunun ötesinde, X-Real-IPbaşlığın tanımı ile gösterildiği gibi başlığın en soldaki değeri göstermesini sağlayacak herhangi bir önerisi olan var X-Forwarded-Formı?

Yanıtlar:


95

Birden fazla IP zincirlendiğinde X-Forward-For sıkıntılarını çözmenin anahtarının yeni tanıtılan yapılandırma seçeneği olduğuna inanıyorum real_ip_recursive(nginx 1.2.1 ve 1.3.0'da eklendi). Gönderen nginx realip docs :

Özyinelemeli arama etkinse, güvenilen adreslerden biriyle eşleşen özgün bir müşteri adresi, istek başlığı alanında gönderilen son güvenilmeyen adresle değiştirilir.

nginx, varsayılan olarak zincirdeki son IP adresini alıyordu, çünkü güvenilen kabul edilen tek kişi oydu. Ancak, yeni real_ip_recursiveetkin ve çoklu set_real_ip_fromseçeneklerle, birden çok güvenilir proxy tanımlayabilirsiniz ve bu güvenilir olmayan son IP'yi alır.

Örneğin, bu yapılandırma ile:

set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Ve bir X-Forwarded-For başlığıyla sonuçlandı:

X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1

nginx şimdi 123.123.123.123 müşterinin IP adresi olarak seçecektir.

Nginx'in yalnızca en soldaki IP adresini seçmemesi ve güvenilir proxy'leri açıkça tanımlamanızı gerektirdiği için, IP sahtekarlığının kolay şekilde engellenmesi gerekir.

Diyelim ki müşterinin gerçek IP adresi 123.123.123.123. Diyelim ki müşterinin yararı yok ve IP adreslerini taklit etmeye çalışıyorlar 11.11.11.11. Sunucuya bu başlığın zaten bulunduğu bir istek gönderir:

X-Forwarded-For: 11.11.11.11

Ters proxy'ler bu X-Forwarded-For zincirine sadece IP ekler, diyelim ki, nginx bunu elde edince, bunun böyle göründüğünü söyler:

X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1

Yalnızca en soldaki adresi aldıysanız, istemcinin IP adresini kolayca taklit etmesine olanak tanır. Ancak yukarıdaki örnek nginx config ile, nginx yalnızca son iki adrese vekil olarak güvenir. Bu, nginx'in 123.123.123.123IP adresi olarak doğru seçileceği anlamına gelir ; bu sahte IP gerçekte en solda olmasına rağmen.


1
Bunun için çok teşekkür ederim, bu gerçekten bana yardımcı oldu. Bu kabul edilen cevap olmalı.
José F. Romaniello

1
Varsayılan olarak real_ip_header, nginx.org/en/docs/http/ngx_http_realip_module.html uyarınca X-Real-IP gibi görünmektedir. Kötü niyetli bir kullanıcının rastgele X-Real-IP ile istek gönderebileceği ve $ remote_addr olarak kullanılabileceği anlamına mı geliyor? nginx içinde (ve ayrıca muhtemelen uygulamaya da geçti)?
gansbrest

@gansbrest Hayır, çünkü set_real_ip_from, güvenilen ana bilgisayarları sınırlar.
El Yobo

9

X-Forwarded-ForÜstbilginin ayrıştırılması gerçekten nginx real_ip modülünde hatalı.

len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;

for (p = ip + len - 1; p > ip; p--) {
  if (*p == ' ' || *p == ',') {
    p++;
    len -= p - ip;
    ip = p;
    break;
  }
}

Başlık dizesinin en sağında başlar ve bir boşluk veya virgül görür görmez, IP değişkeni içindeki boşluğu veya virgülün sağ tarafına bakmayı ve yapışmayı durdurur. Bu nedenle, en son proxy adresini orijinal müşteri adresi olarak ele alıyor.

Spesifikasyona göre hoş oynamıyor; bu, bir RFC'de acı verici şekilde açık bir şekilde dile getirilmemesi tehlikesidir.

Bir yana: Başlangıçta Squid tarafından tanımlanmış olan formatta iyi bir birincil kaynak bulmak bile zor - belgelerini kazmak siparişi doğrular; en soldaki orijinal müşteri, en son eklenen. Bu wikipedia sayfasına bir [kaynak belirtilmeli] eklemeye çok cazip davranıyorum. Bir anonim düzenlemek konuyla ilgili internet kullanıcısının otorite gibi görünüyor.

Mümkünse, ara proxy'lerinizi başlığın sonuna eklemeyi bırakıp yalnızca gerçek müşteri adresiyle bırakmayı bırakabilir misiniz?


Cevabınız için teşekkürler, @Shane. Aslında, nginx'e ulaşırken, X-Forwarded-Forzaten var. (bu doğru istemci IP adresidir) nginx'in kendisi yük dengeleyicimizin (önceki atlama) IP adresini X-Forwarded-Forbaşlığa eklemeye devam eder. (muhtemelen "uzak adres" olarak gördüğü şeyi eklemek) Basitçe yapmasaydı, X-Forwarded-Forbaşlığımı daha önce olduğu gibi kullanabilirdim . (Son zamanlarda nginx'e taşınıyoruz)
Kirk Woll

@Kirk Yani, nginx başlığa ulaştığında, sadece asıl müşterinin adresi mi? Ancak, işleme alınırken, bağlantı veren proxy sunucusunun başlığına eklenir? Bu bir anlam ifade etmiyor - bu başlığa dokunması gereken tek zaman, bir başka proxy'ye bağlantıyı a aracılığıyla göndermesidir proxy_pass- ve o zaman bile, yalnızca proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;yerinde.
Shane Madden

W3C bile bunu yanlış anlıyor : dokümanları "proxy'lerin isteğin başlatıcısının IP adresini bir X-Forward-For HTTP başlık alanındaki virgülle ayrılmış bir listenin sonuna eklemesi gerekir ", başlaması gerektiğini belirtiyor .
Ian Kemp

3
@IanKemp, hayır, son doğrudur. Bir vekil sunucu tarafında , isteğin başlatıcısı (yani, TCP isteği) önceki vekil (eğer varsa). Bu önceki vekil muhtemelen büyük X-Forwarded-Forolasılıkla solda orijinal müşteri adresi ve muhtemelen buna eklenmiş önceki herhangi bir vekil ile birlikte bir başlık gönderir . Dolayısıyla, şu anda hizmet veren proxy, bu listenin sonuna önceki proxy'yi (= başlatıcı) ekler ve böylece artırılmış X-Forwarded-Forüstbilgiyi bir sonraki yukarı akış sıçramasına hizmet eder . Verilmiş, daha açık bir ifade seçmiş olabilirler.
blubberdiblub

5

X-Real-IP, sunucunun konuştuğu asıl istemcinin (sunucunun "gerçek" istemcisi) IP adresidir; bu, proxy bağlantısı olması durumunda proxy sunucusudur. Bu yüzden X-Real-IP, X-Forwarded-For başlığındaki son IP'yi içerecektir.


1
Tamam, ama, benim için bu hiçbir zaman yararlı bir bilgi değildir. Müşterinin orijinal IP adresini almak istiyorum - bu çok önemlidir ve okuduğum her şeye göre, bu başlıkların amacı. Proxy sunucularımızın IP adresini neden bilmek isteyeyim?
Kirk Woll,

Senin için yararlı değilse, o zaman senin için değil. Kimse seni X-Real-IP kullanmaya zorlamıyor. Uygulamanızdaki kullanıcının IP'sine ihtiyacınız varsa, uygulamanızın X-Forwarded-For (X-Forwarded-For'u ayarlamayan bazı proxy'ler (internet güvenlik cihazı / güvenlik duvarları) olduğu için) her zaman güvenilir değildir; İçin). Nginx bağlamında, X-Forwarded-For önemli değildir, çünkü nginx'in istemcisi olan son girişten (X-Real-IP) bir yana, o müşterilerle konuşmaz. İhtiyacınız yoksa, ayarlama, ayarlama veya sadece dikkate
almama

2
Hayır, demek istediği, neden olur X-Real-IPkendi proxy sunucusunun IP adresi dönen hiç yararlı olabilir?
Kirk Woll

Harika .. cevap adamım. Bu kesin bilgiyi arıyordum. Proxy sunucumdaki bir ncat sunucusuyla konuşmam gerekiyor, bu yüzden hemen buna ihtiyacım var.
Yugal Jindle
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.