惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
K
Kaspersky official blog
V
Vulnerabilities – Threatpost
Hacker News - Newest:
Hacker News - Newest: "LLM"
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
I
Intezer
TaoSecurity Blog
TaoSecurity Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Spread Privacy
Spread Privacy
A
About on SuperTechFans
NISL@THU
NISL@THU
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
S
Security @ Cisco Blogs
S
SegmentFault 最新的问题
G
Google Developers Blog
B
Blog
N
News and Events Feed by Topic
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Google DeepMind News
Google DeepMind News
V2EX - 技术
V2EX - 技术
V
Visual Studio Blog
MyScale Blog
MyScale Blog
Webroot Blog
Webroot Blog
Vercel News
Vercel News
IT之家
IT之家
Microsoft Security Blog
Microsoft Security Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
S
Security Affairs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
博客园 - 叶小钗
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Know Your Adversary
Know Your Adversary
T
Tailwind CSS Blog
F
Fortinet All Blogs
D
DataBreaches.Net
博客园 - Franky
博客园_首页
H
Heimdal Security Blog
宝玉的分享
宝玉的分享
阮一峰的网络日志
阮一峰的网络日志
Attack and Defense Labs
Attack and Defense Labs
Project Zero
Project Zero
雷峰网
雷峰网

博客园 - victor.x.qu

MCP 企业托管授权(Enterprise-Managed Authorization) 从状态机到运行时:聊聊 .NET 11 的 Runtime Async 和老 Async/Await 到底差在哪 如何用c# 做 mcp/ChatGPT app 春节期间浅试了 ai 视频生成 举个栗子:做个AI Gateway demo 2025个人总结 实现 json path 来评估函数式解析器的损耗 VKProxy 集成 OpenTelemetry c# ACME client (补充) c# ACME client 留个VKProxy性能测试记录 VKProxy新增一些功能 http流量镜像 VKProxy新增CORS设置和http响应缓存 VKProxy新增速率限制功能 VKProxy已提供命令行工具,镜像和简单的ui 已经在为VKProxy写UI配置站点和文档了 莫想到有一天得重新写个 etcd client 如何使用 websocket 完成 socks5 网络穿透 如何基于 Kestrel 实现 socks5 代理 记录一下 简单udp和sni 代理 done
终于写完轮子一部分:tcp代理 了,记录一下
victor.x.qu · 2025-03-08 · via 博客园 - victor.x.qu

24年终自己立了flag: 25年做些轮子玩(用于浪费生命,赚不了钱)
所以25年就准备用c#写一个网络代理NZOrz(nginx知道吧,就那玩意儿干的事),包含 udp/tcp/http1 2 3,
至于为啥不用rust写,主要由于某台电脑某些不可告知的原因不方便安装rust,所以等我写完c#的,后面有空再说吧(应该25年没时间了吧)

代码借鉴出处

秉承将生命浪费到底的造轮子精神,实力不行就尽可能借鉴(抄袭,读书人的事,怎么能说呢)
所以这里首先列举一下借鉴出处

  1. 借鉴 Kestrel 的 socket 处理核心 (理论上基于Kestrel也是可行的)
  2. 借鉴 Yarp 各项代理处理 (实现只有http)

所以整体实现上都是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 呢?毕竟借鉴代码也不易呀 哈哈哈哈哈