国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

云服務(wù)器|WEB服務(wù)器|FTP服務(wù)器|郵件服務(wù)器|虛擬主機(jī)|服務(wù)器安全|DNS服務(wù)器|服務(wù)器知識|Nginx|IIS|Tomcat|

服務(wù)器之家 - 服務(wù)器技術(shù) - 服務(wù)器知識 - 使用Nginx作為HTTPS正向代理服務(wù)器

使用Nginx作為HTTPS正向代理服務(wù)器

2019-07-11 12:34今日頭條阿里云云棲社區(qū) 服務(wù)器知識

正向代理本身并不復(fù)雜,而如何代理加密的HTTPS流量是正向代理需要解決的主要問題。本文將介紹利用NGINX來正向代理HTTPS流量兩種方案,及其使用場景和主要問題。

NGINX主要設(shè)計作為反向代理服務(wù)器,但隨著NGINX的發(fā)展,它同樣能作為正向代理的選項之一。正向代理本身并不復(fù)雜,而如何代理加密的HTTPS流量是正向代理需要解決的主要問題。本文將介紹利用NGINX來正向代理HTTPS流量兩種方案,及其使用場景和主要問題。

HTTP/HTTPS正向代理的分類

簡單介紹下正向代理的分類作為理解下文的背景知識:

按客戶端有無感知的分類

普通代理:在客戶端需要在瀏覽器中或者系統(tǒng)環(huán)境變量手動設(shè)置代理的地址和端口。如squid,在客戶端指定squid服務(wù)器IP和端口3128。

透明代理:客戶端不需要做任何代理設(shè)置,“代理”這個角色對于客戶端是透明的。如企業(yè)網(wǎng)絡(luò)鏈路中的Web Gateway設(shè)備。

按代理是否解密HTTPS的分類

隧道代理 :也就是透傳代理。代理服務(wù)器只是在TCP協(xié)議上透傳HTTPS流量,對于其代理的流量的具體內(nèi)容不解密不感知。客戶端和其訪問的目的服務(wù)器做直接TLS/SSL交互。本文中討論的NGINX代理方式屬于這種模式。

中間人(MITM, Man-in-the-Middle)代理:代理服務(wù)器解密HTTPS流量,對客戶端利用自簽名證書完成TLS/SSL握手,對目的服務(wù)器端完成正常TLS交互。在客戶端-代理-服務(wù)器的鏈路中建立兩段TLS/SSL會話。如Charles,簡單原理描述可以參考文章。

https://www.jianshu.com/p/405f9d76f8c4

注:這種情況客戶端在TLS握手階段實際上是拿到的代理服務(wù)器自己的自簽名證書,證書鏈的驗證默認(rèn)不成功,需要在客戶端信任代理自簽證書的Root CA證書。所以過程中是客戶端有感的。如果要做成無感的透明代理,需要向客戶端推送自建的Root CA證書,在企業(yè)內(nèi)部環(huán)境下是可實現(xiàn)的。

使用Nginx作為HTTPS正向代理服務(wù)器

為什么正向代理處理HTTPS流量需要特殊處理?

作為反向代理時,代理服務(wù)器通常終結(jié) (terminate) HTTPS加密流量,再轉(zhuǎn)發(fā)給后端實例。HTTPS流量的加解密和認(rèn)證過程發(fā)生在客戶端和反向代理服務(wù)器之間。

而作為正向代理在處理客戶端發(fā)過來的流量時,HTTP加密封裝在了TLS/SSL中,代理服務(wù)器無法看到客戶端請求URL中想要訪問的域名,如下圖。所以代理HTTPS流量,相比于HTTP,需要做一些特殊處理。

使用Nginx作為HTTPS正向代理服務(wù)器

NGINX的解決方案

根據(jù)前文中的分類方式,NGINX解決HTTPS代理的方式都屬于透傳(隧道)模式,即不解密不感知上層流量。具體的方式有如下7層和4層的兩類解決方案。

HTTP CONNECT隧道 (7層解決方案)

歷史背景

早在1998年,也就是TLS還沒有正式誕生的SSL時代,主導(dǎo)SSL協(xié)議的Netscape公司就提出了關(guān)于利用web代理來tunneling SSL流量的INTERNET-DRAFT。其核心思想就是利用HTTP CONNECT請求在客戶端和代理之間建立一個HTTP CONNECT Tunnel,在CONNECT請求中需要指定客戶端需要訪問的目的主機(jī)和端口。Draft中的原圖如下:

使用Nginx作為HTTPS正向代理服務(wù)器

整個過程可以參考HTTP權(quán)威指南中的圖:

客戶端給代理服務(wù)器發(fā)送HTTP CONNECT請求。

代理服務(wù)器利用HTTP CONNECT請求中的主機(jī)和端口與目的服務(wù)器建立TCP連接。

代理服務(wù)器給客戶端返回HTTP 200響應(yīng)。

客戶端和代理服務(wù)器建立起HTTP CONNECT隧道,HTTPS流量到達(dá)代理服務(wù)器后,直接通過TCP透傳給遠(yuǎn)端目的服務(wù)器。代理服務(wù)器的角色是透傳HTTPS流量,并不需要解密HTTPS。

使用Nginx作為HTTPS正向代理服務(wù)器

NGINX ngx_http_proxy_connect_module模塊

NGINX作為反向代理服務(wù)器,官方一直沒有支持HTTP CONNECT方法。但是基于NGINX的模塊化、可擴(kuò)展性好的特性,阿里的@chobits提供了ngx_http_proxy_connect_module模塊,來支持HTTP CONNECT方法,從而讓NGINX可以擴(kuò)展為正向代理。

環(huán)境搭建

以CentOS 7的環(huán)境為例。

1) 安裝

對于新安裝的環(huán)境,參考正常的安裝步驟和安裝這個模塊的步驟(https://github.com/chobits/ngx_http_proxy_connect_module),把對應(yīng)版本的patch打上之后,在configure的時候加上參數(shù)--add-module=/path/to/ngx_http_proxy_connect_module,示例如下:

./configure

--user=www

--group=www

--prefix=/usr/local/nginx

--with-http_ssl_module

--with-http_stub_status_module

--with-http_realip_module

--with-threads

--add-module=/root/src/ngx_http_proxy_connect_module

對于已經(jīng)安裝編譯安裝完的環(huán)境,需要加入以上模塊,步驟如下:

#停止NGINX服務(wù)

#systemctlstopnginx

#備份原執(zhí)行文件

#cp/usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx.bak

#在源代碼路徑重新編譯

#cd/usr/local/src/nginx-1.16.0

./configure

--user=www

--group=www

--prefix=/usr/local/nginx

--with-http_ssl_module

--with-http_stub_status_module

--with-http_realip_module

--with-threads

--add-module=/root/src/ngx_http_proxy_connect_module

#make

#不要makeinstall

#將新生成的可執(zhí)行文件拷貝覆蓋原來的nginx執(zhí)行文件

#cpobjs/nginx/usr/local/nginx/sbin/nginx

#/usr/bin/nginx-V

nginxversion:nginx/1.16.0

builtbygcc4.8.520150623(RedHat4.8.5-36)(GCC)

builtwithOpenSSL1.0.2k-fips26Jan2017

TLSSNIsupportenabled

configurearguments:--user=www--group=www--prefix=/usr/local/nginx--with-http_ssl_module--with-http_stub_status_module--with-http_realip_module--with-threads--add-module=/root/src/ngx_http_proxy_connect_module

2) nginx.conf文件配置

server{

listen443;

#dnsresolverusedbyforwardproxying

resolver114.114.114.114;

#forwardproxyforCONNECTrequest

proxy_connect;

proxy_connect_allow443;

proxy_connect_connect_timeout10s;

proxy_connect_read_timeout10s;

proxy_connect_send_timeout10s;

#forwardproxyfornon-CONNECTrequest

location/{

proxy_passhttp://$host;

proxy_set_headerHost$host;

}

}

使用場景

7層需要通過HTTP CONNECT來建立隧道,屬于客戶端有感知的普通代理方式,需要在客戶端手動配置HTTP(S)代理服務(wù)器IP和端口。在客戶端用curl 加-x參數(shù)訪問如下:

#curlhttps://www.baidu.com-svo/dev/null-x39.105.196.164:443

*Abouttoconnect()toproxy39.105.196.164port443(#0)

*Trying39.105.196.164...

*Connectedto39.105.196.164(39.105.196.164)port443(#0)

*EstablishHTTPproxytunneltowww.baidu.com:443

>CONNECTwww.baidu.com:443HTTP/1.1

>Host:www.baidu.com:443

>User-Agent:curl/7.29.0

>Proxy-Connection:Keep-Alive

>

<

*ProxyrepliedOKtoCONNECTrequest

*InitializingNSSwithcertpath:sql:/etc/pki/nssdb

*CAfile:/etc/pki/tls/certs/ca-bundle.crt

CApath:none

*SSLconnectionusingTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

*Servercertificate:

*subject:CN=baidu.com,O="BeijingBaiduNetcomScienceTechnologyCo.,Ltd",OU=serviceoperationdepartment,L=beijing,ST=beijing,C=CN

...

>GET/HTTP/1.1

>User-Agent:curl/7.29.0

>Host:www.baidu.com

>Accept:*/*

>

...

{[datanotshown]

從上面-v參數(shù)打印出的細(xì)節(jié),可以看到客戶端先往代理服務(wù)器39.105.196.164建立了HTTP CONNECT隧道,代理回復(fù)HTTP/1.1 200 Connection Established后就開始交互TLS/SSL握手和流量了。

NGINX stream (4層解決方案)

既然是使用透傳上層流量的方法,那可不可做成“4層代理”,對TCP/UDP以上的協(xié)議實現(xiàn)徹底的透傳呢?答案是可以的。NGINX官方從1.9.0版本開始支持ngx_stream_core_module模塊,模塊默認(rèn)不build,需要configure時加上--with-stream選項來開啟。

問題

用NGINX stream在TCP層面上代理HTTPS流量肯定會遇到本文一開始提到的那個問題:代理服務(wù)器無法獲取客戶端想要訪問的目的域名。因為在TCP的層面獲取的信息僅限于IP和端口層面,沒有任何機(jī)會拿到域名信息。要拿到目的域名,必須要有拆上層報文獲取域名信息的能力,所以NGINX stream的方式不是完全嚴(yán)格意義上的4層代理,還是要略微借助些上層能力。

ngx_stream_ssl_preread_module模塊

要在不解密的情況下拿到HTTPS流量訪問的域名,只有利用TLS/SSL握手的第一個Client Hello報文中的擴(kuò)展地址SNI (Server Name Indication)來獲取。NGINX官方從1.11.5版本開始支持利用ngx_stream_ssl_preread_module模塊來獲得這個能力,模塊主要用于獲取Client Hello報文中的SNI和ALPN信息。對于4層正向代理來說,從Client Hello報文中提取SNI的能力是至關(guān)重要的,否則NGINX stream的解決方案無法成立。同時這也帶來了一個限制,要求所有客戶端都需要在TLS/SSL握手中帶上SNI字段,否則NGINX stream代理完全沒辦法知道客戶端需要訪問的目的域名。

環(huán)境搭建

1) 安裝

對于新安裝的環(huán)境,參考正常的安裝步驟,直接在configure的時候加上--with-stream,--with-stream_ssl_preread_module和--with-stream_ssl_module選項即可。示例如下:

./configure

--user=www

--group=www

--prefix=/usr/local/nginx

--with-http_ssl_module

--with-http_stub_status_module

--with-http_realip_module

--with-threads

--with-stream

--with-stream_ssl_preread_module

--with-stream_ssl_module

對于已經(jīng)安裝編譯安裝完的環(huán)境,需要加入以上3個與stream相關(guān)的模塊,步驟如下:

#停止NGINX服務(wù)

#systemctlstopnginx

#備份原執(zhí)行文件

#cp/usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx.bak

#在源代碼路徑重新編譯

#cd/usr/local/src/nginx-1.16.0

#./configure

--user=www

--group=www

--prefix=/usr/local/nginx

--with-http_ssl_module

--with-http_stub_status_module

--with-http_realip_module

--with-threads

--with-stream

--with-stream_ssl_preread_module

--with-stream_ssl_module

#make

#不要makeinstall

#將新生成的可執(zhí)行文件拷貝覆蓋原來的nginx執(zhí)行文件

#cpobjs/nginx/usr/local/nginx/sbin/nginx

#nginx-V

nginxversion:nginx/1.16.0

builtbygcc4.8.520150623(RedHat4.8.5-36)(GCC)

builtwithOpenSSL1.0.2k-fips26Jan2017

TLSSNIsupportenabled

configurearguments:--user=www--group=www--prefix=/usr/local/nginx--with-http_ssl_module--with-http_stub_status_module--with-http_realip_module--with-threads--with-stream--with-stream_ssl_preread_module--with-stream_ssl_module

2) nginx.conf文件配置

NGINX stream與HTTP不同,需要在stream塊中進(jìn)行配置,但是指令參數(shù)與HTTP塊都是類似的,主要配置部分如下:

stream{

resolver114.114.114.114;

server{

listen443;

ssl_prereadon;

proxy_connect_timeout5s;

proxy_pass$ssl_preread_server_name:$server_port;

}

}

使用場景

對于4層正向代理,NGINX對上層流量基本上是透傳,也不需要HTTP CONNECT來建立隧道。適合于透明代理的模式,比如將訪問的域名利用DNS解定向到代理服務(wù)器。我們可以通過在客戶端綁定/etc/hosts來模擬。

在客戶端:

cat/etc/hosts

...

#把域名www.baidu.com綁定到正向代理服務(wù)器39.105.196.164

39.105.196.164www.baidu.com

#正常利用curl來訪問www.baidu.com即可。

#curlhttps://www.baidu.com-svo/dev/null

*Abouttoconnect()towww.baidu.comport443(#0)

*Trying39.105.196.164...

*Connectedtowww.baidu.com(39.105.196.164)port443(#0)

*InitializingNSSwithcertpath:sql:/etc/pki/nssdb

*CAfile:/etc/pki/tls/certs/ca-bundle.crt

CApath:none

*SSLconnectionusingTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

*Servercertificate:

*subject:CN=baidu.com,O="BeijingBaiduNetcomScienceTechnologyCo.,Ltd",OU=serviceoperationdepartment,L=beijing,ST=beijing,C=CN

*startdate:5月0901:22:022019GMT

*expiredate:6月2505:31:022020GMT

*commonname:baidu.com

*issuer:CN=GlobalSignOrganizationValidationCA-SHA256-G2,O=GlobalSignnv-sa,C=BE

>GET/HTTP/1.1

>User-Agent:curl/7.29.0

>Host:www.baidu.com

>Accept:*/*

>

<

{[datanotshown]

*Connection#0tohostwww.baidu.comleftintact

常見問題

1) 客戶端手動設(shè)置代理導(dǎo)致訪問不成功

4層正向代理是透傳上層HTTPS流量,不需要HTTP CONNECT來建立隧道,也就是說不需要客戶端設(shè)置HTTP(S)代理。如果我們在客戶端手動設(shè)置HTTP(s)代理是否能訪問成功呢? 我們可以用curl -x來設(shè)置代理為這個正向服務(wù)器訪問測試,看看結(jié)果:

#curlhttps://www.baidu.com-svo/dev/null-x39.105.196.164:443

*Abouttoconnect()toproxy39.105.196.164port443(#0)

*Trying39.105.196.164...

*Connectedto39.105.196.164(39.105.196.164)port443(#0)

*EstablishHTTPproxytunneltowww.baidu.com:443

>CONNECTwww.baidu.com:443HTTP/1.1

>Host:www.baidu.com:443

>User-Agent:curl/7.29.0

>Proxy-Connection:Keep-Alive

>

*ProxyCONNECTaborted

*Connection#0tohost39.105.196.164leftintact

可以看到客戶端試圖于正向NGINX前建立HTTP CONNECT tunnel,但是由于NGINX是透傳,所以把CONNECT請求直接轉(zhuǎn)發(fā)給了目的服務(wù)器。目的服務(wù)器不接受CONNECT方法,所以最終出現(xiàn)"Proxy CONNECT aborted",導(dǎo)致訪問不成功。

2) 客戶端沒有帶SNI導(dǎo)致訪問不成功

上文提到用NGINX stream做正向代理的關(guān)鍵因素之一是利用ngx_stream_ssl_preread_module提取出Client Hello中的SNI字段。如果客戶端客戶端不攜帶SNI字段,會造成代理服務(wù)器無法獲知目的域名的情況,導(dǎo)致訪問不成功。

在透明代理模式下(用手動綁定hosts的方式模擬),我們可以在客戶端用openssl來模擬:

#openssls_client-connectwww.baidu.com:443-msg

CONNECTED(00000003)

>>>TLS1.2[length0005]

160301011c

>>>TLS1.2Handshake[length011c],ClientHello

0100011803036b2e7586526cd5a580d7

a461656d725333fb33f043a3aac24ae3

47849f698bd60000acc030c02cc028c0

24c014c00a00a500a300a1009f006b00

6a006900680039003800370036008800

8700860085c032c02ec02ac026c00fc0

05009d003d00350084c02fc02bc027c0

23c013c00900a400a200a0009e006700

40003f003e0033003200310030009a00

99009800970045004400430042c031c0

2dc029c025c00ec004009c003c002f00

960041c012c008001600130010000dc0

0dc003000a0007c011c007c00cc00200

05000400ff01000043000b0004030001

02000a000a0008001700190018001600

230000000d0020001e06010602060305

01050205030401040204030301030203

03020102020203000f000101

140285606590352:error:140790E5:SSLroutines:ssl23_write:sslhandshakefailure:s23_lib.c:177:

---

nopeercertificateavailable

---

NoclientcertificateCAnamessent

---

SSLhandshakehasread0bytesandwritten289bytes

...

openssl s_client默認(rèn)不帶SNI,可以看到上面的請求在TLS/SSL握手階段,發(fā)出Client Hello后就結(jié)束了。因為代理服務(wù)器不知道要把Client Hello往哪個目的域名轉(zhuǎn)發(fā)。

如果用openssl帶servername參數(shù)來指定SNI,則可以正常訪問成功,命令如下:

#openssls_client-connectwww.baidu.com:443-servernamewww.baidu.com

總結(jié)

本文總結(jié)了NGINX利用HTTP CONNECT隧道和NGINX stream兩種方式做HTTPS正向代理的原理,環(huán)境搭建,使用場景和主要問題,希望給大家在做各種場景的正向代理時提供參考。

作者:懷知

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲精品九九 | 精品无码三级在线观看视频 | 久久综合九色综合网站 | 日操| 国产免费黄色 | 亚洲综合在线视频 | 成视频年人免费看黄网站 | 黄色国产免费看 | 久久精品一区 | 国产一级黄色av | 日韩成人免费视频 | 4h影院| 一级片在线播放 | 国产午夜精品一区二区三区免费 | 亚洲天堂网站 | 日韩在线视频观看 | 免费一级网站 | 国产精品亚洲a | 日韩一区二区三区在线观看 | 久久三区 | 一级免费av | sese综合| 国产日韩精品久久 | 国产精品久久久久久久久久久久久久久久 | 亚洲国产综合在线观看 | 欧美区国产 | 在线免费成人 | 欧美精品欧美精品系列 | 国产精品久久久久久久久小说 | 亚洲九九九 | 午夜影院免费观看 | 亚洲永久免费视频 | 91中文在线 | 欧美第一网站 | 日本视频二区 | 精品国产一区二区三区日日嗨 | 亚洲91av | 国产精品二区三区 | 天天综合久久 | 国产精品免费观看 | 看黄免费在线 |