时间:2023-02-10 16:48:01 | 来源:建站知识
时间:2023-02-10 16:48:01 来源:建站知识
NGINX主要设计作为反向代理服务器,但随着NGINX的发展,它同样能作为正向代理的选项之一。正向代理本身并不复杂,而如何代理加密的HTTPS流量是正向代理需要解决的主要问题。本文将介绍利用NGINX来正向代理HTTPS流量两种方案,及其使用场景和主要问题。./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
对于已经安装编译安装完的环境,需要加入以上模块,步骤如下:# 停止NGINX服务# systemctl stop nginx# 备份原执行文件# 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# 不要make install# 将新生成的可执行文件拷贝覆盖原来的nginx执行文件# cp objs/nginx /usr/local/nginx/sbin/nginx# /usr/bin/nginx -Vnginx version: nginx/1.16.0built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --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
server { listen 443; # dns resolver used by forward proxying resolver 114.114.114.114; # forward proxy for CONNECT request proxy_connect; proxy_connect_allow 443; proxy_connect_connect_timeout 10s; proxy_connect_read_timeout 10s; proxy_connect_send_timeout 10s; # forward proxy for non-CONNECT request location / { proxy_pass http://$host; proxy_set_header Host $host; } }
# curl https://www.baidu.com -svo /dev/null -x 39.105.196.164:443* About to connect() to proxy 39.105.196.164 port 443 (#0)* Trying 39.105.196.164...* Connected to 39.105.196.164 (39.105.196.164) port 443 (#0)* Establish HTTP proxy tunnel to www.baidu.com:443> CONNECT www.baidu.com:443 HTTP/1.1> Host: www.baidu.com:443> User-Agent: curl/7.29.0> Proxy-Connection: Keep-Alive>< HTTP/1.1 200 Connection Established< Proxy-agent: nginx<* Proxy replied OK to CONNECT request* Initializing NSS with certpath: sql:/etc/pki/nssdb* CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256* Server certificate:* subject: CN=baidu.com,O="Beijing Baidu Netcom Science Technology Co., Ltd",OU=service operation department,L=beijing,ST=beijing,C=CN...> GET / HTTP/1.1> User-Agent: curl/7.29.0> Host: www.baidu.com> Accept: */*>< HTTP/1.1 200 OK...{ [data not shown]
从上面-v参数打印出的细节,可以看到客户端先往代理服务器39.105.196.164建立了HTTP CONNECT隧道,代理回复HTTP/1.1 200 Connection Established后就开始交互TLS/SSL握手和流量了。./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
对于已经安装编译安装完的环境,需要加入以上3个与stream相关的模块,步骤如下:# 停止NGINX服务# systemctl stop nginx# 备份原执行文件# 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# 不要make install# 将新生成的可执行文件拷贝覆盖原来的nginx执行文件# cp objs/nginx /usr/local/nginx/sbin/nginx# nginx -Vnginx version: nginx/1.16.0built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)built with OpenSSL 1.0.2k-fips 26 Jan 2017TLS SNI support enabledconfigure arguments: --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
stream { resolver 114.114.114.114; server { listen 443; ssl_preread on; proxy_connect_timeout 5s; proxy_pass $ssl_preread_server_name:$server_port; }}
cat /etc/hosts...# 把域名www.baidu.com绑定到正向代理服务器39.105.196.16439.105.196.164 www.baidu.com# 正常利用curl来访问www.baidu.com即可。# curl https://www.baidu.com -svo /dev/null* About to connect() to www.baidu.com port 443 (#0)* Trying 39.105.196.164...* Connected to www.baidu.com (39.105.196.164) port 443 (#0)* Initializing NSS with certpath: sql:/etc/pki/nssdb* CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256* Server certificate:* subject: CN=baidu.com,O="Beijing Baidu Netcom Science Technology Co., Ltd",OU=service operation department,L=beijing,ST=beijing,C=CN* start date: 5月 09 01:22:02 2019 GMT* expire date: 6月 25 05:31:02 2020 GMT* common name: baidu.com* issuer: CN=GlobalSign Organization Validation CA - SHA256 - G2,O=GlobalSign nv-sa,C=BE> GET / HTTP/1.1> User-Agent: curl/7.29.0> Host: www.baidu.com> Accept: */*>< HTTP/1.1 200 OK< Accept-Ranges: bytes< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform< Connection: Keep-Alive< Content-Length: 2443< Content-Type: text/html< Date: Fri, 21 Jun 2019 05:46:07 GMT< Etag: "5886041d-98b"< Last-Modified: Mon, 23 Jan 2017 13:24:45 GMT< Pragma: no-cache< Server: bfe/1.0.8.18< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/<{ [data not shown]* Connection #0 to host www.baidu.com left intact
# curl https://www.baidu.com -svo /dev/null -x 39.105.196.164:443* About to connect() to proxy 39.105.196.164 port 443 (#0)* Trying 39.105.196.164...* Connected to 39.105.196.164 (39.105.196.164) port 443 (#0)* Establish HTTP proxy tunnel to www.baidu.com:443> CONNECT www.baidu.com:443 HTTP/1.1> Host: www.baidu.com:443> User-Agent: curl/7.29.0> Proxy-Connection: Keep-Alive>* Proxy CONNECT aborted* Connection #0 to host 39.105.196.164 left intact
可以看到客户端试图于正向NGINX前建立HTTP CONNECT tunnel,但是由于NGINX是透传,所以把CONNECT请求直接转发给了目的服务器。目的服务器不接受CONNECT方法,所以最终出现"Proxy CONNECT aborted",导致访问不成功。# openssl s_client -connect www.baidu.com:443 -msgCONNECTED(00000003)>>> TLS 1.2 [length 0005] 16 03 01 01 1c>>> TLS 1.2 Handshake [length 011c], ClientHello 01 00 01 18 03 03 6b 2e 75 86 52 6c d5 a5 80 d7 a4 61 65 6d 72 53 33 fb 33 f0 43 a3 aa c2 4a e3 47 84 9f 69 8b d6 00 00 ac c0 30 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f 00 96 00 41 c0 12 c0 08 00 16 00 13 00 10 00 0d c0 0d c0 03 00 0a 00 07 c0 11 c0 07 c0 0c c0 02 00 05 00 04 00 ff 01 00 00 43 00 0b 00 04 03 00 01 02 00 0a 00 0a 00 08 00 17 00 19 00 18 00 16 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01140285606590352:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:---no peer certificate available---No client certificate CA names sent---SSL handshake has read 0 bytes and written 289 bytes...
openssl s_client默认不带SNI,可以看到上面的请求在TLS/SSL握手阶段,发出Client Hello后就结束了。因为代理服务器不知道要把Client Hello往哪个目的域名转发。# openssl s_client -connect www.baidu.com:443 -servername www.baidu.com
关键词:代理,服务,使用