46从零开始用Rust编写nginx,数据还能这么传,多层代理(IP多级代理)搭建
wmproxy
wmproxy
已用Rust
实现http/https
代理, socks5
代理, 反向代理, 负载均衡, 静态文件服务器,websocket
代理,四层TCP/UDP转发,内网穿透等,会将实现过程分享出来,感兴趣的可以一起造个轮子
项目地址
国内: https://gitee.com/tickbh/wmproxy
github: https://github.com/tickbh/wmproxy
设计目标
通过多层代理的代理结构,构建出属于自己的网络通道。
多层代理能做什么
多层代理(也称为IP多级代理)是一种网络代理技术
它通过多个代理服务器来接收和发送数据包,从而隐藏真实IP地址。每个代理服务器都可以处理一个或多个网络请求,通过这种方式,可以在防火墙后面传输数据,同时隐藏真实IP地址和用户身份。这种技术通常用于企业网络和互联网上的安全传输。
当前多层代理的工作原理是在应用层上进行代理传输,从而将原始IP地址和用户身份隐藏起来。在发送数据时,发送方的IP地址会被伪装成目标IP地址的某个IP地址,而接收方的IP地址则会被隐藏在多个IP地址中。这种层层转发网络流量的方式,使得最终目标服务器无法直接获取到请求的真实IP地址,从而增加了网络的安全性和匿名性。
但是请注意,使用多层代理也可能会导致网络连接速度变慢,因为数据需要通过多个代理服务器进行传输。同时如果代理服务器被攻击或出现故障,也可能会影响网络的稳定性和可靠性。因此在选择是否使用多层代理时,需要综合考虑其优缺点,并根据实际需求做出决策。
如何部署
通常了解一个程序如何运行最快的方式除了官方文档,另一种就是查找当前程序的help,通常wmproxy --help
或者wmproxy -h
就可以查询到帮助信息。此时我们是子命令代理,通过wmproxy proxy -h
,可以查询控制消息
Usage: wmproxy.exe proxy [-s=ARG] [-b=ARG] [-c=ARG] [--flag=ARG] [-S=ARG] [--user=ARG] [--pass=ARG] [
--udp-bind=ARG] [--map-http-bind=ARG] [--map-https-bind=ARG] [--map-tcp-bind=ARG] [--map-proxy-bind=ARG
] [--map-cert=ARG] [--map-key=ARG] [--ts] [--tc] [--two-way-tls] [--domain=ARG] [--cert=ARG] [--key=ARG
] [--mappings=ARG]... [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG
]
代理类, 一个代理类启动一种类型的代理
-s, --server-id=ARG 代理id
[default: 0]
-b, --bind=ARG 代理绑定端口地址
-c, --center-addr=ARG 中心代理绑定端口地址
--flag=ARG 代理种类, 如http https socks5
-S, --server=ARG 连接代理服务端地址
--user=ARG 用于socks验证及中心服务器验证
--pass=ARG 用于socks验证及中心服务器验证
--udp-bind=ARG udp的绑定地址
--map-http-bind=ARG 内网http的映射地址
--map-https-bind=ARG 内网https的映射地址
--map-tcp-bind=ARG 内网tcp的映射地址
--map-proxy-bind=ARG 内网代理的映射地址
--map-cert=ARG 内网映射的证书cert
--map-key=ARG 内网映射的证书key
--ts 连接服务端是否启用tls
--tc 接收客户端是否启用tls
--two-way-tls 双向认证是否启用
--domain=ARG tls证书所用的域名
--cert=ARG 公开的证书公钥文件
--key=ARG 隐私的证书私钥文件
--mappings=ARG
此时我们绑定端口分为两种
-b, --bind=ARG 代理绑定端口地址
-c, --center-addr=ARG 中心代理绑定端口地址
- 其中
-b
是绑定来自于第三方代理客户端发起(http/https/socks)代理请求的信息 - 其中
-c
是绑定来自于客户端与服务端建立的代理请求信息。是服务器内部间构建的信息通道。 - 其中
-S
或者--server
表示该程序需连接到代理服务端,将数据请求发送到服务器处理。 - 其中
--ts
表示连接服务端时是否启用tls - 其中
--tc
表示接收客户端时是否需要tls,这两个需要正确配对并设置相应的--cert
及--key
以下流程图,展示数据的处理流程,其中代理B的角色可以是0个也可以是若干个。
participant Client as 用户端
participant A as 代理端A<br/>监听-b 8090
participant B as 代理端B<br/>监听"-c 8091"
participant C as 代理端C<br/>监听"-c 8092"
B->>C: 主动连接127.0.0.1:8092<br/>建立内部通道
A->>B: 主动连接127.0.0.1:8091<br/>建立内部通道
Client->>A: 发起HTTP代理请求
A->>B: 构建内部通讯协议<br/>创建唯一id
B->>C: 构建代理A与C中转通道<br/>双向绑定中转数据
C->>C: 解析数据,并处理代理
C->>B: 返回代理数据
B->>A: A与C的中转通道
A->>Client: 解析数据转成代理请求发送
- 代理C的启动命令:
wmproxy proxy -c :8092
- 代理B的启动命令:
wmproxy proxy -c :8091 -S 127.0.0.1:8092
- 代理A的启动命令:
wmproxy proxy -b :8090 -S 127.0.0.1:8091
通过如何我们就构建出了一条内部的代理通道,此时通过curl测试
curl.exe --proxy http://127.0.0.1:8090 https://www.baidu.com -I
可以得到以下正确返回200信息
HTTP/1.1 200 OK
Server: wenmeng
content-length: 0
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Fri, 26 Jan 2024 02:27:04 GMT
Etag: "575e1f71-115"
Last-Modified: Mon, 13 Jun 2016 02:50:25 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
源码剥析
关于server_id
因为在构建tcp唯一映射的时候,是通过本地的自增id来进行处理。
pub fn calc_next_id(&mut self) -> u64 {
let id = self.next_id;
self.next_id = self.next_id.wrapping_add(2);
Helper::calc_sock_map(self.option.server_id, id)
}
即当出口处理的服务器如果前端有多条客户端的时候存在冲突的可能的。就比如id均为2,那么服务端将无法正确处理是来自哪个客户端的数据,也无法进行相应的转发。所以此处我们引入server_id的概念,通过server_id与id进行组合运算,得出系统内的唯一id,保证数据没有冲突。
let mut map = HashMap::<u64, Sender<ProtFrame>>::new();
关于中心客户端
- 源码:
center_client
- 类名:
CenterClient
- 功能:它负责将客户端的数据转化成服务器内部的通讯,并将内部的通讯转化成客户端的数据。
- 构建:当仅它有
-b
监听第三方客户端的时候构建。 - 核心函数:
async fn inner_serve<T>(
option: &ProxyConfig,
stream: T,
sender: &mut Sender<ProtFrame>,
receiver_work: &mut Receiver<(ProtCreate, Sender<ProtFrame>)>,
receiver: &mut Receiver<ProtFrame>,
mappings: &mut Vec<MappingConfig>,
) -> ProxyResult<()>
关于中心服务端
- 源码:
center_server
- 类名:
CenterServer
- 功能:它负责将服务器内部的数据进行解析,并发起http代理的请求,此处他为出口
- 构建:当仅他的目标上级服务器不存在时且
-c
参数被设置进行构建。即-S
没有设置 - 核心函数:
pub async fn inner_serve<T>(
stream: T,
option: ProxyConfig,
sender: Sender<ProtFrame>,
mut receiver: Receiver<ProtFrame>,
mut receiver_work: Receiver<(ProtCreate, Sender<ProtFrame>)>,
mappings: Arc<RwLock<Vec<MappingConfig>>>,
) -> ProxyResult<()>
关于中心转发服
- 源码:
center_trans
- 类名:
CenterTrans
- 功能:它负责将来自代理客户端的请求转发给代理服务端
- 构建:当且仅当
-c
被设置且-S
被设置,即监听中心客户端又连接中心服务端,充当转发功能,由于不存在任何解析,性能高。 - 核心函数:
pub async fn serve<T>(&mut self, mut stream: T) -> ProxyResult<()>
where
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
let mut server = if self.tls_client.is_some() {
let connector = TlsConnector::from(self.tls_client.clone().unwrap());
let stream = HealthCheck::connect(&self.server).await?;
// 这里的域名只为认证设置
let domain = rustls::ServerName::try_from(
&*self
.domain
.clone()
.unwrap_or("soft.wm-proxy.com".to_string()),
)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?;
let outbound = connector.connect(domain, stream).await?;
MaybeHttpsStream::Https(outbound)
} else {
let outbound = HealthCheck::connect(&self.server).await?;
MaybeHttpsStream::Http(outbound)
};
tokio::spawn(async move {
let _ = tokio::io::copy_bidirectional(&mut stream, &mut server).await;
});
Ok(())
}
小结
多层代理可以帮助我们在有限的情况下构建出更稳定的代理通道,可以更好的保护源站,也可以利用该方法给企业构建出稳定的内网通道。也可以在统一出口的情况下保护内网的数据。
点击 [关注],[在看],[点赞] 是对作者最大的支持
46从零开始用Rust编写nginx,数据还能这么传,多层代理(IP多级代理)搭建的更多相关文章
- bloom-server 基于 rust 编写的 rest api cache 中间件
bloom-server 基于 rust 编写的 rest api cache 中间件,他位于lb 与api worker 之间,使用redis 作为缓存内容存储, 我们需要做的就是配置proxy,同 ...
- 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(二)
前一节已经完成了Oracle数据库和ODI的安装,并已经为ODI在Oracle数据库中创建了两个用户,分别用于存放主资料库数据和工作资料库数据,在ODI中完成主资料库和工作资料库的创建,也分别为其创建 ...
- 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(一)
0. 环境说明及软件准备 ODI(Oracle Data Integrator)是Oracle公司提供的一种数据集成工具,能高效地实现批量数据的抽取.转换和加载.ODI可以实现当今大多数的主流关系型数 ...
- centos LNMP第一部分环境搭建 LAMP LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/php/{p.conf.default,p.conf} php运行方式SAPI介绍 第二十三节课
centos LNMP第一部分环境搭建 LAMP安装先后顺序 LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/local/php/{ ...
- 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(三)
资料库的创建.体系结构的创建.模型反向工程都已经完成了,下面就是创建以及执行接口来完成工作了. 浏览前两节请点击: [ODI]| 数据ETL:从零开始使用Oracle ODI完成数据集成(一) [OD ...
- C#开发BIMFACE系列46 服务端API之离线数据包下载及结构详解
BIMFACE二次开发系列目录 [已更新最新开发文章,点击查看详细] 在前一篇博客<C#开发BIMFACE系列45 服务端API之创建离线数据包>中通过调用接口成功的创建一个离线数 ...
- java编写网站数据抓取
来公司已经俩月了,每天加班平均工时11个小时的我又想起了老东家温馨舒适安逸的生活.已经有好久没时间读博客写博客了,我觉得我退步了,嗯嗯,我很不开心 今天记录下抓数据的一些东西吧. 数据抓取现在是很普遍 ...
- Nginx正向代理、反向代理、负载均衡及性能优化
一.Nginx是什么 Nginx是一款高性能的 HTTP 和反向代理服务器,由俄罗斯人Igor Sysoev(伊戈尔·赛索耶夫)为俄罗斯网站Rambler.ru开发的,在Rambler.ru网站平稳的 ...
- Centos8 Docker+Nginx部署Asp.Net Core Nginx正向代理与反向代理 负载均衡实现无状态更新
首先了解Nginx 相关介绍(正向代理和反向代理区别) 所谓代理就是一个代表.一个渠道: 此时就涉及到两个角色,一个是被代理角色,一个是目标角色,被代理角色通过这个代理访问目标角色完成一些任务的过程称 ...
- nginx正向代理,反向代理,透明代理(总结)
1正向代理 正向代理,也就是传说中的代理,他的工作原理就像一个跳板, 简单的说, 我是一个用户,我访问不了某网站,但是我能访问一个代理服务器 这个代理服务器呢,他能访问那个我不能访问的网站 于是我先连 ...
随机推荐
- svelte响应式原理
svelte文件编译为js后的结构 源代码: <script lang="ts"> let firstName = '张' let lastName = '三' let ...
- PySpark 报错 java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
解决方案: mv mysql-connector-java-8.0.20.jar $SPARK_HOME/jars/ 驱动文件mysql-connector-java-8.0.20.jar是从mave ...
- 【有奖体验】AI 都这么厉害了,可以看图生成文字描述!
立即体验基于函数计算部署[图生文]一键部署图像描述模型: https://developer.aliyun.com/topic/aigc_fc 人工智能生成内容(Artificial Intellig ...
- vue-cli3title标签中的htmlWebpackPlugin.options.title
https://blog.csdn.net/weixin_56650035/article/details/119355625
- uni-app滚动加载下一页
https://www.bilibili.com/video/BV1BJ411W7pX?p=39
- citespace 文献计量工具初探
先放几个教程: 知乎 - CiteSpace 使用教程 - 312 赞同 知乎 - CiteSpace 入门教程 - 949 赞同 简书 - 研究方法 | 用 CiteSpace 进行科学文献可视化分 ...
- Multi-Master APB Interconnect
APB总线并不是只有一个master(AHB2APB Bridge),可以通过设计支持多个APB Master,只是比较复杂 Lattice 实现了一款Multi-Master Interconnec ...
- Laravel - blade 基础语法和include的使用
<!-- 1. 模板中输出PHP变量 --> @section('footer') <div style="color:#fff"> @par ...
- [转帖]nginx优化配置及方法论
https://www.jianshu.com/p/87f8c03e91bd 1.优化方法论 从软件层面提升硬件使用效率 增大CPU的利用率 增大内存的利用率 增大磁盘IO的利用率 增大网络带宽的利用 ...
- [转帖]Tomcat部署及优化
目录 一.Tomcat简介 1 Tomcat的三大核心组件 2 Java Servlet 3 JSP全称Java Server Pages 4 Tomcat 功能组件结构 5 Tomcat 请求过程 ...