客户端-服务器-代理模型

引言

(声明:纯技术博客!)

曾几何时,在国内还是可以访问google、faceboook、youtobe之类的网站的,后来由于防火墙的原因,导致我们不再能够访问这些网站了,不免为人生一大憾事!后来出于各种各样的需求,例如查找学习资料等,就有人想要翻墙了,于是就有了翻墙代理。

原理

代理实现的关键在于如何绕过防火墙,得先知道防火墙是如何阻止我们访问外网的?大致有以下三种手段:

  1. 域名劫持--->当你的主机发出DNS请求地址解析服务,就给你返回一个错误的ip或者压根不返回
  2. IP黑名单--->国家入口网关封锁该IP,数据无法通过
  3. 主干路由器关键字过滤阻断--->含有敏感关键字一率不允许通过

先看原理图再解释:

过程:

客户端负责充当一个跳板,将浏览器的请求数据加密(目的是让让数据不能被直接识别)后转发给server。由于数据经过了加密,所以也就不会被主干路由器的关键字屏蔽技术阻挡。我们直接让client与server沟通,所以用不到DNS服务,也就不会存在被假的IP欺骗或是找不到IP地址的情况。又因为我们会给server选择一个不知名的IP地址,即不会是防火墙IP黑名单中的地址,所以不会被封锁。(跨出国门第一步)

server接收到来自client的数据,先解密,然后代理浏览器发出请给对应网站服务器。网站服务器将server请求的数据再传给它,server再将数据进行加密,发送给我们的client。

最后,client将解密后的数据交给浏览器,这便是大致的原理了。

SOCKS5协议:

SOCKS5 是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Internet网中的服务器,或者使通讯更加安全。SOCKS5 服务器通过将前端发来的请求转发给真正的目标服务器, 模拟了一个前端的行为。在这里,前端和SOCKS5之间也是通过TCP/IP协议进行通讯,前端将原本要发送给真正服务器的请求发送给SOCKS5服务器,然后SOCKS5服务器将请求转发给真正的服务器。

我们这里也要借助这个协议,让我们的数据通过防火墙。下面列出相关的知识。

RFC1928(URL为:http://www.ietf.org/rfc/rfc1928.txt)描述了Socks协议的细节,告诉我们客户程序如何同Socks代理协商,取得透过该协议对外传输的途径。看了看RFC1928文档,大概整理出了socks5服务器处理TCP请求的流程

socks5连接建立的时候首先由客户端发出如下格式数据给服务端:

                             

在SOCKS5中VER字节总是0x05代表socks5,NMETHODS存放客户端可以接受的认证方法数量n,后面的n个字节就是各个方法对应的编号了。

收到客户端发出的请求后,服务端做出回应:

                                       

其中验证方法对应的编号如下:
          o  X'00' NO AUTHENTICATION REQUIRED
          o  X'01' GSSAPI
          o  X'02' USERNAME/PASSWORD
          o  X'03' to X'7F' IANA ASSIGNED
          o  X'80' to X'FE' RESERVED FOR PRIVATE METHODS
          o  X'FF' NO ACCEPTABLE METHODS

客户端接受到如此回应后就可以开始与服务端进行验证了。在此0x02号代表的用户名密码验证方式在RFC1929文档中有介绍。我先不管验证,先实现匿名socks5代理。以后再考虑添加验证功能。

验证完毕后,客户端就可以开始提出要求了。到底要socks5代理为它做什么。请求数据包的格式如下:

            

各字节代表的意义:
          o  VER    protocol version: X'05'
          o  CMD
             o  CONNECT X'01'
             o  BIND X'02'
             o  UDP ASSOCIATE X'03'
          o  RSV    RESERVED
          o  ATYP   address type of following address
             o  IP V4 address: X'01'
             o  DOMAINNAME: X'03'
             o  IP V6 address: X'04'
          o  DST.ADDR       desired destination address
          o  DST.PORT desired destination port in network octet order

这里的目标地址可以有三种格式(IPV4 IP,域名,IPV6 IP)。其中IPV4,IPV6地址固定长度分别为4字节,16字节。域名以pascal字符串保存:第一字节为字符串长度,后面跟字符串内容。

收到客户端的请求后,服务端开始回应:

            

 Where:

          o  VER    protocol version: X'05'
          o  REP    Reply field:
             o  X'00' succeeded
             o  X'01' general SOCKS server failure
             o  X'02' connection not allowed by ruleset
             o  X'03' Network unreachable
             o  X'04' Host unreachable
             o  X'05' Connection refused
             o  X'06' TTL expired
             o  X'07' Command not supported
             o  X'08' Address type not supported
             o  X'09' to X'FF' unassigned
          o  RSV    RESERVED
          o  ATYP   address type of following address
             o  IP V4 address: X'01'
             o  DOMAINNAME: X'03'
             o  IP V6 address: X'04'
          o  BND.ADDR       server bound address
          o  BND.PORT       server bound port in network octet order

   Fields marked RESERVED (RSV) must be set to X'00'.

对应客户端的3种不同要求:
针对CONNECT请求的回复:
BND.PORT里面保存的是服务端连接到远程服务器所分配的端口,BND.ADDR保存的是分配的IP地址。(这里socks5为什么这么做我还有点不清楚,不过不管它,先实现再说,以后在看看socks5 proxy client那边是怎么利用的)
针对BIND请求的回复:
    服务端将两次回复客户端。第一次回复是在服务端开启新的socket并开启一个端口侦听后。BND.PORT存放服务端侦听的端口。BND.ADDR存放IP地址。客户端一般会利用这段信息来告诉远端服务器。第二次回复是用来表明远端服务器连接成功。BND.PORT和BND.ADDR分别存放远端服务器连接用的端口及IP。

源码

源码挺长的,就不贴出来了,托管在GitHub上,附上链接:https://github.com/Fireplusplus/Project/tree/master/esocks

启动步骤

(费尽心思从别人那里借来的服务器的账号,当然你也可以自己买一个:网址:https://www.linode.com/ 就是有点小贵,一个月大概60~70RMB)

首先,得把server部署到服务器上:

               scp server  user_name@IP:/dir --->          将服务器应用程序拷到远端服务器上

               ssh user_name@IP                 --->          登录到服务器

               ./ser 6666                               --->          将服务器跑起来(6666就是client与server通信的端口,不冲突即可)

启动客户端:

              ./cli 6667 IP 6666                     --->          第一个端口号为client与浏览器通信端口,后边接服务器IP和端口号

最后,设置浏览器信息(以FireFox浏览器为例):

选项--->高级--->网络--->设置:

              

运行结果

现在就可以访问外网啦!

熟悉的界面又回来了

大哭

         

上youtobe看个小视频

大笑

          

         

画质清晰,视频流畅,nice!

上个Twitter:

        

国外的微博,不错呦!

再来个Facebook:

        

嫌麻烦,就不注册了。

遇到的问题

  1. server与cilent无法建立连接,提示验证方法错误。仔细分析后发现是加密解密对应关系没搞好,导致server未能识别client请求。重新修改了加密和解密的位置。
  2. 浏览器设置问题,client与server运行起来,但依旧无法访问外网。解决办法就是一个字:试。幸好选项不多,多次试验下来,搞定。设置方法在前面已经贴出。
1. 关注技术大牛或技术社区账号 在推特、youtobe等国外平台上,有许多知名的技术大牛或技术社区账号,他们会不定期地分享自己的编程技术、代码、技术栈学习心得和经验,通过关注他们,可以及时获取到最新的技术动态和学习资源。 2. 加入技术社区和论坛 参加技术社区和论坛可以与其他开发者互动,分享经验和技巧,提出问题并得到解答。同时,这些社区和论坛也会定期发布技术文章、教程和视频,帮助开发者学习和掌握新的编程技术和技巧。 3. 订阅技术博客和YouTube频道 订阅一些技术博客和YouTube频道可以获取到最新的编程技术和技巧,学习一些新的东西。在这些博客和频道中,你可以找到许多优秀的作者和视频,他们会为你提供很多技术资源和学习资料。 4. 参加在线课程和学习活动 参加在线课程和学习活动可以帮助你更深入地学习和掌握编程技术和技巧。在这些课程和活动中,你可以与其他开发者互动,分享经验和技巧,并且得到一些专业的指导和建议,帮助你更快地成长。同时,这些课程和活动也会提供一些实际操作和项目,帮助你将所学的知识应用到实际中。 总之,利用推特、youtobe等国外平台进行编程技术、代码、技术栈的学习需要多方面的参与和学习,要掌握好自己的学习方法和步骤,才能更好地进行学习和提高自己的技术水平。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fireplusplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值