ssl - 根据 RFC 2817 在 Nginx 中将 HTTP 升级到 TLS

标签 ssl nginx https tls1.2

我一直在研究如何将 HTTP 连接升级到 TLS 并实现跨代理跃点的端到端隧道。我想在此隧道中使用客户端证书,在几跳后在接收端对其进行操作。 我读了RFC 2817 (HTTP Upgrade to TLS) 看起来这是可能的。我只是不知道如何使用 Nginx 来做到这一点,因为它是 Nginx 的新手。

我想知道我是否犯了一个完全的菜鸟错误,或者这在 Nginx 中是否完全可行。

我的 Nginx 实例 1 具有以下 http block 配置:

http {
  include       mime.types;
  default_type  application/octet-stream;
  log_format main    '$remote_addr - $remote_user [$time_local] '
                   '$ssl_protocol/$ssl_cipher '
                   '$ssl_client_cert '
                   '$ssl_client_raw_cert '
                   'HTTP UPGRADE: $http_upgrade '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent"';

access_log  logs/access.log;

sendfile        on;
keepalive_timeout  65;

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

# HTTPS server
server {
    listen       443 ssl;
    listen       [::]:443 ssl;
    server_name  localhost;

    access_log logs/access-ssl.log main;

    ssl_certificate      /root/certs/server.crt;
    ssl_certificate_key  /root/certs/server.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /root/certs/dhparams.pem;

    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers  on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass https://10.0.3.4/;
    }

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

第二个 Nginx 实例具有以下配置 除了一处不同外,配置几乎相同 proxy_pass https://10.0.3.5/index.html

最后一个 Nginx 实例具有以下配置:

http {
include       mime.types;
default_type  application/octet-stream;
log_format main    '$remote_addr - $remote_user [$time_local] '
                   '$ssl_protocol/$ssl_cipher '
                   '$ssl_client_cert '
                   '$ssl_client_raw_cert '
                   'HTTP UPGRADE: $http_upgrade '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent"';

access_log  logs/access.log;

sendfile        on;
keepalive_timeout  65;

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

# HTTPS server
server {
    listen       443 ssl;
    listen       [::]:443 ssl;
    server_name  localhost;

    access_log logs/access-ssl.log main;

    ssl_certificate      /root/certs/server.crt;
    ssl_certificate_key  /root/certs/server.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /root/certs/dhparams.pem;

    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers  on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    location / {
        root   html;
        index  index.html index.htm;
    }

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

当我使用 HTTPS 访问 URL 时,我确实收到了响应,但日志中没有打印任何关于客户端证书的信息。当我仅使用 HTTP 时,我会收到 301 响应。这是我打的两个电话: $ curl -k -i --cert/root/certs/client-cert.pem --key/root/certs/client-key.pem --header "Upgrade: TLS/1.2"--header "Connection : 升级"https://10.0.3.3/

$ curl -k -i --cert/root/certs/client-cert.pem --key/root/certs/client-key.pem --header "升级:TLS/1.2"-- header “连接:升级” http://10.0.3.3/

最佳答案

RFC 2817 定义了两种 TLS 升级方法:CONNECT 请求和Connection: Upgrade

CONNECT 是浏览器在使用显式配置的 HTTP 代理时发出的 HTTP 请求。它不与透明代理或反向代理一起使用。与例如 squid 相反nginx 是一个网络服务器而不是 HTTP 代理(从浏览器的角度来看),因此不实现 CONNECT 请求。

至于 RFC 2817 中指定的连接升级到 TLS:这只是一个想法,没有浏览器支持这个。这种升级机制实际上在今天的浏览器中使用,但不是用于升级到 TLS,而是仅用于 WebSockets。

关于ssl - 根据 RFC 2817 在 Nginx 中将 HTTP 升级到 TLS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35811238/

相关文章:

linux - stunnel 和 sshuttle 有什么区别

docker - 部署在Docker容器中的Nginx不会暴露部署在另一个Docker容器中的nuxtjs(502 Bad Gateway)

Nginx 配置错误 : can not detect int size

amazon-web-services - 使用 Application Load Balancer 将 http 重定向到 https

node.js - 如何在 Node.js 中进行不安全的 HTTPS 调用

Android、Golang 和 SSL

perl - IO::Socket::SSL 客户端检查服务器证书

ssl - 在 tcp 端口上获取 openvpn 服务器的 ssl 证书

nginx - 我可以在 Nginx Conf 中添加多少个服务器 block

laravel - https 请求 "invalid request (unsupported ssl request)"