Nginx напред, приватен backend зад VPN
Браузерот разговара со Nginx, а Nginx отвора втора врска во тунелот. Насочи ги двете, провери ги двата сертификати и задржи јавните пренасочувања јавни.
Следи едно барање од телефон во воз до backend што постои само во приватна мрежа. Телефонот резолвира јавно име, се поврзува со јавна адреса на порта 443 и завршува нормално TLS ракување. Nginx ја прифаќа таа врска и потоа отвора втора, целосно одделна, кон адреса до која стигнува само преку VPN интерфејс. Ништо на телефонот не се менува и телефонот никогаш не дознава дека имало тунел.
Следење на едно барање низ две врски
Влезниот дел е јавна HTTP трансакција. Има јавно име, јавен сертификат и повратен пат што мора да работи за секоја адреса што посетителот ја има во тој момент. Секоја промена што го нарушува тој пат ги крши сите посетители одеднаш. Затоа јавниот дел е оној со кој најмалку сакаш да експериментираш.
Излезниот дел е приватен. Nginx станува клиент, резолвира внатрешно име или користи фиксна адреса и стигнува до услуга што би одбила врска од интернет.
Public client -> frontend public address:443 (TLS, public name)
Frontend -> VPN private backend 10.40.0.20:8443 (TLS, private name)
Држи ги одделно во главата и конфигурацијата станува очигледна. Ако ги споиш, на крајот ќе се обидуваш да направиш јавен клиент да учествува во тунел, а оттаму доаѓа најголемиот дел од конфузијата во овој дизајн. Приватниот дел смее да биде кревок. Јавниот не.
Пред да изградиш било што од ова, потврди дека објавувањето на апликацијата е намерно. Работечки прокси е и работечко изложување, а моделот на автентикација мора да биде одлука, а не несакан ефект.
Името на порталот мора да го преживее тунелот
Во резолвирањето на имиња лежи суптилна замка. Ако приватниот DNS го презапише истото име што VPN профилот го користи за сопствениот портал, повторното поврзување може на крајот да се обиде да стигне до тој портал низ тунелот што сам треба да го воспостави. Клиентот има потреба тоа име да биде резолвирано пред тунелот да постои. Откако ќе се резолвира внатре во тунелот, врската никогаш повеќе не може да се изгради.
Користи одделни одобрени имиња за порталот и backend и ограничи ја политиката на резолверот така што секое име ќе се резолвира до адресата што му е потребна на неговиот корисник. Менувањето на Host заглавието на апликацијата не помага овде, зашто пребарувањето го прави VPN клиентот.
Потоа размисли за опфатот. Frontend има потреба од рута до адресата на backend и мора да продолжи да одговара на јавни клиенти. Целосен тунел на тој хост може да го исполни првиот услов и да го скрши вториот.
Каде политиката дозволува, тунел до конкретна дестинација е почист дизајн. Каде политиката бара целосен тунел, frontend припаѓа во одделен мрежен контекст, наместо да биде крпен со ad hoc рути за познати посетители.
Да се напише блокот на серверот така што двата дела проверуваат
Претпостави дека backend прикажува сертификат за backend.corp.example и одговара на приватна адреса. Поврзувањето со адреса додека се проверува име е токму она за што служат SNI и именските опции на прокси модулот.
upstream private_app {
server 10.40.0.20:8443;
}
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /etc/nginx/tls/app-fullchain.pem;
ssl_certificate_key /etc/nginx/tls/app-key.pem;
location / {
proxy_pass https://private_app;
proxy_ssl_server_name on;
proxy_ssl_name backend.corp.example;
proxy_ssl_trusted_certificate /etc/nginx/trust/backend-ca.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_set_header Host app.example.com;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
Секоја патека и адреса погоре е заменик. Важни се деловите што ја држат проверката вклучена: име за проверка, пакет на доверба со кој да се провери и длабочина што одговара на одобрениот ланец.
proxy_set_header Host app.example.com е намерно. Backend треба да биде конфигуриран да го прифаќа тоа јавно потекло и треба да им верува на препратените заглавија само од овој frontend. Препишувањето на X-Forwarded-For со адресата на клиентот е правилно за еден прокси и погрешно за ланец, така што распоредување со повеќе прокси има потреба од сопствено уредување на доверливи адреси.
Да се направи јавното потекло да се однесува како такво
Апликацијата треба да издава апсолутни URL-а, пренасочувања и колачиња за јавното потекло. Ако пренасочи посетител кон backend.corp.example, тој посетител е испратен на име што не може да го резолвира.
Поправи го тоа преку поддржаната поставка за надворешен URL на апликацијата и прегледана политика за пренасочување, а не со препишување на имиња на хостови во телата на одговорите. Замената на низи во произволна содржина ги крши потпишаните товари и создава грешки што тешко се следат.
Колачињата заслужуваат иста грижа. Колаче ограничено на приватното име никогаш нема да биде испратено од браузер што го знае само јавното.
Потврди и дека Nginx навистина може да го поседува јавниот сокет. Постоечка веб услуга на 443 мора да се премести или frontend мора да живее на друго место, зашто два процеса не можат да ја врзат истата адреса и истата порта.
Да се провери секој дел таму каде што навистина работи
Валидирај ја конфигурацијата со инсталираниот парсер пред секое повторно вчитување, за печатна грешка да не го собори слушателот што моментално служи.
Потоа тестирај го делот на backend од самиот хост на frontend, во истиот мрежен контекст што го користи Nginx. Ping низ тунелот докажува достапност и ништо за TLS, авторизација или апликацијата.
На крајот упати свежо јавно барање до вистинското име на хостот со нормална проверка на сертификатот и набљудувај ја патеката на одговорот, а не само телото.
Задржи ги двете набљудувања заедно со распоредената конфигурација и запиши што се случува кога тунелот не е достапен. Frontend треба да врати контролирана upstream грешка, а не тивко да премине на друг backend што никој не го документирал. 502 со јасна линија во логот е добар исход. Кеширана страница од несакано потекло не е.