wmproxy

wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子

项目地址

国内: https://gitee.com/tickbh/wmproxy

github: https://github.com/tickbh/wmproxy

设计目标

需要能对针对性的IP地址进行放行或者禁止,从而达到网络限制或者安全等目的,保护系统的整体稳定性。

IP的作用

IP地址的作用是标示一台在互联网上的主机,就像每个人的住宅地址一样,邮寄东西需要住宅地址,而互联网上一台电脑对另一台电脑发送数据也需要一个可以识别的地址。

早期的IP地址由32位(即IPv4)的数据表示,也就是大概有42亿的地址,以现如今的网络拥有量已经将公有IP即将耗尽的情形。即使有大量的地址并不会占用公网地址,如公司内部的电脑,家庭内部的电脑,手机等并未占用公网地址,可能很多的设备占用了同一个公网出口。所以我们做了IPv4的限定的时候,也有可能将正常的用户做了相关限定。

现在正在推行的IP地址是128位(即IPv6)的数据将可以表示很大的IP数,将可以每个物联网的设备都拥有独立的IP,但是由于IP的升级涉及到大量的基础设备,大量的旧软件,所以当下基本上两种IP都必须支持的阶段。但是国内相对IPv4占了大部分。

IP中子网掩码

子网掩码就是为了划分同网段的主机数量。每类网段默认是254个。

我们在现实的生活中经常看到路由上255.255.255.0/24也经常在云的白名单上看到了0.0.0.0/0,那么他们表示的含义又是什么呢?

通常我们可以把IPv4看成一个无符号的32位整型,那么255.255.255.0/24后面的24就表示0xffffff00,那么我们将某个IP与该值进行按位与运算,得到相同的值将表示归属于同一个IP段。

举例:内网常用的ip如192.168.0.100按位与后将变成192.168.0.0,及192.168.0.1-254这254个ip按位与得到的地址均为

192.168.0.0,所以他们归属于同一个IP段,也就是表示在他们在同一个路由器下面。

0.0.0.0/0中最后的0就是表示0x00000000,那么我们将任意的IP与该值做按位与得到的值均为0.0.0.0,则表示所有的IP都归属于同一个类,也就是通常配置的白名单对所有的都生效。

IPv6与IPv4类似,只是IPv6的长度更长,子网的长度可以由0-127,而IPv6不叫子网掩码,通常称其为前缀,但其原理都是用位表示,前n位为网络位,则说明IP只要前n位一样,则子网一样,IP的机制通了,涉及IP的问题也就好解决了。

源码的实现

Rust中并不支持子网掩码等,那么我们将在其基础上增加一个8位的无符号型:

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IpGate {
pub ip: IpAddr,
pub gate: u8,
}

序列化我们通过serde_with中的DisplayForStr实现,如果存在/则将其切割,如果不存在那么子网掩码位数为0,兼容两种模式:


impl FromStr for IpGate {
type Err = io::Error; fn from_str(s: &str) -> Result<Self, Self::Err> {
let vals = s.split("/").collect::<Vec<&str>>();
let ip = vals[0].parse::<IpAddr>().map_err(|_| io::Error::new(io::ErrorKind::Other, "parse ip error"))?;
let mut gate = 0;
if vals.len() > 1 {
gate = vals[1].parse::<u8>().map_err(|_| io::Error::new(io::ErrorKind::Other, "parse ip error"))?;
if ip.is_ipv4() && gate > 32 {
return Err(io::Error::new(io::ErrorKind::Other, "too big gate"));
} else if ip.is_ipv6() && gate > 128 {
return Err(io::Error::new(io::ErrorKind::Other, "too big gate"));
}
}
Ok(IpGate {
ip, gate
})
}
} impl Display for IpGate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.gate > 0 {
f.write_fmt(format_args!("{}/{}", self.ip, self.gate))
} else {
f.write_fmt(format_args!("{}", self.ip))
}
}
}

查看是否包含:

pub fn contains(&self, ip: &IpAddr) -> bool {
if self.gate == 0 {
ip == &self.ip
} else {
match (&ip, &self.ip) {
(IpAddr::V4(other), IpAddr::V4(my)) => {
let other = u32::from_be_bytes(other.octets()) >> (32u8 - self.gate);
let my = u32::from_be_bytes(my.octets()) >> (32u8 - self.gate);
other == my
}
_ => {
ip == &self.ip
}
}
}
}

在负载均衡中的通行及禁止

我们将配置信息转化成可通行的IP段数组或者禁止的IP段数组

  • 如果存在可通行的配置那么必须在配置中才可通行
  • 如果存在禁止的IP,那么在配置中的将会被禁止

我们在配置的时候,就可以进行如下的配置:

[[http.server.location]]
rule = "/try"
# 只允许本地网络通行
allow_ip = "127.0.0.1 192.168.0.0/24" [[http.server.location]]
rule = "/"
reverse_proxy = "http://server"
# 全面禁止10开头的IP段
deny_ip = "10.0.0.0/8"

源码示例:


if l.comm.deny_ip.is_some() || l.comm.allow_ip.is_some() {
if let Some(ip) = req.headers().system_get("{client_ip}") {
let ip = ip
.parse::<IpAddr>()
.map_err(|_| ProtError::Extension("client ip error"))?;
if let Some(allow) = &l.comm.allow_ip {
if !allow.contains(&ip) {
return Ok(Response::status503()
.body("now allow ip")
.unwrap()
.into_type());
}
}
if let Some(deny) = &l.comm.deny_ip {
if deny.contains(&ip) {
return Ok(Response::status503().body("deny ip").unwrap().into_type());
}
}
}
}

小结

后续可能需要在接受连接的时候就直接禁止掉IP,那么我们可以防止客户端持续的发送流量,即可能造成流量被耗尽。

IP的通行及禁止帮我们更好的保护系统的健壮性及私域的隐私性做保证。自动禁止IP的话,将是WAF等进阶能力的,更好的保护源站。

点击 [关注][在看][点赞] 是对作者最大的支持

38. 干货系列从零用Rust编写负载均衡及代理,负载均衡中ip通行与禁止的更多相关文章

  1. 【转】Spring Boot干货系列:(一)优雅的入门篇

    转自Spring Boot干货系列:(一)优雅的入门篇 前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社区中热度一直很高,所以决定花时间来了解和学习,为自己做 ...

  2. Spring Boot干货系列:(八)数据存储篇-SQL关系型数据库之JdbcTemplate的使用

    Spring Boot干货系列:(八)数据存储篇-SQL关系型数据库之JdbcTemplate的使用 原创 2017-04-13 嘟嘟MD 嘟爷java超神学堂 前言 前面几章介绍了一些基础,但都是静 ...

  3. Spring Boot干货系列:(七)默认日志框架配置

    Spring Boot干货系列:(七)默认日志框架配置 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 今天来介绍下Spring Boot如何配置日志logback,我刚学习的时候, ...

  4. Spring Boot干货系列:(五)开发Web应用JSP篇

    Spring Boot干货系列:(五)开发Web应用JSP篇 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 上一篇介绍了Spring Boot中使用Thymeleaf模板引擎,今天 ...

  5. Spring Boot干货系列:(四)Thymeleaf篇

    Spring Boot干货系列:(四)Thymeleaf篇 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 Web开发是我们平时开发中至关重要的,这里就来介绍一下Spring Boo ...

  6. Spring Boot干货系列:(一)优雅的入门篇

    Spring Boot干货系列:(一)优雅的入门篇 2017-02-26 嘟嘟MD 嘟爷java超神学堂   前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社 ...

  7. Spring Boot干货系列:(十二)Spring Boot使用单元测试(转)

    前言这次来介绍下Spring Boot中对单元测试的整合使用,本篇会通过以下4点来介绍,基本满足日常需求 Service层单元测试 Controller层单元测试 新断言assertThat使用 单元 ...

  8. (转)Spring Boot干货系列:(七)默认日志logback配置解析

    转:http://tengj.top/2017/04/05/springboot7/ 前言 今天来介绍下Spring Boot如何配置日志logback,我刚学习的时候,是带着下面几个问题来查资料的, ...

  9. (转)Spring Boot干货系列:(四)开发Web应用之Thymeleaf篇

    转:http://tengj.top/2017/03/13/springboot4/ 前言 Web开发是我们平时开发中至关重要的,这里就来介绍一下Spring Boot对Web开发的支持. 正文 Sp ...

  10. 【WEB API项目实战干货系列】- 导航篇(十足干货分享)

    在今天移动互联网的时代,作为攻城师的我们,谁不想着只写一套API就可以让我们的Web, Android APP, IOS APP, iPad APP, Hybired APP, H5 Web共用共同的 ...

随机推荐

  1. Ds100p -「数据结构百题」1~10

    1.「一本通 4.6 例 1」营业额统计 原题来自:HNOI 2002 Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger 拿出 ...

  2. strimzi实战之一:简介和准备

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于strimzi strimzi是一个开源项目,已加 ...

  3. 全局重写Element UI中的Message消息提示显示时长

    需求:Message消息提示显示时长过长 环境:"vue": "2.6.12"."element-ui": "^2.15.6&qu ...

  4. Springboot 实现QQ登录(界面跳转)

    Springboot 实现QQ登录(界面跳转) 现在第三方登录已经变成主流app的登录方式了 今天记录一下如何给自己的网站实现第三方登录(这里以QQ登录为例) 准备工作 首先确保你准备好你自己网站的域 ...

  5. c语言代码练习12

    //计算1/1-1/2+1/3...-1/100的和#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { in ...

  6. python~windows自动化工具 uiautomation库

    微软提供了关于自动化操作PC端桌面应用程序的工具,官方描述为: Microsoft UI Automation is an accessibility framework that enables W ...

  7. select...for update到底是加了行锁,还是表锁?

    前言 前几天,知识星球中的一个小伙伴,问了我一个问题:在MySQL中,事务A中使用select...for update where id=1锁住了,某一条数据,事务还没提交,此时,事务B中去用sel ...

  8. 2022-10-22 CSP赛前隔离时的模拟赛 2:3

    T1 简单红题,不懈于写. 锐评:镜子反射出来的竟然没有镜像一下. T2 坑人东西调了 2h. 类似于 round1 的 T4. 线性 \(\Theta(n)\) 过. T3 T4 其实简单,负边权要 ...

  9. Xmind思维导图工具2023最新专业版破解思路

    工具介绍 XMind 是一款最为流行的专业级思维_导图_制作与编辑软件,它现在在全球范围内都已极具名气,可谓是办公.学习.团队交流必备工具之一. 准备工作 1,官方Xmind软件 2,一个心意的编辑器 ...

  10. 7z 一键压缩备份

    该批处理已开源 开原地址: 点击进入 磁盘备份 工具有很多,如果你需要增量式备份的话,以下这些方法并不适合你.goodsync 可以了解一下. 以下方式仅适用于,懒人一键压缩备份. 对于我来说 定期的 ...