Заявката, която пристига в приложението ви, носи два вида доказателства за адрес: съседът, който е отворил мрежовата връзка, и HTTP поле, което твърди адреса на по-ранен клиент. Те отговарят на различни въпроси. Съседният сокет се наблюдава, а заглавката се твърди от този, който я е написал, и нито едно от двете не трябва тихо да замества другото в дневник или в правило за достъп. Сравнението по-долу ги държи разделени и след това показва единствената подредба, в която заглавката става използваема.

Опишете пътя, преди да сравнявате каквото и да е:

Client -> approved reverse proxy -> application origin

В тази подредба съседният сокет на произхода обикновено е проксито, а заглавката за препращане може да носи твърдението на проксито за клиента. Стойността ѝ идва от контролираната връзка с това прокси, а не от името на заглавката.

Два вида доказателства за адрес

Съседният сокет е факт за една TCP връзка: нещо е завършило ръкостискане от този адрес. Това не е непременно човекът, устройството или акаунтът, за които ви е грижа, защото VPN или изходен възел на Tor могат законно да бъдат източникът, който услугата наблюдава. Той все пак е единственият адрес, който самият хост е проверил, и това е цялата му стойност.

Полето за препращане е метаданни за верига. X-Forwarded-For, X-Real-IP и стандартизираното поле Forwarded може да бъде написано от всеки клиент, който достигне крайна точка, която ги възпроизвежда, така че надеждността им зависи изцяло от това на кого е било позволено да ги задава.

Пазете и двете в контекста на заявката под различни имена. Приложение, което презаписва съседа със заглавката, губи способността по-късно да реконструира грешка в доверието, а това е точно моментът, в който тя ви е нужна.

Заглавката никога не пренасочва връзката

Записването на адрес в поле за препращане не променя източника на TCP връзката, пристигаща на сървъра, и не променя маршрутизацията никъде по пътя. Обикновената VPN маршрутизация или изходен NAT доставя трафик без никаква HTTP заглавка. По същия начин транзитен шлюз не пренаписва правилно защитен HTTPS обмен, без да промени подредбата на TLS крайната точка.

Обратната грешка е също толкова честа: HTTPS не прави заглавката за препращане, предоставена от клиента, истинна. Той защитава преноса на фалшиво твърдение точно толкова добре, колкото на истинско.

Ако колега предложи промяна на заглавка, за да поправи проблем с маршрутизацията, диагнозата вече е сбъркана. Поправете пътя или поправете конфигурацията на проксито, което пише заглавката.

Назовете проксито, на което е позволено да твърди

Две правила правят полето за препращане използваемо и двете са конфигурация, а не код. Ръбът нормализира или изхвърля всичко, което идва отвън, според собственото си документирано поведение за тези полета. След това произходът взема заместващ адрес от пътя на проксито, който сте назвали, и от нищо друго. Второто правило важи само докато клиентите не могат да достигнат произхода по друг начин, тъй като произход, който отговаря и на директни, и на проксирани заявки, няма представа на кое от тях служи.

Модулът на NGINX за реален IP показва разделянето ясно. set_real_ip_from назовава подателите, чието твърдение се брои, и real_ip_header казва кое поле го носи; първото извършва доверяването, второто само казва къде да се гледа.

set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on  - walk the list back past every trusted address

Директива за избор на заглавка сама по себе си все още не установява нищо за това кой е изпратил стойността.

Сигурността на транспорта трябва да действа по целия път между компонентите, на които вярвате. Ръб, който нормализира правилно, губи тази стойност в момента, в който незащитен междинен етап надолу по веригата позволи на някой друг да редактира твърдението, докато то пътува.

Работете съзнателно с вериги с много междинни етапи

Няколко проксита се нуждаят от ясен модел на веригата. Не вземайте най-лявата или най-дясната стойност, разделена със запетаи, защото някоя публикация в блог го е направила; разберете кое от вашите проксита добавя, кое замества и кое запазва входящото поле. Например NGINX може да обхожда списъка назад срещу своето доверено множество и да спре на първия адрес, който не притежава, и това е правилото на този продукт, а не закон, на който се подчинява всяка рамка. Четете документацията на собственото си прокси със същите два въпроса: коя стойност избира и на кои податели вярва?

Запишете веригата: ред на етапите, кой етап задава полето и кой етап премахва входящите копия. След това дръжте тази бележка до конфигурацията на проксито, а не само в билета. След това я проверете, като изпратите заявка с фалшифицирана заглавка през одобрения процес за валидиране и потвърдите, че произходът я игнорира.

Когато добавите етап, прегледайте този документ. Нов балансьор на натоварването, вмъкнат пред довереното прокси, може да промени кой адрес печели, без някой да редактира приложението.

Пазете и двете наблюдения в дневника

Където диагностиката е разрешена, записвайте съседа на връзката и нормализирания адрес на клиента като две отделни полета и добавяйте само метаданните за препращане, които целта наистина изисква. След това докажете внедряването с две заявки: една през прокси, която трябва разумно да запише и двете стойности, и един опит директно към произхода, който трябва да бъде отказан.

Помнете какво означава двойката. Заглавката добавя контекст, предоставен от компонент, който сте избрали да вярвате; съседът остава единственият адрес, който вашият хост действително е видял. Нито едно от двете не е доказателство за индивидуална идентичност и дизайн, който приема което и да е от тях за доказателство, ще сгреши относно някого.

Подобни статии