انجیناکس؛ شب ۴۶: TLS passthrough، SNI و PROXY protocol
فهرست نوشته
در TLS passthrough، Nginx stream گواهی را باز نمیکند؛ بر پایهٔ اطلاعات ClientHello مسیر اتصال را انتخاب میکند. امشب آن را با TLS termination و انتقال IP مقایسه میکنیم.
این جلسه بخشی از دورهٔ انجیناکس در ۵۰ شب است. قرارداد آزمایشگاه، مسیرها و روال اعمال تغییر در راهنمای دوره آمده است.
محیط: stream SSL preread در build موجود باشد؛ ورودی TCP/16443 فقط برای کلاینت ۲۰ باز است. دو HTTPS backend محلی 8444 و 9444 با گواهی آزمایشگاه و محتوای متفاوت داریم.
backendهای قابل تشخیص#
در context http دو server کامل محلی بساز: اول listen 127.0.0.1:8444 ssl; server_name www.nginx.test; و دوم listen 127.0.0.1:9444 ssl; server_name app.nginx.test;. در هر دو certificate/key شب ۱۱ و یک location با پاسخ ثابت متفاوت قرار بده. این return فقط marker backend TLS است و آزمون WAF یا ACL HTTP نیست.
در /etc/nginx/stream.d/30-tls-pass.conf:
map $ssl_preread_server_name $tls_route {
www.nginx.test 127.0.0.1:8444;
app.nginx.test 127.0.0.1:9444;
default 127.0.0.1:1;
}
server {
listen 16443;
allow 192.168.57.20;
deny all;
ssl_preread on;
proxy_connect_timeout 2s;
proxy_timeout 30s;
proxy_pass $tls_route;
}
پورت 1 مقصد نامعتبر عمدی آزمایشگاه است؛ پیش از استفاده با ss تأیید کن هیچ سرویسی آنجا گوش نمیدهد. نام ناشناخته و بدون SNI به backend پیشفرض واقعی راه پیدا نمیکند. ssl_preread با TLS termination یعنی listen ... ssl فرق دارد؛ این ورودی certificate/key ندارد. SNI نام اعلامشدهٔ کلاینت است، احراز هویت کاربر محسوب نمیشود.
curl --cacert ~/nginx-lab/pki/ca.crt \
--resolve www.nginx.test:16443:192.168.57.10 https://www.nginx.test:16443/
curl --cacert ~/nginx-lab/pki/ca.crt \
--resolve app.nginx.test:16443:192.168.57.10 https://app.nginx.test:16443/
این فرمانها از کلاینت ۲۰ هستند؛ CA واقعی و IP شاخه را جایگزین کن. هر نام باید marker backend خودش را با TLS معتبر بدهد. با openssl s_client و -noservername مسیر بدون SNI را بررسی کن؛ نباید certificate سایت مجاز را دریافت کنی. نام ناشناخته را نیز با SNI صریح آزمایش کن.
مرز دید stream و انتقال IP#
در stream رمزگشایی انجام نمیشود، بنابراین security headers، URI rate limit و ModSecurity HTTP در این لایه اعمال نمیشوند. آنها روی backendی که TLS را باز میکند قرار میگیرند. log stream زمان و بایت/مقصد session را دارد، نه path رمزشدهٔ HTTP. قابلیتهایی مثل ECH میتوانند مشاهدهٔ SNI را محدود کنند؛ این روش را router عمومی همهٔ TLSها فرض نکن.
backend محلی بهصورت پایه peer را loopback میبیند. تمرین اختیاری انتقال IP باید هر دو طرف را همزمان تغییر دهد: در stream proxy_protocol on;، در backend listen 127.0.0.1:8444 ssl proxy_protocol; و counterpart دوم، همراه set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; در HTTP backend. فقط همتای خصوصی قابل اعتماد مجاز به ارسال این preamble است. روشن کردن یک طرف، TLS را خراب میکند. این تنظیم با listen ... proxy_protocol در ورودی stream یکی نیست؛ ورودی نمونه کلاینت TLS عادی دریافت میکند.
بازگشت: ابتدا دو طرف PROXY protocol را با هم برگردان، سپس route/listener موقت را بردار و validate/reload کن. مجوز پورت و policy SELinux را مثل شب ۴۴ فقط در دامنهٔ همین تمرین نگه دار.
منبع: SSL preread ، PROXY protocol در stream ، real IP در HTTP .