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正向代理 正向代理,也就是传说中的代理,他的工作原理就像一个跳板, 简单的说, 我是一个用户,我访问不了某网站,但是我能访问一个代理服务器 这个代理服务器呢,他能访问那个我不能访问的网站 于是我先连 ...
随机推荐
- MIGO生产订单入库写入批次特性增强
一.生产订单入库 MIGO根据生产订单入库时,将生产订单中的字段,写入到批次特性中 二.BADI:MB_MIGO_BADI 调用BADI中的IF_EX_MB_MIGO_BADI~POST_DOCUME ...
- 供应链安全情报 | 恶意py包伪装代理SDK进行后门攻击,目标锁定python开发者
概述 2023年11月28号,悬镜供应链安全实验室在Pypi官方仓库(https://pypi.org)监测到两起伪装成http和socks5代理SDK的开源组件投毒事件.python开发者一旦下载安 ...
- vue Promise的使用
一.Promise是什么? Promise是异步编程的一种解决方案. 二.那什么时候我们会来处理异步事件呢? 1. 一种很常见的场景应该就是网络请求了. 我们封装一个网络请求的函数,因为不能立即拿到结 ...
- 洛谷 P9683 A Certain Forbidden Index 题解
题目链接:\(\color{Purple}\texttt{P9683 A Certain Forbidden Index}\). 填坑.提供一个相对好写的做法. 考虑把一堆不交的区间绑在一起问(即先询 ...
- go 变量逃逸分析
0. 前言 在 小白学标准库之 reflect 篇中介绍了反射的三大法则以及变量的逃逸分析.对于逃逸分析的介绍不多,大部分都是引自 Go 逃逸分析.不过后来看反射源码的过程中发现有一种情况 Go 逃逸 ...
- 聊一聊数字孪生与3D可视化
前言 在当代科技发展的背景下,数字孪生和3D可视化技术逐渐成为各行业的关键工具和解决方案.数字孪生是一种将实物事物与数字模型相结合的概念,通过将物理世界和数字世界实时连接,创造出一个对实体进行虚拟建模 ...
- SV 数据类型-2
动态数组 数组定义的时候不用给定数组元素个数 动态数组实例 例1 队列
- Git-基本介绍
- [转帖]linux之iftop命令
https://rumenz.com/rumenbiji/linux-iftop.html Linux安装iftop > yum install iftop -y > iftop 界面如下 ...
- [转帖]Jmeter学习笔记(二十三)——生成HTML性能报告
https://www.cnblogs.com/pachongshangdexuebi/p/11759316.html 有时候我们写性能报告的时候需要一些性能分布图,JMeter是可以生成HTML性能 ...