nginx反向代理,支持SNI的https回源


轉載自:https://blog.fcci.cn/2016/05/nginx-https-proxy-sni/

作者姚毅,版權所有,署名轉載

背景:

這事起源於需要一個反向代理,請求的后端是某開放雲的CDN,CDN配置為基於HTTPS的虛擬主機(單IP多Host區分的虛擬主機)

注意:所以本文並不是你的nginx提供了https服務,而在於反向代理的后端是否為https服務。

正常nginx配置了SSL是可以通過HTTPS訪問后端的,但是對SNI的支持有點麻煩。

代理服務器是nginx。以下為配置過程:

首先支持SNI協議的openssl版本最低為0.9.8f

Mozilla NSS 3.11.1 client-side only
OpenSSL
0.9.8f (released 11 Oct 2007) – not compiled in by default, can be compiled in with config option ‘–enable-tlsext’
0.9.8j (released 07 Jan 2009) through 1.0.0 (released 29 March 2010) – compiled in by default
GNU TLS
libcurl / cURL since 7.18.1 (released 30 Mar 2008) when compiled against an SSL/TLS toolkit with SNI support
Python 3.2 (ssl, urllib and httplib modules)
Qt 4.8
Oracle Java 7 JSSE

這里選用了最新的openssl 1.0.1t

openssl安裝

1、下載openssl

curl -o openssl.tar.gz https://www.openssl.org/source/openssl-1.0.1t.tar.gz

2、解壓縮

tar -xvf openssl-1.0.1t.tar.gz

openssl這里不用編譯,有源代碼就可以了

nginx安裝

1、下載nginx

nginx從1.7之后開始支持SNI proxy指令,我這里選擇的nginx 1.10

wget http://nginx.org/download/nginx-1.10.0.tar.gz

2、解壓縮

tar -xvf nginx-1.10.0.tar.gz

3、進入nginx目錄,配置

cd nginx-1.10.0

以下是我的配置命令,目錄自行選擇

./configure –prefix=/opt/nginx/ –with-http_ssl_module –with-openssl=~/openssl-1.0.1t

上面參數解釋:

–prefix是nginx安裝目錄

–with-http_ssl_module是啟用ssl支持

–with-openssl是剛剛下載的openssl代碼目錄

4、編譯、安裝

make && make install

編譯之后,進入nginx的sbin/nginx -V 看一下是否支持

nginx version: nginx/1.10.0
built by gcc 3.4.5 20051201 (Red Hat 3.4.5-2)
built with OpenSSL 1.0.1t 3 May 2016
TLS SNI support enabled

如果有TLS SNI support enabled就表示支持SNI

配置nginx

修改nginx安裝后的conf/nginx.conf文件

以下是我的server配置節

以上配置酌情修改,注意以下幾點:

1、proxy_pass 后面是https://這說明請求以https協議發出

2、為了安全,proxy_ssl_verify 應該配置為on,這里便於調試配置了off,如果配置了on,請確保你的ca文件中有對方服務器的證書

3、ssl_protocols 表示支持的協議,印象中是sslv3和tls1.0以后才支持的SNI,所以都寫上吧。

4、最關鍵的一句proxy_ssl_server_name on最關鍵的,也就是把主機名字傳遞給后端服務器,讓對方服務器在TLS握手層面就可以收到host,便於打到具體的主機。(nginx 1.7開始支持)

重啟nginx服務器(涉及socket監聽的不要使用reload,因為無法reload信號無法讓nginx重新監聽)

驗證

curl -v -x 127.0.0.1:8443 http://www.symantec.com/

應返回:
* Trying 127.0.0.1…
* Connected to 127.0.0.1 (127.0.0.1) port 8443 (#0)
> HEAD http://www.symantec.com/ HTTP/1.1
> Host: www.symantec.com
> User-Agent: curl/7.47.1
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK

特別說明一下:http://www.symantec.com/這里雖然寫的是http,但實際上代理走的是https協議,這里不能直接寫https

未配置SNI會出現的問題

目前發現,對於使用SNI做域名識別的HTTPS Web服務器,如果代理服務器不發送SNI,會返回502錯誤。即無法正常和后端通信。

參考資料

SNI(Server Name Indication)https://en.wikipedia.org/wiki/Server_Name_Indication

nginx關於proxy_ssl_server_name的配置:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_server_name


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM