Ahri is an intranet sharing tool. Like VPN
Ahri 是一个高效且易用的网络环境共享工具。
你可以将它理解为一个 VPN,但 ta 又不是一个传统意义上的 VPN。 你只需要有一个拥有公网 IP 的 VPS 便可以使用 Ahri 同时访问多个内网环境,并且支持使用公网服务器的网络环境。
Ahri 只想做好三件事。
请不要将 Ahri 与 frp,SSR,V2Ray 等项目做比较,因为 Ahri 对使用场景的定位与它们不同。
当然,如果你有优化 Ahri 的意见和建议,我很乐意接受。
|特性|详情| |:--:|:--| |通用性|Ahri 基于 TCP,所以不关心转发的数据包是基于何种应用层协议的,也就是说 Ahri 一定支持 http。理论上讲,ta 支持所有基于 TCP 的上层协议。| |帧化数据协议|Ahri 拥有自己的应用层协议(Ahri protocol)来经行流量转发。Ahri 对流量的处理方式类似于 http 2.0,所有的数据均是 帧化 的。| |安全|Ahri 采用了 RSA, AES-256-CFB 加密算法保证数据的安全性。| |高效|Ahri 由 golang 编写,本身非常底层,执行效率极高。同时,Ahri 采用 多路复用 模式,在 client 与 server 之间仅建立一个 TCP 连接,避免不必要的协议握手。| |低内存, 低 CPU 使用率|采用 sync.pool 降低 GC 压力与内存占用量。* ahri-client 活跃时,MEM < 7.0MB,%CPU ~= 10%,%CPU max < 15.0% 。* ahri-server 活跃时,MEM < 15.0MB,%CPU ~ 1.5%,%CPU max < 2.1%。| |跨平台|Ahri 由 golang 编写,轻松跨平台;|
*最简模型下的内存测试环境与情景:
在工作中,因商务合作需要使用几家合作公司的内网环境,导致我需要频繁切换 VPN 配置。 而回到家中,如果偶遇突发情况又无法使用自己公司的内网(因为运维不给配)。 TeamViewer 个人版虽然免费,但时不时会出现服务器宕机的情况。 女友公司的运维配置的 VPN 不稳定。
一系列的恼人事件发生后,我决定编写 Ahri 来改善我的工作与生活质量。同时,希望 Ahri 可以帮助那些遇到类似情况的人。
注意: 请严格遵守你所在地区的相关法律法规, 不要将 Ahri 用于违法犯罪行为(尤其是科学上网); 否则后果自负, 毕竟技术无罪, 最坏的情况我会清除源码.
Ahri 适用于但不局限于以下场景,ta 可以解决这些问题。
场景一
你的工作内容需要使用到公司内网,但由于外因,没有 VPN 或根本无法使用。
TeamViewer 无法连接到公司内网的电脑或使用时及其卡顿。
作为开发,需要使用到几个中间件,而它们都在公司内网。
场景二
因商务合作需要使用几家合作公司的内网环境,频繁切换 VPN 配置非常麻烦。
场景三
你所在的网络环境对一些公网域名或 IP 进行了拦截,导致你无法使用它们。
Ahri 需要解决的问题其实是流量转发。然而并不是所有的流量都需要转发,或多次转发。 所以,就请求的发起来说,流量的目的地有三种类型。
Ahri 服务由两个二进制程序来提供,它们是 ahri-server,ahri-client。
ahri-server 负责响应来自 ahri-client 的请求,或者转发一个 ahri-client 的请求给另一个 ahri-client。
ahri-client 负责发起请求,或者响应另一个 ahri-client 的请求。ta 有三个模式。
ahri-client 采用主动注册到 ahri-server 的方式来进行连接,而 ahri-server 会对数个 ahri-client 进行管理。 ahri-client 注册到 ahri-server 后,它们之间会有一个内容加密的 TCP 连接。在这个连接中会传递心跳包与各类数据包。
然后再解释上面挖的一个坑,对一个 TCP 连接经行多路复用。
基于 TCP ,Ahri 自行定义了一个应用层协议 Ahri Protocol。 ta 由 Ahri Registe Protocol(ARP)与 Ahri Frame Protocol(AFP)组成。 ARP 定义了 ahri-client 应该怎样注册到 ahri-server。 AFP 定义了 ahri-client 与 ahri-server 应该怎样交互数据包。 详细的内容请查看Ahri Protocol。
在这里我仅想说明,协议中出现了 Frame,表明 Ahri 将数据做了帧化,对数据包的管理方式类似于 HTTP 2.0。在这样的前提下,仅使用一个 TCP 连接便可以使 ahri-client 与 ahri-server 沟通顺畅。
为了让 ahri-server 管理数个 ahri-client,ARP 规定每一个 ahri-client 均有一个名字(最大长度为 2 的ACSII字符)。 每一个 ahri-client 均有一个 ahri.hosts 文件,可以控制本地请求转发的目的地;也可控制是否对他人提供某些域名或 IP 的转发服务。 其中 'S', 'L', '-', '|' 为系统保留名, 禁止使用它们对 ahri-client 命名.
我们假设自己的客户端名为 'A', 另一个客户端名为 'B', 且均注册至服务端 S, 以下就是 ahri.hosts 文件的示例.
# 转发本地请求至服务端 youtube.com S转发本地请求至另一个客户端 B
mary-live.com B
当前 ahri-client 为 give 或 trade 模式时, 禁止其他客户端访问本地网络环境中的这个域名
tom-live.com -
当前 ahri-client 遇到该域名时, 拦截本地请求, 一般用于广告屏蔽
ad-live.com |
显式表明请求应该在本地处理, 当然所有请求的默认目的地就是 L, 所以可以不写下面这一行.
baidu.com L
我们回顾一下上面的使用场景。 假设我本机 ahri-client 是 A, 我使用的 ahri-server 是 S, 我公司内网(LAN 1)中有一个 ahri-client 是 B, 别人公司内网(LAN 2)中有一个 ahri-client 是 C。
场景一 & 场景二
这两个场景是最常见的 VPN 使用场景,只不过场景二略复杂一点。
当我在自己家时。 我使用自己公司的内网时,流量走向是 A -> S -> B -> LAN 1, 然后原路返回。 我也可以使用对方公司的内网,流量走向是 A -> S -> C -> LAN 2, 然后原路返回。 我也可以正常访问任何公网资源,A -> Internet。
当我在自己公司,使用自己公司的内网时,流量走向是 A -> LAN 1,然后原路返回。 我也可以使用对方公司的内网,流量走向是 A -> S -> C -> LAN 2, 然后原路返回。 我也可以正常访问任何公网资源,A -> Internet。
场景三
对这个场景的处理其实是我在实现场景一、二的过程中顺带写出来的衍生物。 主要就是你所在的网络环境会对一些公网资源的请求进行拦截。 A -> Internet 这条路不通了。所以换线为 A -> S -> Internet。
希望我对上面的场景的解决描述的足够清楚。
我已经对常用的系统完成了源码编译的工作, 你应该可以在 releases 中找到可运行在你系统上的版本. 如果没有, 请自行从源码编译(go1.12.1+).
详细参数与解释仅需要在命令行下执行对应的帮助程序(因为 windows 的限制,需要将 ahri-client 与 ahri-server 先重命名为 ahri-client.exe 与 ahri-server.exe)
客户端 ahri-client -h服务端 ahri-server -h
windows 下
ahri-client.exe -h ahri-server.exe -h
方法一
直接运行 ahri-client / ahri-server, 参数如下.
Usage: ./ahri-client [socks5-cfg] [global-cfg] server-info: -sip serverIp, -sp serverPort, -k serverPassword client-info: -n clientName, -m clientMode socks5-cfg: -s5ip socks5Ip, -s5p socks5Port, -f ahriHostsFile global-cfg: -L logLevel, -T timeoutUnitSecParameters: -L int the log level, 0 ~ 3 ==> debug, info, warn, error (default 3) -T int the timeout of one-way communication time interval between an AhriClient and an AhriServer; Special: AhriClient Dial timeout = 3T, heartbeat timeout = 2T (default 5) -f string the ahri hosts file of this ahri client (default "ahri.hosts") -k string the password of an ahri server -m int the work mode of this ahri client, 0: Take, 1: Give, 2: Trade -n string the name of this ahri client -s5ip string the socks5 IP of this ahri client (default "127.0.0.1") -s5p string the socks5 port of this ahri client (default "23456") -sip string the IP of an ahri server -sp string the port of an ahri server
Usage: ./ahri-server [global-cfg] server-info: -ip serverIp, -p serverPort, -k serverPassword, -a rsaPrivateKey, -b rsaPublicKey global-cfg: -L logLevel, -T timeoutUnitSecParameters: -L int the log level, 0 ~ 3 ==> debug, info, warn, error (default 3) -T int the timeout of one-way communication time interval between an AhriClient and an AhriServer; Special: AhriClient Dial timeout = 3T, heartbeat timeout = 2T (default 5) -a string the private rsa key file of this ahri server (default "rsa_private_key.pem") -b string the public rsa key file of this ahri server (default "rsa_public_key.pem") -ip string the IP of an ahri server -k string the password of an ahri server -p string the port of an ahri server
使用 ahri-client, 你几乎仅配置 ahri.hosts 即可使用. 使用 ahri-server, 你需要 openssl 帮你生成 RSA 公私钥对, 如果你是 *nix 环境, 可以直接调用
bash gen_rsa_keys.sh.
方法二
为了降低配置难度,压缩包中已包含 start.sh,stop.sh 。 仅需要修改必要的参数即可在 *nix 环境中使用。 至于 Windows,参考 sh 脚本即可编写 bat 即可。
提示:如果 ahri-client 与 ahri-server 之间的网络环境是 低带宽 或 高延迟,请适当增大
-T参数的值。
Ahri 其实很简单,但对于不熟悉终端的童鞋还是太难了,那么跟着这个【实践教程】,你可以学习到基础用法。
我已测试并正常使用该工具多时,有任何意见与建议或者问题,请 open 一个 issues。
ahri-client 可以使用最长 2 个 ASCII 字符(你就当做两个英文字母好了)来命名自身。同时 'S', 'L', '-', '|' 均是系统保留名,禁止使用。 为什么最长 2 个字符?由 ARP 决定的。如此,一台服务器已经可以选 (256^2 - 4) 个客户端名,足够使用。
因为 Ahri 的交叉编译脚本中,默认使用 ahri-client 与 ahri-server 这两个名字命名二进制文件,而 windows 要求可执行文件以
exe作为后缀名。 所以,将 ta 们重命名加上
.exe即可。
一般来说,至少在 *nix 环境下绝大多数工具的对接都可以使用 nc 来解决。
下面是 ssh 使用 nc 来对接 Ahri 的例子。
现在本地 socks5 监听代理是 socks5://127.0.0.1:23456 自己服务器是server.test.com修改~/.ssh/config 文件 添加下面配置
host server.test.com HostName server.test.com ProxyCommand nc -X 5 -x 127.0.0.1:23456 %h %p ServerAliveInterval 30 然后通过 ssh [email protected] 就可以愉快的使用 Ahri 代理登录了。