Keen的博客

记录所思、所想、所遇

欢迎来到我的个人站~


【网络技术】代理服务器原理

1. 代理技术原理

为了安全起见,我们的网络存在各种防火墙,Client与Server的连接,时常无法直接发起,因为防火墙阻断了之间的请求,比如:在中国访问国外部分网站google等,被ISP运营商防火墙直接拦截了。代理技术,就是为了此处而生,它相当于在Client和Server这条无法连同的通道之外,再构筑起一条新的连接通道。

使用代理,本质上是在Client和Server之外,增加了一个新的Proxy服务,这个Proxy服务可以直接被Client访问,同时它又能连接Server,这样Client与Server之间虽然不通,但是可以绕行,通过Proxy去间接访问,也就是Client访问的直接目标地址,不再是Server,而是Proxy。那Client访问Proxy,Proxy怎么知道把请求转发到Server上去呢?这就需要协议来支撑,网络中很多协议支持Proxy代理,比如Http、Socks等。本质上,是Client的请求包原理只需要地址五元组(源IP+源Port+目标IP+目标Port+协议类型)就可以实现通信,现在在此基础上增加了Proxy地址信息,Client请求包包含了地址八元组(源IP+源Port+目标IP+目标Port+协议类型+代理IP+代理Port+代理协议类型),通过这种方式实现了通信,具体可以参考后续的源码分析。

2. 代理分类

  • 正向代理:通常是架设在靠近Server处,通过将Client请求流量全部引入到Proxy,由Proxy转发到Server端,Client请求包包含了地址八元组(源IP+源Port+目标IP+目标Port+协议类型+代理IP+代理Port+代理协议类型)。
  • 反向代理:通常是架设在靠近Client处,通过将Client并不需要访问Server,不需要地址八元组,只需要地址五元组(Client的IP+Client的Port+反向代理的IP+反向代理的Port),直接将本地反向代理作为Server看待,由反向代理,通过预先设置的转发规则,进行转发,实际上就是实现了路由表的作用

3. 代理源码分析

3.1. 资料

httptunnel源码:https://github.com/larsbrinkhoff/httptunnel
httptunnel应用案例:https://sergvergara.files.wordpress.com/2011/04/http_tunnel.pdf
tinyproxy源码:https://github.com/tinyproxy/tinyproxy

3.2. httptunnel原理

这里http等隧道原理,基本上还是使用tcp等socket转发包,基本框架如下:

png

客户端核心流程:

相当于建立一个本地正向代理服务器,所有流量都导入到本地代理端口,例如:10001

  • 建立一个socket A,监听端口:10001,负责接受本地任意socket L流量请求
  • 创建隧道,主要建立了双向通道socket TC_out和socket TC_in,分别负责post请求和get请求
  • 读取socket L到流量,通过socket TC_out发送出去到远端隧道服务
  • 从socket TC_in中读取远端隧道到数据,写到socket L

服务器核心流程:

相当于一个反向代理服务器,接受隧道所有流量,并转发到对应到服务上去

  • 创建隧道,主要是建立了双向通道socket TS_out和socket TS_in,分别负责远端到get请求和post请求
  • 等待隧道中到连接
  • 建立socket S,对待支持的服务,发起connect连接
  • 隧道数据到来,读取socket TS_in的数据,并写入socket S,由socket S将数据转发到真实服务
  • 读取socket S中的数据,将数据全部写入socket TS_out

3.3. httptunnel总结

从前面的原理可以看见,实际上http隧道,实现的是代理的功能,负责从代理隧道中的数据解读真实数据,然后由提前connect到的服务端的socket,负责推送数据(这里获取可以考虑读取隧道中的数据,然后在第一个包的时候,自动根据隧道数据包中的真实目标地址,建立socket,后续所有的真实目标地址的内容,都通过此socket传递出去)。这里面,如果考虑安全性,可以通过在隧道建立连接时,对当前会话进行校验(可以是在http请求头中加入校验的token),当客户端第一次与服务端建立隧道时,校验是否合法,如果合法,则放行,建立socket,后续的数据流量,均直接通过socket的send data发送。如果要做到更严格,就需要对每一个数据包进行校验,本质上,就是要在隧道服务中,读取每一个socket数据后,校验头部,然后再决定是否转发到真实服务,这里可能会非常耗时,所以一般应该只需要校验连接即可。

另外,所谓到http代理,实际上,就是将http请求,外层再套用一层http请求,由两个目的地址,一个是代理的目的地址,一个是真实的目的地址,真实的目的地址被封装在内层。

为何区分http代理和socks代理呢?
由于要支持上述代理通信,实际上,就是需要客户端本身要能支持数据包两层封装。而对应的,服务端,也必须要支持数据包两层解封。而解封的第一层,就得严格按照第一层使用的协议类型,来进行解封,比如http协议,就按照http协议进行数据包解封;tcp包,就按照tcp包的格式进行解封,而第二层,也是需要按照第二层的数据包结构,将目的地址解包出来。所以这里使用的两种代理类型,就必须是根据具体数据包格式来进行的。(其实这里插一句,如果tcp协议中,支持对上层的协议进行标注,也就是每一个tcp包中都存在当前封装的上层数据包中,使用的是何种协议,是不是也可以实现任意类型自动匹配代理?可惜tcp中并无标准标注,就不太方便自行定义来适配任意数据端发包方式)

3.4. tinyproxy原理

阅读了tinyproxy源码,前面的httptunnel中想说明的基于隧道数据包解析获取到待连接的目标地址,已实现。基本原理还是一样,建立socket,listen等待客户端连接,将所有连接,新建socket去主动连接目标服务,并自动读取客户端连接进来的socket的数据包,转发到主动连接目标服务的转发socket上。

4. SSH隧道代理的应用

我们工作中,常常遇到这种情况:我们在异地办公,无法访问内网全部端口,但是由于内网运维维护的需要,内网机器开放了SSH服务(22号端口),这样,虽然我们访问内网端口受限,但是利用SSH隧道机制,可以解决访问问题。

png

4.1. SSH隧道转发原理

SSH隧道技术,实际上是利用SSH Server作为跳板机,将请求流量通过SSH封包,传达到SSH Server,进而SSH Server作为中转代理,将包解析出来,转发到目标地址。如果我们能够通过外网经过SSH协议访问到任意一台企业内网的SSH Server,那么我们就可以利用SSH Tunnel机制来实现网络流量穿透,解除端口限制问题。

SSH代理形式,可以有两种:

  • 路由模式:配置转发表,根据端口号转发(本质上是一种反向代理服务)
  • 本地Socks代理模式:本地启动一个Socks5代理服务,根据IP转发所有端口数据(本质上是一种正向代理服务)

两种模式优缺点:

  • 路由模式在本地启动反向代理,可以做本地流量劫持,转到本地反向代理服务上,就可以不修改代码来进行流量的穿透,但是本地流量劫持存在成本,一般也可以选择修改代码中访问目标,配置成本地反向代理,这样流量就安全的通达到目的地,但是需要修改代码配置。一般是端口到端口的转发,当然也可以实现任意端口的转发,需要我们代理服务上支持
  • 本地Socks代理模式,需要在客户端代码层面支持代理配置,如果代码实现上没有增加代理的支持,那这种模式是无效的,但是一旦代码层面支持,那我们不需要改动任何程序自身的固定配置,只需要提供程序自身原本就支持的代理设置配置即可,简单易用。当然本地Socks代理,也可以作为反向代理使用,但是需要一定代码逻辑支持封包和拆包。

4.2. SSH隧道代理 - 路由表模式

针对上述访问内网诉求,SSH Tunnel常规做法,是在客户端本地启动端口转发服务,作为一个反向代理,与SSH Server连接,将请求转发到内网目标机器上。也就是这里,我们需要设置的内容包括:本地反向代理服务的IP/端口、SSH Server的IP/端口、访问目标的IP/端口,如下:

客户请求 —→ 本地反向代理服务的IP/端口(IP默认都是localhost或者127.0.0.1) —→ SSH Server的IP/端口(这里的端口号通常是22) —→ 访问目标的IP/端口

4.2.1. 使用免费的MobaXterm(Windows下专用)

Windows下推荐使用MobaXterm,因为穷,它免费。具体使用如下:

  • Step1:准备环境,理清需要代理转发的端口
假设我们内网服务的端口包括:27800、8080、8443,因此我们需要分别对这些进行转发。
假设我们的服务部署在主机上,IP(9.134.126.182),我们刚好可以SSH访问它,那么它既作为目标机器,也可以作为SSH Server正向代理服务主机。

转发规则1:客户请求 ---→ 本地反向代理服务的IP/端口(127.0.0.1:8443,注意这里的端口可以随意,不一定需要跟目标端口一致) ---→ SSH Server的IP/端口(9.134.126.182:22) ---→ 访问目标的IP/端口(9.134.126.182:8443)

转发规则2:客户请求 ---→ 本地反向代理服务的IP/端口(127.0.0.1:27800,注意这里的端口可以随意,不一定需要跟目标端口一致) ---→ SSH Server的IP/端口(9.134.126.182:22) ---→ 访问目标的IP/端口(9.134.126.182:27800)

转发规则3:客户请求 ---→ 本地反向代理服务的IP/端口(127.0.0.1:8080,注意这里的端口可以随意,不一定需要跟目标端口一致) ---→ SSH Server的IP/端口(9.134.126.182:22) ---→ 访问目标的IP/端口(9.134.126.182:8080)
  • Step2:点击MobaXterm菜单栏Tools—–MobaSSHTunnel(Port Forwarding),启动SSH Tunnel本地反向代理服务

png

  • Step3:设置转发规则

png

  • Step4:设置完所有转发规则后,点击启动按钮(MobaXterm免费版最多设置3条规则,不过正好我们这里够用)

png

4.2.2. 使用收费的XShell(Windows/Mac/Linux通用)

  • Step1:准备环境,理清需要代理转发的端口
假设我们内网服务的端口包括:27800、8080、8443,因此我们需要分别对这些进行转发。
假设我们的服务部署在主机上,IP(9.134.126.182),我们刚好可以SSH访问它,那么它既作为目标机器,也可以作为SSH Server正向代理服务主机。

转发规则1:客户请求 ---→ 本地反向代理服务的IP/端口(127.0.0.1:8443,注意这里的端口可以随意,不一定需要跟目标端口一致) ---→ SSH Server的IP/端口(9.134.126.182:22) ---→ 访问目标的IP/端口(9.134.126.182:8443)

转发规则2:客户请求 ---→ 本地反向代理服务的IP/端口(127.0.0.1:27800,注意这里的端口可以随意,不一定需要跟目标端口一致) ---→ SSH Server的IP/端口(9.134.126.182:22) ---→ 访问目标的IP/端口(9.134.126.182:27800)

转发规则3:客户请求 ---→ 本地反向代理服务的IP/端口(127.0.0.1:8080,注意这里的端口可以随意,不一定需要跟目标端口一致) ---→ SSH Server的IP/端口(9.134.126.182:22) ---→ 访问目标的IP/端口(9.134.126.182:8080)
  • Step2:启动SSH Session连接

png
png

  • Step3:设置转发规则

png

  • Step4:启动连接

png

4.3. SSH隧道代理 - Socks5代理模式

一般正向代理有几种:Http代理、Https代理、Socks4代理、Socks5代理、Ftp代理等。最常见的是Http代理,支持Http请求,最常使用在浏览器上;另一种Socks4代理支持UDP请求,而Socks5同时支持UDP和TCP请求的代理转发。代理的本质是起到路由的作用,Http代理是在Http协议本身的Tunnel机制基础上支持,而Socks代理是在传输层上的端口监听及数据流量转发,本质上是支持Http请求的。

微软的IE默认只支持Http代理,Chrome默认使用IE的代理设置,不过我们也可以使用Chrome的代理插件,比如:SwitchyOmega,去配置使用Socks代理。

SSH只支持Socks5代理,不支持其他类型代理,不过好在我们也可以利用第三方软件,将Socks5代理转换成Http代理(比如Fiddler等)

针对上述访问内网诉求,SSH Tunnel另一种常规做法,是在客户端本地启动Socks代理服务,作为一个正向代理,转发数据到SSH Server,通过将SSH Server作为跳板,解析出原始数据包的目标地址,进而进行转发,只要目标机器是SSH Server可达,就可以使用这种方式。也就是这里,我们需要设置的内容包括:本地Socks代理服务的IP/端口、SSH Server的IP/端口,如下:

客户请求 —→ 本地Socks代理服务的IP/端口(IP默认都是localhost或者127.0.0.1) —→ SSH Server的IP/端口(这里的端口号通常是22)

这种模式的好处,是不需要设置源端口和目标端口,不是根据端口一对一转发,而是任意端口直接转发,端口号不变,只是通过SSH隧道穿透网络防火墙。

4.3.1. 使用免费的MobaXterm(Windows下专用)

Windows下推荐使用MobaXterm,因为穷,它免费。具体使用如下:

  • Step1:准备环境
假设我们的服务部署在主机上,IP(9.134.126.182),我们刚好可以SSH访问它,我们可以将它作为SSH Server正向代理服务主机。

配置规则:客户请求 ---→ 本地Socks代理服务的IP/端口(127.0.0.1:11000,注意这里的端口可以随意) ---→ SSH Server的IP/端口(9.134.126.182:22)
  • Step2:点击MobaXterm菜单栏Tools—–MobaSSHTunnel(Port Forwarding),启动SSH Tunnel本地反向代理服务

png

  • Step3:设置转发规则

png

  • Step4:设置完所有转发规则后,点击启动按钮

png

  • Step5:本地查看Socks5代理服务端口是否正常启动

png

  • Step6:配置Chrome浏览器代理插件SwitchyOmega,设置Socks5代理

png

4.3.2. 使用收费的XShell(Windows/Mac/Linux通用)

  • Step1:准备环境
假设我们的服务部署在主机上,IP(9.134.126.182),我们刚好可以SSH访问它,我们可以将它作为SSH Server正向代理服务主机。

配置规则:客户请求 ---→ 本地Socks代理服务的IP/端口(127.0.0.1:11000,注意这里的端口可以随意) ---→ SSH Server的IP/端口(9.134.126.182:22)
  • Step2:启动SSH Session连接

png
png

  • Step3:设置转发规则

png

  • Step4:启动连接
  • Step5:本地查看Socks5代理服务端口是否正常启动

png

  • Step6:配置Chrome浏览器代理插件SwitchyOmega,设置Socks5代理

png

附录

Socks5代理转Http代理工具

Fiddler工具、Privoxy工具

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少