高效的代理工具hiproxy-下

1前言

hiproxy的核心功能是请求代理,在代理请求的同时,处理了一些开发中的细节问题,比如https证书自动生成、自动配置浏览器代理等。在《高效的代理工具hiproxy - 上》中,对hiproxy做了一个基本的介绍,接下来介绍一下hiproxy的基本原理以及用到的核心技术。

这篇文章将主要从HTTP/HTTPS请求代理、HTTP证书生成、hiproxy插件以及浏览器代理几个方面介绍

2HTTP请求代理原理

对于HTTP请求,配置了代理之后,浏览器会发送GET/POST等请求给hiproxy。由于HTTP是明文传输的,hiproxy能够获取到请求的基本信息(比如请求路径、参数、Headers和Cookie等)。当hiproxy接收到请求之后,根据用户的hosts和rewrite规则配置,对请求的信息做一定的修改,然后去相应的目标服务器请求资源并返回给客户端。

也就是说,hiproxy充当了一个中间人(The Man-In-The-Middle),在浏览器和服务器之间转发数据。

3HTTPS请求代理原理

对于HTTPS请求,配置代理之后,跟HTTP请求不一样的是,浏览器会发送CONNECT请求到hiproxy,hiproxy会新建一个到最终目标服务器的TCP连接(也就是新建了一个隧道),当连接建立完成之后,会通知浏览器连接已经建立。然后hiproxy会在客户端和服务端之间转发数据。这其实也就是隧道代理。

但是这只是能简单代理请求,传输的数据是加密的,hiproxy无法解密。hiproxy也没办法获取到请求的信息(比如参数和Cookie),更没有办法修改响应的数据。如果不需要对请求、响应的信息做对应的修改,这就能满足我们的需求。

如果我们需要实现跟HTTP请求一样的功能:根据请求的信息,对请求和响应做一些修改,需要怎么做呢?

好在我们可以充分利用中间人攻击这种模式。

因为最终的目标服务器能获取到请求的信息,我们可以在hiproxy和最终服务器之间再启动一个中间人服务(这里简称为M),当hiproxy接收到CONNECT请求之后,新建一个到M的连接,当M收到请求之后,跟HTTP请求代理一样,对请求信息做一些修改,然后去目标服务器请求资源并返回给客户端。

4证书生成原理

在SSL/TLS握手阶段,客户端发送给服务端的第一条消息(ClientHello)中,会通过SNI(Server Name Indication)扩展,将要请求的域名发送过去。

当服务端接收到域名之后,就能使用自己的CA根证书,生成对应的域名证书返回给浏览器。

在hiproxy中,用户可以给域名配置对应的证书,如果用户配置了证书,hiproxy会使用用户配置的证书,如果没有,才会自动去生成新证书。

5hiproxy插件实现原理

hiproxy提供了一套插件扩展机制,这个机制很简单:插件开发完成后,将插件安装到全局,hiproxy启动时会自动查找安装的所有插件。

hiproxy找到按照的插件之后,会分别去解析对CLI命令、指令和页面的扩展。

开发者开发新插件时,可以参考hiproxy-plugin-example。这是一个完整的插件示例,你可以基于这个示例开发新的插件。

这里需要说明的是:hiproxy的插件就是一个普通的npm模块,不需要将hiproxy作为依赖安装到插件中。

举个例子,我们要为hiproxy添加一个CLI命令,可以按照如下方式去配置:

然后就可以在控制台执行:

hiporxy hello --name zdying --age 18

对于Rewrite命令,也是类似的配置:

然后,在配置文件中使用:

add $result 8800 88;

除此之外,我们也可以给hiproxy添加一些页面,比如我们开发了一个插件hiproxy-plugin-dashboard,可以在线管理hiproxy的配置文件。

页面扩展的配置,也比较简单:

详情可以查看插件开发指南。zh

6浏览器窗口/代理配置原理

首先,找到系统中浏览器对应的路径。比如在OSX上,查找<browser-name>.app,然后启动这个app,并传入参数来配置代理服务器地址。

<path-to-chrome-app>.app [options] [url]

在windows上,会去注册表中查找对应浏览器的exe文件路径。然后运行并传递参数。

<path-to-chrome-app>.exe [options] [url]

对于Chrome/Opera浏览器来说,我们需要传递两个方面的参数:

代理服务的地址:--proxy-pac-url(PAC代理文件路径)和--proxy-server(普通代理地址)二选一,这两种代理hiproxy都支持。

用户数据存放的目录:--user-data-dir当传递这个参数,并且这个目录不是浏览器默认存放用户数据的目录,则会新建一个新的浏览器实例,这个示例独立于其他的浏览器窗口,互不影响(这个实例配置了代理,其他浏览器实例的请求不会通过这里配置的代理)。

7最后

这篇文章,介绍了hiproxy核心的原理以及用到的技术,相信大家对hiproxy的实现已经有了一定的了解。如果对hiproxy感兴趣,欢迎为她贡献代码。

hiproxy地址:;hiproxy文档: