2016-03-05 78 views
0

HTTP升級到Nginx中的TLS我一直在研究如何將HTTP連接升級到TLS,並實現跨端代理的端到端隧道。我希望在這個隧道中使用客戶端證書,在幾跳之後在接收端進行處理。 我讀RFC 2817(HTTP升級到TLS),似乎這是可能的。我只是不知道如何使用Nginx作爲Nginx新手。根據RFC 2817

我想知道我是否在做一個完整的noob錯誤,或者如果這在Nginx中是完全可能的。

我Nginx的實例1以下配置的HTTP模塊:

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: Upgrade" https://10.0.3.3/

$ curl -k -i --cert /root/certs/client-cert.pem --key /root/certs/client-key.pem --header "Upgrade: TLS/1.2" --header "Connection: Upgrade" http://10.0.3.3/

回答

1

RFC 2817定義了TLS升級方法有兩種:連接請求,並Connection: Upgrade

CONNECT是瀏覽器在使用明確配置的HTTP代理時完成的HTTP請求。它不能用於透明代理或反向代理。與例如squid相反,nginx是一個Web服務器,而不是HTTP代理(從瀏覽器的角度來看),因此不會實現CONNECT請求。

至於連接升級到RFC 2817中指定的TLS:這只是一個想法,沒有瀏覽器支持這一點。這種升級機制實際上在今天的瀏覽器中使用,但不用於升級到TLS,而僅用於WebSockets。

+0

非常感謝你的澄清。我打算使用在應用程序級別實現的此功能,並且我不打算將它用於瀏覽器。這個想法是讓一個應用程序進行調用,呈現自己的證書,並用請求的資源一直代理到一個服務。到達最終服務的跳數有多個,並且最終服務將根據原始發件人的證書對請求進行身份驗證和授權。 – Tempo

+0

@Tempo:由於TLS是端到端加密,因此只有端點可以請求並驗證客戶端證書。這意味着無法通過客戶端證書或中間的某些軟件(nginx或其他)中的請求資源來選擇端點,並且仍然能夠將客戶端證書無損轉發到端點。 –

+0

非常感謝您的評論,非常感謝。如果在這種情況下TLS(和HTTPS隧道/升級)不是一個選項,是否有任何其他經過驗證的解決方案可以用來實現所需的結果?除了從零開始實施自定義協議?即使對於專有協議,我甚至不知道如何開始實施它。作爲一個Nginx模塊呢? – Tempo