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

推荐订阅源

N
News and Events Feed by Topic
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs
博客园 - 叶小钗
P
Privacy International News Feed
Jina AI
Jina AI
Apple Machine Learning Research
Apple Machine Learning Research
T
Threatpost
IT之家
IT之家
博客园 - 聂微东
Know Your Adversary
Know Your Adversary
Help Net Security
Help Net Security
罗磊的独立博客
I
Intezer
S
Schneier on Security
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
Cisco Talos Blog
Cisco Talos Blog
宝玉的分享
宝玉的分享
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Webroot Blog
Webroot Blog
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
P
Privacy & Cybersecurity Law Blog
T
The Exploit Database - CXSecurity.com
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
H
Heimdal Security Blog
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
Y
Y Combinator Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Microsoft Security Blog
Microsoft Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
SecWiki News
SecWiki News
The GitHub Blog
The GitHub Blog
A
Arctic Wolf
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
Engineering at Meta
Engineering at Meta
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

博客园 - 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配置站点和文档了 莫想到有一天得重新写个 etcd client 如何使用 websocket 完成 socks5 网络穿透 如何基于 Kestrel 实现 socks5 代理 记录一下 简单udp和sni 代理 done 终于写完轮子一部分:tcp代理 了,记录一下
VKProxy已提供命令行工具,镜像和简单的ui
victor.x.qu · 2025-06-14 · via 博客园 - victor.x.qu

VKProxy 是使用c#开发的基于 Kestrel 实现 L4/L7的代理

经过6个月业余时间偶尔缝缝补补,已经达到能跑的地步了 (感兴趣的同学烦请点个github小赞赞呢)

相关使用写了一些简单的文档说明

这里列举一下新增的安装使用方式

提供简单的命令行工具,可以在本地进行相关测试

dotnet tool install --global VKProxy.Cli

不过目前只支持 net9.0 (net10 正式发布后会切换制net10)

安装后可以使用如下命令

vkproxy -h
// it will output
--config (-c)       json file config, like /xx/app.json
--socks5            use simple socks5 support
--etcd              etcd address, like http://127.0.0.1:2379
--etcd-prefix       default is /ReverseProxy/
--etcd-delay        delay change config when etcd change, default is 00:00:01
--help (-h)         show all options
View more at https://fs7744.github.io/VKProxy.Doc/docs/introduction.html

如果使用json文件配置

配置项很多,可参考后续具体配置项说明

这里举个例子

创建json文件

{
  "ReverseProxy": {
    "Listen": {
      "http": {
        "Protocols": [
          "Http1"
        ],
        "Address": [
          "127.0.0.1:5001"
        ]
      }
    },
    "Routes": {
      "HTTPTEST": {
        "Match": {
          "Hosts": [
            "*com"
          ],
          "Paths": [
            "/ws*"
          ],
          "Statement": "Method = 'GET'"
        },
        "ClusterId": "apidemo",
        "Timeout": "00:10:11"
      }
    },
    "Clusters": {
      "apidemo": {
        "LoadBalancingPolicy": "RoundRobin",
        "HealthCheck": {
          "Active": {
            "Enable": true,
            "Policy": "Http",
            "Path": "/test",
            "Query": "?a=d",
            "Method": "post"
          }
        },
        "Destinations": [
          {
            "Address": "http://127.0.0.1:1104"
          },
          {
            "Address": "https://google.com"
          }
        ]
      }
    }
  }
}

然后启动

vkproxy -c D:\code\test\proxy\config.json

// 启动后会看到类似如下的内容
info: VKProxy.Server.ReverseProxy[3]
      Listening on: [Key: http,Protocols: HTTP1,EndPoint: 127.0.0.1:5001]
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\test\proxy
warn: VKProxy.Server.ReverseProxy[5]
      Active health failed, can not connect socket 127.0.0.1:1104 No connection could be made because the target machine actively refused it. (127.0.0.1:1104).

使用 etcd 配置

在多实例的情况,同一份配置分发就比较麻烦, 这里提供 ui 可以配置etcd + agent 从etcd读取配置 方便大家使用

ui使用可以参考 UI配置站点

用tool 启动 agent 可以这样使用

vkproxy --etcd http://127.0.0.1:2379 --etcd-prefix /ReverseProxy/

// 启动后会看到类似如下的内容
info: VKProxy.Server.ReverseProxy[3]
      Listening on: [Key: http,Protocols: HTTP1,EndPoint: 127.0.0.1:5001]
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\test\proxy
warn: VKProxy.Server.ReverseProxy[5]
      Active health failed, can not connect socket 127.0.0.1:1104 No connection could be made because the target machine actively refused it. (127.0.0.1:1104).

Docker

当大家基本代理功能足够时,简化大家使用成本/快速构建的默认已构建镜像

所有的镜像可以在 docker hub vkproxy agent 找到

提供如下环境变量

  • VKPROXY_CONFIG

    json file config, like /xx/app.json

    example VKPROXY_CONFIG=/xx/app.json

  • VKPROXY_SOCKS5

    use simple socks5 support

    example VKPROXY_SOCKS5=true

  • ETCD_CONNECTION_STRING

    etcd address, like http://127.0.0.1:2379

    example ETCD_CONNECTION_STRING=http://127.0.0.1:2379

  • ETCD_PREFIX

    default is /ReverseProxy/

    example ETCD_PREFIX=/ReverseProxy/

  • ETCD_DELAY

    delay change config when etcd change, default is 00:00:01

    example ETCD_DELAY=00:00:01

如果使用json文件配置

配置项很多,可参考后续具体配置项说明

这里举个例子

创建json文件

{
  "ReverseProxy": {
    "Listen": {
      "http": {
        "Protocols": [
          "Http1"
        ],
        "Address": [
          "127.0.0.1:5001"
        ]
      }
    },
    "Routes": {
      "HTTPTEST": {
        "Match": {
          "Hosts": [
            "*com"
          ],
          "Paths": [
            "/ws*"
          ],
          "Statement": "Method = 'GET'"
        },
        "ClusterId": "apidemo",
        "Timeout": "00:10:11"
      }
    },
    "Clusters": {
      "apidemo": {
        "LoadBalancingPolicy": "RoundRobin",
        "HealthCheck": {
          "Active": {
            "Enable": true,
            "Policy": "Http",
            "Path": "/test",
            "Query": "?a=d",
            "Method": "post"
          }
        },
        "Destinations": [
          {
            "Address": "http://127.0.0.1:1104"
          },
          {
            "Address": "https://google.com"
          }
        ]
      }
    }
  }
}

然后启动

docker run --rm -v /mnt/d/code/test/proxy:/config -e VKPROXY_CONFIG=/config/config
.json -e ETCD_CONNECTION_STRING= --network host a.newegg.org/docker-hub-remote/vkproxy/agent:0.0.0.6

// 启动后会看到类似如下的内容
info: VKProxy.Server.ReverseProxy[3]
      Listening on: [Key: http,Protocols: HTTP1,EndPoint: 127.0.0.1:5001]
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: /app
warn: VKProxy.Server.ReverseProxy[5]
      Active health failed, can not connect socket [2404:6800:4012:7::200e]:443 Network is unreachable ([2404:6800:4012:7::200e]:443).
warn: VKProxy.Server.ReverseProxy[5]
      Active health failed, can not connect socket 127.0.0.1:1104 Connection refused (127.0.0.1:1104).

使用 etcd 配置

在多实例的情况,同一份配置分发就比较麻烦, 这里提供 ui 可以配置etcd + agent 从etcd读取配置 方便大家使用

ui使用可以参考 UI配置站点

用 docker 启动 agent 可以这样使用

docker run --rm -e ETCD_CONNECTION_STRING=http://127.0.0.1:2379 --network host vkproxy/agent:0.0.0.6

// 启动后会看到类似如下的内容
info: VKProxy.Server.ReverseProxy[3]
      Listening on: [Key: http,Protocols: HTTP1,EndPoint: 127.0.0.1:5001]
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\test\proxy
warn: VKProxy.Server.ReverseProxy[5]
      Active health failed, can not connect socket 127.0.0.1:1104 No connection could be made because the target machine actively refused it. (127.0.0.1:1104).

通过UI站点配置

由于文件配置存在一定使用难度,所以也有提供简单的 ui配置站点VKProxy.Web

[!WARNING]
由于文件分发会导致大家部署多实例的难度,所以 ui 站点目前只支持 etcd 作为配置源, 同时服务器参数相关无法通过ui站点配置, 请使用文件会程序配置 参见服务器参数

首先启动一个 etcd (可参考 Run etcd clusters inside containers)

export NODE1=127.0.0.1

ETCD_VERSION=v3.4.37
REGISTRY=quay.io/coreos/etcd
# available from v3.2.5
REGISTRY=gcr.io/etcd-development/etcd

docker run \
  -p 2379:2379 \
  -p 2380:2380 \
  --volume=${DATA_DIR}:/etcd-data \
  --name etcd ${REGISTRY}:${ETCD_VERSION} \
  /usr/local/bin/etcd \
  --data-dir=/etcd-data --name node1 \
  --initial-advertise-peer-urls http://${NODE1}:2380 --listen-peer-urls http://0.0.0.0:2380 \
  --advertise-client-urls http://${NODE1}:2379 --listen-client-urls http://0.0.0.0:2379 \
  --initial-cluster node1=http://${NODE1}:2380

VKProxy agent 启动参考 安装

UI 所有的镜像可以在 docker hub vkproxy ui 找到

UI docker 部署

参数可以使用如下

  • ETCD_CONNECTION_STRING

    etcd address, like http://127.0.0.1:2379

    example ETCD_CONNECTION_STRING=http://127.0.0.1:2379

  • ETCD_PREFIX

    default is /ReverseProxy/

    example ETCD_PREFIX=/ReverseProxy/

  • ASPNETCORE_URLS

    example ASPNETCORE_URLS=http://*:80

举例:

docker run --rm -e ETCD_CONNECTION_STRING=http://127.0.0.1:2379 -e ASPNETCORE_URLS=http://*:8770 --network host vkproxy/ui:0.0.0.7

// 启动后会看到类似输出
warn: Microsoft.AspNetCore.Hosting.Diagnostics[15]
      Overriding HTTP_PORTS '8080' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'http://*:8770'.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:8770
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: /app

然后你就可以在浏览器 访问 http://127.0.0.1:8770 使用 UI 了

webui.jpg

定制化扩展

为了方便大家使用 KVProxy 在一些场景,默认功能无法满足时,可以通过自定义扩展实现自己的需求。

同时也是遵照 asp.net core 设计理念,提供了两种扩展方式

中间件管道

中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在管道中的下一个组件前后执行工作。

请求委托用于生成请求管道。 请求委托处理每个 HTTP/tcp/udp 请求。

具体概念可参考ASP.NET Core 中间件

KVProxy 添加了 udp 和 tcp 的特殊中间件

具体参见如何通过中间件定制化功能

还有一个socks5的示例以供大家参考如何利用中间件扩展实现socks5

特定功能策略增加

有些特定功能策略比较难以直接使用中间件扩展,这里列举主要部分

(其实由于基于依赖注入,天生解耦,所以内部实现基本都可以覆盖或者添加新实现)

ReverseProxyFeature

除了两大扩展方式之外,还有一个接口数据在运行时有表明当前路由匹配情况

public interface IReverseProxyFeature  // http 路由会使用该接口
{
    public RouteConfig Route { get; set; } // 匹配上的路由,如为 null 则未匹配任何路由
    public DestinationState? SelectedDestination { get; set; } // 在选中健康的目标地址后,对应配置会设置在这里
}

public interface IL4ReverseProxyFeature : IReverseProxyFeature // tcp / udp 路由会使用该接口
{
    public bool IsDone { get; set; }  // 表明是否已经处理,当为 true 时,KVProxy 内置L4代理将不会进行代理
    public bool IsSni { get; set; }   // 表明是否为 tcp sni 代理模式
    public SniConfig? SelectedSni { get; set; }  // 为 tcp sni 代理模式时的配置
}

运行时可通过 feature 获取, 比如

// http
internal class EchoHttpMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var f = context.Features.Get<IReverseProxyFeature>();
    }
}

//tcp
internal class EchoTcpProxyMiddleware : ITcpProxyMiddleware
{
    public Task InitAsync(ConnectionContext context, CancellationToken token, TcpDelegate next)
    {
        var f = context.Features.Get<IL4ReverseProxyFeature>();
    }

    public Task<ReadOnlyMemory<byte>> OnRequestAsync(ConnectionContext context, ReadOnlyMemory<byte> source, CancellationToken token, TcpProxyDelegate next)
    {
        var f = context.Features.Get<IL4ReverseProxyFeature>();
    }

    public Task<ReadOnlyMemory<byte>> OnResponseAsync(ConnectionContext context, ReadOnlyMemory<byte> source, CancellationToken token, TcpProxyDelegate next)
    {
        logger.LogInformation($"tcp {DateTime.Now} {context.Features.Get<IL4ReverseProxyFeature>()?.SelectedDestination?.EndPoint.ToString()} reponse size: {source.Length}");
    }
}

//udp
internal class EchoUdpProxyMiddleware : IUdpProxyMiddleware
{
    public Task InitAsync(UdpConnectionContext context, CancellationToken token, UdpDelegate next)
    {
        var f = context.Features.Get<IL4ReverseProxyFeature>();
    }

    public Task<ReadOnlyMemory<byte>> OnRequestAsync(UdpConnectionContext context, ReadOnlyMemory<byte> source, CancellationToken token, UdpProxyDelegate next)
    {
        var f = context.Features.Get<IL4ReverseProxyFeature>();
    }

    public Task<ReadOnlyMemory<byte>> OnResponseAsync(UdpConnectionContext context, ReadOnlyMemory<byte> source, CancellationToken token, UdpProxyDelegate next)
    {
        logger.LogInformation($"udp {DateTime.Now} {context.Features.Get<IL4ReverseProxyFeature>()?.SelectedDestination?.EndPoint.ToString()} reponse size: {source.Length}");
    }
}

不建议大家直接修改 IReverseProxyFeature 的值,可能会破坏路由

可扩展套接字应用程序框架

除了代理功能外,由于通过反射释放了Kestrel的能力,你也可以把 VKProxy 当成可扩展套接字应用程序框架使用

使用它轻松构建始终连接的套接字应用程序,而无需考虑如何使用套接字,如何维护套接字连接以及套接字如何工作。

(在Kestrel基础上开发,理论可以帮大家节省一些比如直接socket要自己管理 socket之类的事情)

具体可以参考可扩展套接字应用程序框架

2025年后续大概就继续添加限流 追踪啊之类功能吧