代理(Proxy)也称网络代理,是一种特殊的网络服务,允许一个(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。
HTTP协议中,允许通过中间人(Intermediaries)来完成请求,“中间人”的交互流程,如下图所示:
客户端原本发送给目标服务的报文,现在会发送给中间人,由中间人转发到目标服务器;当目标服务器返回后,中间人会将报文发送给客户端
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之类的并没有处理
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。