一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
反向代理 Reverse Proxy
一提起proxy这个词,对于熟悉nginx的人来说,那肯定是指反向代理。
反向代理,简单的说:
代理服务器收到http请求之后,根据http请求中的一些信息和提前准备好的配置,去将这个请求转发给真正的源。
然后将真正的源的回复,转发给客户端。
反向代理有几个关键点需要注意:
-
- 需要提前配置, 比如,
nginx里需要配置upstream。
- 需要提前配置, 比如,
-
- 代理程序可以根据很多参数来判断,我到底进入哪个
upstream, 比如 Host、Path、要是愿意,甚至可以通过cookie,等,这个完全看代理程序怎么写。
- 代理程序可以根据很多参数来判断,我到底进入哪个
反向代理就简单介绍到这里。
正向代理的概念
正向代理其实在开发过程中用的更多,比如说:
- 抓包分析
- 加快第三方库的获取
- 等等
他的作用是什么呢,比如说你要访问 http://www.xxx.com, 由于你的网络有问题,你访问不了,你需要让一个能访问这个网址的人帮你访问,然后把Response回复给你,此时,这个能帮你访问的中间人,称之为正向代理。
所以这个中间人,能抓包分析。
如果这个中间人比你的网络好,那么自然能加快整个过程。
正向代理 http 协议
一般来说,客户端和代理服务器之间,需要有一些提前的交流,比如说告知,我想访问的真正的源是什么。
那么 正向http代理,有这个过程吗?
我们不妨来试试.
环境准备
- mac 或者 linux 命令行环境
- windows 下,可以安装 msys2 或者 gitbash 来模拟
linux命令行 - 需要安装两个命令:
curl和nc
无代理访问 http://www.baidu.com
输入如下指令:
$ curl -v http://www.baidu.com
我们可以看见整个过程, 这里我们把请求的部分拉出来:
* Trying 14.215.177.38...
* TCP_NODELAY set
* Connected to www.baidu.com (14.215.177.38) port 80 (#0)
> GET / HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/7.64.1
> Accept: */*
>
我们可以看见,不使用代理的情况下,他直接访问了www.baidu.com的IP地址:14.215.177.38。
有代理访问 http://www.baidu.com
那么如何让curl通过一个中间代理去访问指定的网址呢?
简单如斯:
$ http_proxy="http://127.0.0.1:8888" curl -v http://www.baidu.com
按回车,不出所料的话:
* About to connect() to proxy 127.0.0.1 port 8888 (#0)
* Trying 127.0.0.1...
* 拒绝连接
* Failed connect to 127.0.0.1:8888; 拒绝连接
* Closing connection 0
curl: (7) Failed connect to 127.0.0.1:8888; 拒绝连接
从这段文字,可以看出,curl 试图访问 127.0.0.1:8888, 这正是我们想要的。
但是,我们并没有一个可用的代理程序监听 127.0.0.1:8888。
此时,nc 命令派上用场:
新开一个窗口:
$ nc -l 8888 # 注意这个命令会卡在这里
这个命令的作用就是监听 127.0.0.1:8888 ,然后卡在这里,等到有人往里面发数据,就会打印。
然后在老窗口里:
$ http_proxy="http://127.0.0.1:8888" curl -v http://www.baidu.com
按下回车,我们可以看见,两个窗口都有动静。
我们先来看curl
* About to connect() to proxy 127.0.0.1 port 8888 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
> GET http://www.baidu.com/ HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.baidu.com
> Accept: */*
> Proxy-Connection: Keep-Alive
这个输出说明,他访问了127.0.0.1:8888, 然后将HTTP的一些 header(头) 发送了过去。
然后再来看看nc:
GET http://www.baidu.com/ HTTP/1.1
User-Agent: curl/7.29.0
Host: www.baidu.com
Accept: */*
Proxy-Connection: Keep-Alive
我们发现nc收到的报文就是一个普通的http报文,并没有其他的东西,也就是说:
在正向代理http协议的时候,并不需要多余的协商过程。
那问题就来了,一个真正的代理程序,是如何得知,要把这个请求转发给谁呢?
答案就在上面:
Host: www.baidu.com
这个 http 头就告知了代理程序,真正想访问的是 www.baidu.com。
然后,代理程序通过解析这个 Host 头,就能把请求转发出去了。
正向代理 https 协议
通过刚才访问 http://www.baidu.com的过程,我们得知:
正向代理的时候,真正的源信息,是通过解析http报文来得知的。
但是问题来了,如果是 https 协议呢?
https协议的报文是加密的,那么中间人获取的就是一堆密文,也就无法解析 http Host 头部。
我们还是来观察一下:
第一个窗口,打开nc
$ nc -l 8888
第二个窗口,让 curl 用代理访问 https://www.baidu.com
https_proxy="http://127.0.0.1:8888" curl -v https://www.baidu.com
注意,此时写在前面的环境变量是https_proxy。
回车之后,观察 nc:
CONNECT www.baidu.com:443 HTTP/1.1
Host: www.baidu.com:443
User-Agent: curl/7.29.0
Proxy-Connection: Keep-Alive
看见了没,这一段信息,是由curl发来的,但这不属于正常的https流程。
这一段信息,说明:
curl在用代理请求https的时候,会先把必须的信息发给这个代理程序,比如说第一行:
CONNECT www.baidu.com:443
此时,代理程序,就知道了真正的源是:www.baidu.com:443, 从而进行后续的转发。