正向代理

1,443 阅读5分钟

一、正向代理

  正向代理:其实就是代理服务器代理了客户端,去和目标服务器进行交互。主要应用场景一般是面向互联网,比如VPN、代理等工具访问google,其实就是正向代理,通过正向代理访问目标服务器,目标服务器是不知道真正的客户端是谁?甚至不知道访问自己的是个代理。 forward.png

二、主要用途:

1)绕过访问限制

  通过代理服务器,可以绕过自身IP的访问限制,访问只允许特定IP访问的网站收缩访问控制、访问国外网站、教育网等。

2)提高访问速度

  通过代理服务器设置缓存,当不同用户访问相同信息时,可以直接从缓存中取出信息返回给用户,提高访问速度

3)隐藏客户端真实IP

三、使用Nginx作为正向代理

虽然Nginx 主要设计作为反向代理服务器器,但是随着Nginx 的发展同样也可以作为正向代理服务器来使用。

3.1 使用nginx 作为正向代理,从客户端有无感知角度来看:

1)对客户端不透明:客户端需要在浏览器中或者系统的环境变量中主动的去设置代理服务器的IP和端口。

2)对客户端透明:客户端不需要做任何代理设置(4层正向代理),可以从DNS层面将解析IP设置为代理服务器的IP

3.2 从代理服务器是否解决HTTPS流量的视角看,可以分为

1)隧道代理: 代理服务器在TCP协议的基础上透传HTTPS流量

2)中间人代理: 代理服务器解密 HTTPS 流量,对客户端利用自签名证书完成 TLS / SSL 握手,对目的服务器端完成正常 TLS 交互。在客户端 - 代理 - 服务器的链路中建立两段 TLS / SSL 会话(比如Charles)

  备注: Nginx 作为正向代理(正向代理服务器上没有绑定目标站点的证书,因为正向代理服务器代理的是客户端,对目标服务器器是透明的)在处理HTTPS流量的时候需要做特殊处理,因为作为正向代理在处理客户端发过来的流量的时候,HTTP业务流量封装在TLS/SSL中,代理服务器看不到客户端请求的URL和站点域名,因此与处理HTTP请求相比,HTTPS业务流量需要做些特殊的处理。

forward2.png

四、Nginx在正向代理中的解决方案

   Nginx解决HTTPS代理的方式都属于透传模式,具体方式有如下7层和四层两种方案:

4.1 (方式一) 7层解决方案(HTTP connect 隧道)

   Nginx下的该解决方案是由阿里大佬@chobits 提供的ngx_http_proxy_connect_module模块来支持的,HTTP connect支持的原理如下:

1)客户端给代理服务器发送 HTTP CONNECT 请求。

2)代理服务器利用 HTTP CONNECT 请求中的主机和端口与目的服务器建立 TCP 连接。

3)代理服务器给客户端返回 HTTP 200 响应。

4)客户端和代理服务器建立起 HTTP CONNECT 隧道,HTTPS 流量到达代理服务器后,直接通过 TCP 透传远端目的服务器。代理服务器的角色是透传 HTTPS 流量,并不需要解密 HTTPS。

图片

实验验证

环境:centos7.7,openresty-1.15.8.3 搭建正向代理服务器\

环境搭建:

1、安装补丁/root/openresty/openresty-1.15.8.3/bundle/nginx-1.15.8

patch -p1 <ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch

2、编译./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= ngx_http_proxy_connect_module
gmake gmake install

3、配置
server {    
listen                         3128;
# dns resolver used by forward proxying    
resolver                       8.8.8.8;
     # forward proxy for CONNECT request    
     proxy_connect;    
     proxy_connect_allow            443 563;    
     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;    
     } 
 }

实验结果:

   在客户端浏览器上配置Nginx 正向代理服务器访问,从流量抓包中可以看出,客户端先向代理服务器建立了HTTP Connect 隧道,代理服务器回复HTTP/1.1 200连接建立后就开始交互TLS/SSL握手和流量了。 c-forward.png

c-forward2.png

c-forward3.png

4.2 (方式二)4层解决方案

   Nginx官方模块ngx_stream_core_module模块支持4层代理,对TCP/UDP以上的协议实现透传。

   备注:同样的Nginx在TCP层面代理HTTPS流量仍然面对无法获取客户端想要访问的域名,因为在TCP层面获取的信息仅限于IP和端口层面,要先拿到域名必须要有拆上层报文的获取域名信息的能力,这就说明Nginx的4层代理并发绝对意义上的4层。

   NGINX 官方从 1.11.5 版本开始支持利用ngx_stream_ssl_preread_module模块,利用TLS/SSL握手的第一个客户端hello报文中的扩展地址SNI来获取请求流量中的域名,这就要求客户端在HTTPS请求中TLS/SSL握手中带上SNI字段,否则Nginx stream 代理完全没办法知道客户端想要访问的域名。

实验验证:

实验环境同上,编译的时候需要在configure 加上–with-stream, - with-stream_ssl_preread_module 和–with-stream_ssl_module

1、 编译安装
./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

gmake  gmake install

2、配置
stream {   
resolver 8.8.8.8;    
  server {        
    listen 443;      
    ssl_preread on;       
    proxy_connect_timeout 5s;      
   proxy_pass $ssl_preread_server_name:$server_port;   
  }
}

实验结果:

  对于 4 层正向代理,NGINX 对上层流量基本上是透传,也不需要 HTTP CONNECT 来建立隧道。适合于对客户端透明的方式使用,只需要将访问的域名利用 DNS 解定向到代理服务器,在客户端绑定/ etc / hosts 中来模拟。

192.168.187.184 www.baidu.com

c-stream-forward.png

image.png