终于写完轮子一部分:tcp代理 了,记录一下
24年终自己立了flag: 25年做些轮子玩(用于浪费生命,赚不了钱)
所以25年就准备用c#写一个网络代理NZOrz(nginx知道吧,就那玩意儿干的事),包含 udp/tcp/http1 2 3,
至于为啥不用rust写,主要由于某台电脑某些不可告知的原因不方便安装rust,所以等我写完c#的,后面有空再说吧(应该25年没时间了吧)
代码借鉴出处
秉承将生命浪费到底的造轮子精神,实力不行就尽可能借鉴(抄袭,读书人的事,怎么能说呢)
所以这里首先列举一下借鉴出处
所以整体实现上都是socket 上层做多线程处理,不编写与系统内核交互或者其他io事件库打交道的代码
(为啥?要打跨平台交道,我不如直接用 rust 写 linux的,window写不写看心情,反正服务器是王道是不是)
局限
不得不先提一个局限,dotnet 的socket 没有提供统一的跨进程socket转移api,因为dotnet是跨平台的,不同系统存在差异,该issue Migrate Socket between processes 已经多年没有下文了
所以不好做到热重启
初步完成进度
- TCP server core
- TCP proxy core
- dns (use system dns, no query from dns server )
- LoadBalancingPolicy
- Passive HealthCheck
- TCP Connected Active HealthCheck
- Configuration
- reload config and rebind
- Log
- UDP server core
- Config Validators
- UDP proxy core
- HTTP1 server core
- HTTP2 server core
- HTTP3 server core
- HTTP proxy core
- Metrics
对,目前主要是完成了基础的 tcp 部分(代理协议不支持,毕竟有那么多,时间也有限),下一步以 udp 为优先,(文档吗?等我先完成再说)
tcp代理使用
目前没有提供现成打包好的exe或者docker镜像,毕竟离完成还有很远的距离
要玩可以这样
建一个 net8.0 或者net9.0 的Console 项目
安装package
dotnet add package NZ.Orz --version 0.0.0.2-beta
入口代码
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NZ.Orz;
using NZ.Orz.ReverseProxy.L4;
var app = NZApp.CreateBuilder(args)
    .UseJsonConfig()
    .Build();
await app.RunAsync();
配置 文件 appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  },
  "ReverseProxy": {
    "Routes": {
      "apidemo": {
        "Protocols": "TCP",
        "Match": {
          "Hosts": [ "*:5000" ]
        },
        "ClusterId": "apidemo",
        "RetryCount": 1,
        "Timeout": "00:00:11"
      }
    },
    "Clusters": {
      "apidemo": {
        "LoadBalancingPolicy": "RoundRobin",
        "HealthCheck": {
          "Active": {
            "Enable": false,
            "Policy": "Connect"
          }
        },
        "Destinations": [
          {
            "Address": "[::1]:5144"
          },
          {
            "Address": "[::1]:5146"
          },
          {
            "Address": "google.com:998"
          },
          {
            "Address": "www.baidu.com"
          },
          {
            "Address": "http://google.com"
          },
          {
            "Address": "https://google.com"
          }
        ]
      }
    }
  }
}
然后启动就行, 启动log大致如下
info: NZ.Orz.Server.ReverseProxy[18]
      Config changed. Starting the following endpoints: [Protocols: TCP,Route: apidemo,EndPoint: 0.0.0.0:5000],[Protocols: TCP,Route: apidemo,EndPoint: [::]:5000]
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\code\edge\l4proxy\src\L4Proxy\bin\Debug\net8.0
当然,运行中 如果改动appsettings.json内容,会根据配置 重新监听变动端口/重建路由表等等
也算是一定程度弥补无法热重启的问题
改动tcp的数据
如果想改动tcp的数据,可以实现中间件 ITcpMiddleware
比如
public class EchoMiddleware : ITcpMiddleware
{
    public int Order => 0;
    public Task<ReadOnlyMemory<byte>> OnRequest(ConnectionContext connection, ReadOnlyMemory<byte> source, CancellationToken cancellationToken, TcpConnectionDelegate next)
    {
        Console.WriteLine($"{DateTime.Now} {connection.LocalEndPoint.ToString()} request size: {source.Length}");
        return Task.FromResult(source);
    }
    public Task<ReadOnlyMemory<byte>> OnResponse(ConnectionContext connection, ReadOnlyMemory<byte> source, CancellationToken cancellationToken, TcpConnectionDelegate next)
    {
        Console.WriteLine($"{DateTime.Now} {connection.SelectedDestination.EndPoint.ToString()} reponse size: {source.Length}");
        //source = Encoding.UTF8.GetBytes("HTTP/1.1 400 Bad Request\r\nDate: Sun, 18 Oct 2012 10:36:20 GMT\r\nServer: Apache/2.2.14 (Win32)\r\nContent-Length: 0\r\nContent-Type: text/html; charset=iso-8859-1\r\nConnection: Closed\r\n\r\n").AsMemory();
        //connection.Abort();
        return Task.FromResult(source);
    }
}
然后注入ioc就行
var app = NZApp.CreateBuilder(args)
    .ConfigServices(services =>
    {
        services.AddSingleton<ITcpMiddleware, EchoMiddleware>();
    })
    .UseJsonConfig()
    .Build();
配置简单说明
详细等以后写文档再说吧
Protocols 支持 TCP
Hosts 支持后缀匹配, 比如匹配所有实例5000端口就可以写 *:5000, 匹配某个实例如 192.1.1.1,3000端口就可以写 192.1.1.1:3000
(路由表实现采用 前缀树+字典+SIEVE cahce)
服务发现目前只支持 DNS, 但不支持指定 dns server, 因为 dns不支持,以后再说吧
HealthCheck 支持主动 被动 二选一,不支持一起用, 主动 暂时只支持 socket connect 成功检查
LoadBalancingPolicy 支持四种 Random , RoundRobin , LeastRequests , PowerOfTwoChoices
先就这样,其他等我慢慢实现
大家有空的话,能否在 GitHub https://github.com/fs7744/NZOrz 点个 star 呢?毕竟借鉴代码也不易呀 哈哈哈哈哈
终于写完轮子一部分:tcp代理 了,记录一下的更多相关文章
- iOS进阶之TCP代理鉴权过程
		这段时间接触了网络代理,而自己的任务是完成TCP和UDP的网络代理,所以在这里写些自己的理解吧. 这篇文章先介绍一下TCP代理的鉴权过程(采用的是用户名和密码鉴权),下一篇文章再介绍UDP代理的鉴权过 ... 
- 不写完不让回家的JQuery的事件与动画
		在这看不见太阳的小黑屋里,苦逼的一天又开始了 好了闲话我也就不扯了,接下来我就来说说我对jQuery事件和动画的理解吧!!! 还是得再扯两句,我们敬爱的,Y老师讲完了,jQuery事件和动画,对着我们 ... 
- 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.
		刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 
- nginx TCP 代理& windows傻瓜式安装
		一.下载nginx Windows http://nginx.org/en/download.html 二.解压到目录 三.进入目录并start nginx.exe即可启动 cd d:/java/ng ... 
- nginx : TCP代理和负载均衡的stream模块
		一直以来,Nginx 并不支持tcp协议,所以后台的一些基于TCP的业务就只能通过其他高可用负载软件来完成了,比如Haproxy. 这算是一个nginx比较明显的缺憾.不过,在1.90发布后这个认知将 ... 
- 早期nginx tcp代理(基于patch实现)
		nginx tcp代理功能由nginx_tcp_proxy_module模块提供,同时监测后端主机状态.该模块包括的模块有: ngx_tcp_module, ngx_tcp_core_module, ... 
- Nginx 配置TCP代理
		Nginx 1.9 版本以后增加了stream模块,可以对tcp,udp请求进行代理和负载均衡了,今天来体验一下首先编译安装过程configure的时候增加选项 --with-stream --wit ... 
- Scrum:The Definition of Done —— 作业有没有写完呢?
		Scrum:The Definition of Done -- 作业有没有写完呢?_苗得雨_新浪博客 http://blog.sina.com.cn/s/blog_59450ffc0102eiai.h ... 
- HDU 4640 状态压缩DP 未写完
		原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4640 解题思路: 首先用一个简单的2^n*n的dp可以求出一个人访问一个给定状态的最小花费,因为这i个 ... 
- nginx做TCP代理实现群集
		nginx做TCP代理实现群集 nginx从版本1.9开始,既能做HTTP代理,又能做TCP代理,这就非常完美了. 配置nginx.conf. 为了简单起见,笔者故意去掉了HTTP代理配置部分,只保留 ... 
随机推荐
- 【C#】【报错解决】分析器错误消息: 未能找到 CodeDom 提供程序类型“Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider
			1.工具->NuGet包管理器->程序包管理控制台 2.在程序包管理控制台中输入 PM> Install-Package Microsoft.CodeDom.Providers.Do ... 
- virtualbox设置了共享文件夹却无权限访问
			在virtualbox中设置共享文件夹后,然后登陆ubuntu系统访问共享文件夹,发现没有权限.查看共享文件夹的属性可知,共享文件夹的所有者是root,所属的组是vboxsf.以用户登录的时候,自然是 ... 
- NJU ICS2024 PA 作业心得(三)
			NJU ICS2024 PA 作业心得(三) 需要参考的内容 RISC-V ABIs Specification:是一组规则和规范,定义了在 RISC-V 架构上编写和链接程序的方式.它确保了不同语言 ... 
- Qt音视频开发18-不同视频打开无缝切换
			一.前言 在轮询视频的时候,通常都是需要将之前的视频全部关闭,然后打开下一组视频,在这个切换的过程中,如果是按照常规的做法,比如先关闭再打开新的视频,肯定会出现空白黑屏之类的过度空白区间,如何避免这个 ... 
- 即时通讯技术文集(第29期):IM开发技术合集(Part2) [共18篇]
			为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第29 期. [- 1 -] 谈谈移动端 IM 开发中登录请求的优化 [链接] http://w ... 
- 融云技术分享:全面揭秘亿级IM消息的可靠投递机制
			本文由融云技术团队原创分享,原题"IM 消息同步机制全面解析",为使文章更好理解,对内容进行了重新归纳和细节修订. 1.内容概述 即时通讯(IM)系统最基础.最重要的是消息的及时性 ... 
- OpenMMLab AI实战营 第七课笔记
			OpenMMLab AI实战营 第七课笔记 目录 OpenMMLab AI实战营 第七课笔记 import os import numpy as np from PIL import Image im ... 
- 某苏人社异步JS逆向加解密分析(sm2+sm3+sm4)
			前期准备 网址:aHR0cHM6Ly9ycy5qc2hyc3MuamlhbmdzdS5nb3YuY24vaW5kZXgv 目标: 接口请求内容加密和响应内容解密 请求头加密参数 Web-Encrypt ... 
- VUE3基础环境搭建
			VUE3基础环境搭建 1. 安装vue.js npm install vue -g 安装webpack Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bun ... 
- C# 窗口鼠标穿透以及取消窗口鼠标穿透
			private const int WS_EX_TRANSPARENT = 0x20; private const int GWL_EXSTYLE = -20; /// <summary> ... 
