本文共 3550 字,大约阅读时间需要 11 分钟。
平时经常写代码的程序员免不了要跨越国界来查找技术资料,但是 Google 上不了,Youtube 也看不了,Github 和 StackOverflow 访问起来又龟慢,好不容易被同行推荐了一个国外大神的技术博客,居然也打不开。这是很让人捉急的,遇到这事久了难免会有情绪。
今天,小编给平时有这样遭遇的朋友深度讲解几种代理技术原理,掌握了这项技能之后,读者们就可以畅游互联网了。突破了国界线,你的拷贝粘贴代码的能力将大大提升。但是记住不得用这种技能来挣黑钱哦,因为准确来说靠跨界代理技术谋利并不是合法的,自己偷偷用就可以了,外人你别告诉他。
图片代理技术原理非常简单,你需要在国外搭建一个代理服务器,当你的个人电脑需要访问某个网站时,将这个请求转发到代理服务器,由代理服务器来帮你访问,访问成功后再将结果再传回给你的个人电脑。代理服务器设在国外,你的个人电脑和代理服务器之间的传输速度并不高,但是代理服务器和目标网站之间通常都是可以快速访问的。所以要将代理服务器尽量放在靠近你的地理位置,我一般会选择新加坡、日本或香港。
云服务的时代,在国外搭建一个代理服务器并不是很麻烦。你需要去国外的虚拟主机供应商购买一个便宜的虚拟主机,然后在虚拟主机上安装开源的代理服务器软件。虚拟主机供应商有很多选择,你可以试试我目前正在使用的 https://www.digitalocean.com。购买一个虚拟主机需要使用信用卡,支付宝微信在这里无能为力了。通常是按分钟计费的,花费大概是一天一块钱人民币。
图片如果不知道虚拟主机是什么,你就将它理解为一个远程服务器,它有独立的 ip 地址,可以是 Ubuntu 、Centos 等系统,通过 ssh 链接服务器后使用终端来操作它。
代理软件有很多选择,不同的代理软件使用了不同的代理协议,下面我们从最简单的 HTTP 代理服务器开始讲起。
这种代理是最简单的代理,可以在虚拟主机上使用 Nginx 直接搭建。
server { resolver 8.8.8.8; listen 80; location / { proxy_pass http://$http_host; proxy_set_header Host $http_host; } }它的原理是「请求改写」,将 HTTP 请求的目标地址换成代理服务器的地址,代理服务器再将请求进行改写传递到目标服务器。那代理服务器如何知道目标服务器地址呢,通过请求头里面的 HOST 参数,浏览器会自动加上这个请求头,携带的是目标服务器的地址。上面的 nginx 配置文件中的 $http_host 变量就是目标服务器地址,它是从请求头的 HOST 参数中取出来的。 图片
HTTP 代理的缺点是不支持 https 协议,「请求改写」需要知道请求的内容,https 的内容是加密的无法直接改写。在 https 大行其道的今天,这种代理作用很有限。不过还是有一些国外的技术大神博客依旧使用古老的 http 协议,比如 Redis 大神 antirez 的个人博客 http://antirez.com。下面我就用 antirez 的博客来测试一下自己用 nginx 搭建的 HTTP 代理服务器可用性如何。
图片网页内容正常显示了,不过还是有一些静态文件无法加载进来,这些静态文件都是 https
的地址,HTTP 代理服务器表示无能为力。如果再尝试使用它代理访问 Google、Github 和 StackOverflow,毫无疑问,统统打不开。
HTTP 1.1 协议新增了一种请求类型 CONNECT。有了这种请求类型,HTTPS 网站也可以通过 Nginx 来“畅游”了。它的原理就是将 CONNECT 请求作为握手请求和代理服务器提前交流目标服务器的地址信息,如果代理服务器可以联通目标服务器就向客户端返回 200 OK。接下来代理服务器就开始透传客户端的请求数据直达目标服务器。它不需要知道 HTTPS 请求数据包的具体内容,直接对数据包进行透传。缺点就是多了一个 HTTP 握手请求,多了一个网络数据包来回的开销。这这类型的的代理称之为「隧道代理」。
Nginx 原生并不支持隧道代理,需要使用第三方扩展对 Nginx 源码打补丁后才能使用。开源市场上缺少简单易用的隧道代理的工具包,它的支持性比较差。从实现角度这个代理服务器不能直接使用普通的 HTTP 框架来实现,因为握手之后就是透传,透传并不需要解析 HTTP 协议。但是又不好直接使用 TCP Socket 来实现,因为握手阶段需要解析 HTTP 协议,需要 HTTP 协议的独立解析器。我尝试使用 Go 语言编写了一个简单的隧道代理服务器,让人意外的是使用这种协议在访问某些特殊网站的时候会被莫名其妙的断开链接,此时代理服务器还没来得及将 CONNECT请求 的响应回复给客户端。我能想到的原因就是 CONNECT 请求是明文的,它被某种无形的力量斩断了。
鉴于上面的 HTTP 代理无法代理 https 网址,而隧道代理的支持性并不是很好,我们要换一个更高级的代理协议 —— Socks代理。它是基于 TCP Socket 的代理,在请求的开始浏览器和代理服务器交流一下握手信息,握手信息里包括用户名密码认证、目标服务器地址等,待交流成功后直接透传浏览器发过来的请求包到目标服务器,它可以同时代理 HTTP 和 HTTPS 请求。它不同于隧道代理在于握手协议是简单的自定义二进制协议,易于实现。Socks 代理协议存在 V4 和 V5 两个版本,V5 是目前比较流行的版本。
那有没有开源的 socks 代理服务器软件呢?有的,它是 ss5,不过这个软件比较古老,配置复杂,所以我就不打算使用它来演示了。我要使用开源的 Go Socks 库来编写一个极简的 Socks 代理服务器。需要在目标服务器上安装 Go 语言环境,然后将 Go Socks 库下载下来。
$ go get github.com/armon/go-socks5然后编写一个简单的 main 函数就可以将代理服务器跑起来了
package main import "github.com/armon/go-socks5" func main() { server, _ := socks5.New(&socks5.Config{}) server.ListenAndServe("tcp", "0.0.0.0:1080") }在终端里执行一下 go run main.go,再打开浏览器试一下新代理 图片
Youtube 都正常打开了,SocksV5 是不是很威武!SocksV5 代理要比普通的 HTTP 代理网络延迟高一些,因为多了握手阶段,而且握手阶段有 2 个数据包的来回时间。对于距离遥远的代理服务器来说,2 个数据包的延迟时间也不容小嘘。就我个人的电脑客户端到代理服务器的延迟会达到 250 ms 左右,单个请求不是很明显,很多个请求累计在一起就会有明显的代理延迟了。那能不能将两个数据包来回缩减为一个来回呢?可以,那就是 SocksV4 代理协议,它的握手阶段没有安全认证部分,所以可以使用一个数据包来回搞定。代价也很明显如果你的代理服务器地址暴露了,任谁都可以随意使用。
SocksV5 的握手协议也是明文的,但是为什么它就可以正常使用?这是一个谜,说不准未来这种代理技术也会变的不可用。
ShadowSocks 是一款代理软件,使用的极为广泛。它采用端到端的加密算法来传输请求响应,避免了中间传输的内容以任何形式被窃听。但是代价也是有的,那就是加密后的数据包总是要比原数据包大不少,影响传输效率。
使用它需要在服务器安装 ShadowSocks 服务器软件,同时你的个人电脑要安装 ShadowSocks 客户端,设置好一样的加密算法,就可以正常交流了。小编平时使用的代理工具就是 ShadowSocks。
ShadowSocks 客户端在本地(你的个人电脑)同时开启了 SocksV5 服务和 HTTP 代理服务,我们在浏览器里面将代理地址指向本地的服务地址,就可以直接使用上面的 HTTP/HTTPS 代理协议和 SocksV5 代理协议来访问跨境网站。ShadowSocks 开启了数据安装通道,是常规代理协议的保护伞。
原文发布时间为: 2018-11-19
本文作者:码洞 本文来自云栖社区合作伙伴“”,了解相关信息可以关注“”。转载地址:http://ovhqx.baihongyu.com/