#nginx #nginx-reverse-proxy
Вопрос:
Я использую NGINX для обслуживания статических файлов, обратного прокси-сервера в Django и проверки сертификатов клиентов.
Я не хочу, чтобы сертификат запрашивался в корневом каталоге URL, поэтому я создал другой сервер на Nginx.conf, чтобы запросить сертификат на порту 8443. Этот сервер предназначен только для того, чтобы запросить сертификат и перенаправить клиента обратно на порт 443, где происходит обратный прокси-сервер в Django.
Это мой Nginx.conf:
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
gzip on;
upstream app {
server django:8000;
}
# Redirect from HTTP to HTTPS
server {
listen *:80;
server_name localhost;
return 301 https://localhost$request_uri;
}
server {
listen *:443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/certificate.pem;
ssl_certificate_key /etc/nginx/ssl/certificate.key;
ssl_password_file /etc/nginx/ssl/certificate.pass;
ssl_verify_client off;
ssl_client_certificate /etc/nginx/ssl/chain.cer;
ssl_verify_depth 3;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers EECDH AESGCM:EDH AESGCM:AES256 EECDH:AES256 EDH;
ssl_prefer_server_ciphers on;
server_tokens off;
underscores_in_headers on;
location /static/ {
autoindex off;
alias /static_files/;
}
location / {
try_files $uri $uri/ @app_web;
}
location @app_web {
proxy_pass http://app;
proxy_pass_request_headers on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header CERTINFO $http_certinfo;
proxy_redirect off;
}
}
server {
listen *:8443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/certificate.pem;
ssl_certificate_key /etc/nginx/ssl/certificate.key;
ssl_password_file /etc/nginx/ssl/certificate.pass;
ssl_verify_client on;
ssl_client_certificate /etc/nginx/ssl/certificate.cer
ssl_verify_depth 3;
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers EECDH AESGCM:EDH AESGCM:AES256 EECDH:AES256 EDH;
ssl_prefer_server_ciphers on;
add_header CERTINFO $ssl_client_s_dn;
return 301 https://$host$request_uri;
}
}
Когда клиент аутентифицируется на порту 8443, и я возвращаю его на порт 443, мне нужно переслать информацию о его сертификате, $ssl_client_s_dn, чтобы быть более конкретным. Для этого я пытаюсь использовать метод add_header на сервере порта 8443 (CERTINFO) и метод proxy_set_header, фиксирующий значение с помощью $http_certinfo на сервере порта 443. Но это решение не работает. Заголовок не пересылается с порта 8443 на сервер порта 443.
Мой вопрос в следующем: есть ли способ сделать это? Могу ли я установить какую-то «глобальную» переменную в блоке http, изменить ее значение на порту 8443 и использовать обновленное значение на порту 443 для пересылки в Django?
Большое вам спасибо!
Комментарии:
1. Нет.
add_header
добавляет заголовок ответа и$http_certinfo
является заголовком запроса. Вы не можете заставить браузер добавить другой заголовок запроса, кроме, возможно, файла cookie.2. Рикардо, но есть ли способ сохранить эту информацию не в заголовке запроса, а в какой-то переменной и поделиться ею с другим сервером? Спасибо за ответ.
3. Вместо
return 301
этого вы должны дублироватьlocation
блоки из первогоserver
блока, чтобы этотserver
блок мог передавать учетные данные непосредственно в приложение.4. Твое решение работает просто отлично, Ричард. Я передал учетные данные непосредственно в приложение и перенаправил клиента обратно на порт 443 через приложение. Спасибо вам за вашу помощь.