1
代理(Proxy)也称网络代理,是一种特殊的网络服务,允许一个(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。

HTTP协议中,允许通过中间人(Intermediaries)来完成请求,“中间人”的交互流程,如下图所示:
image.png

客户端原本发送给目标服务的报文,现在会发送给中间人,由中间人转发到目标服务器;当目标服务器返回后,中间人会将报文发送给客户端
HTTP代理常见的应用场景有:伪造请求来源,绕过某些网络限制(你懂),抓包等等。

HTTP 代理

这种“转发”形式的代理,工作原理很简单:当开启代理后,HTTP首部报文会修改为完整URL,代理服务器就会从HTTP Request报文中解析第一行的目标服务信息,比如:

# 未开启代理时的首行报文
GET /v-5fc4b0fa/global/img/logo-b.svg HTTP/1.1

# 开启代理后,发送的首行报文
GET http://cdn.segmentfault.com/v-5fc4b0fa/global/img/logo-b.svg HTTP/1.1

那么该请求的目标服务就是cdn.segmentfault.com 8080,此时收到消息的Proxy Server会连接到目标服务器cdn.segmentfault.com 8080,然后将收到的客户端报文发送到目标服务器,同时将收到的目标服务器报文转发给客户端

至于是收到完整的HTTP报文才转发,还是每收到一个分组就转发,HTTP协议中并没有看到相关的规范

HTTP 隧道代理(Tunnel)

隧道代理主要是为了SSL(TLS)提供的,因为上面介绍的普通代理无法作为HTTPS的代理,HTTPS协议下会加密数据,所以解析报文头这一步就无法工作了

在隧道代理下,和目标服务进行SSL握手的过程会交由代理服务器完成,代理服务还是会转发客户端发送和目标服务返回的每一个分组报文。

隧道代理(HTTPS)下,客户端首先会发送一个CONNECT类型的首行报文,如下所示:

CONNECT home.netscape.com:443 HTTP/1.1
User-agent: Mozilla/4.0
...

隧道代理服务收到首部报文后,会解析CONNECT信息,从中获取目标服务的地址(主机+端口),用来和目标主机建立连接(SSL握手),当连接建立完成后像客户端发送一段连接建立成功的报文:

HTTP/1.1 200 Connection Established

当客户端收到代理服务返回的连接建立成功报文时,就会进行SSL(TLS)握手/HTTP报文加密传输等工作,对于隧道代理服务来说,完成了CONNECT首部解析和返回连接建立成功报文之后就没有特殊工作了,只需要将客户端发送的报文直接转发给目标服务器,同时将收到的目标服务器报文转发给客户端。

在这个过程里,SSL(TLS)握手过程还是由客户端实现的,隧道代理服务并不关心握手的细节,它只是盲目的转发报文

Socks 代理

Socks代理虽然也可以作为HTTP的代理,但是它本身并不是面向HTTP协议的,可参考
https://zh.wikipedia.org/zh-hans/SOCKS

基于Netty的HTTP Proxy Server实现

https://github.com/kongwu-/netty-proxy-server
基本实现,只完成了核心的proxy功能,keepAlive之类的并没有处理

相关文章

参考


空无
3.3k 声望4.3k 粉丝

坚持原创,专注分享 JAVA、网络、IO、JVM、GC 等技术干货