• http内网穿透CYarp[开源]


    0 前言#

    在物联网领域中,mqtt消息一直是海量设备连接到平台的标配协议,而平台向移动端开放的操作接口往往是http协议,这就要求平台为两种协议作消息一一适配。在某些情况下,这些设备是有操作系统的linux或安卓设备,如果我们换个思路,让这些设备直接提供http协议的操作接口(httpd服务器),平台端使用隧道打通设备与移动端的传输层,做为平台开发人员,就可以省去时间做这些繁琐的消息级别的一一适配工作了。

    1 面临的问题#

    1.1 海量连接#

    mqtt默认基于tcp传输,一台设备与平台维持一个tcp连接即可高效的上下并行传输消息。而http/1.1在协议层限制了单个连接串行请求响应,但我们可以使用http/2.0或http/3.0做为http/1.1的传输层,也能达到一个物理链接多路传输http/1.1的目的。这样下来内网http/1.1穿透也和mqtt一样,只需要一个物理长连接。

    1.2 身份认证#

    我尝试使用frp来承载物联网设备的http内网穿透,但至今还没成功完成海量设备的一机一密的身份认证,它里面的token认证方式只适合一平台对一个设备的安全要求,而OIDC验证我至今仍然看不明白怎么使用。对于一款内网穿透组件或应用,能像asp.netcore的身份验证强大,对平台端而言是非常需要的。

    1.3 安全传输#

    设备内置的http服务器,一般都是没有https,因为它本身就不考虑公网传输的能力。但在内网穿透之后,我们必须要考虑设备到公网平台这段的传输安全。

    1.4 开放协议#

    内网穿透组件涉及到平台的服务端和集成在设备里的客户端库,平台端一般只有二次开发的需求。而设备端由于芯片、系统和指令集、内存限制等等因素,只提供客户端库或二进制可执行文件是不够的,还可能需要客户端开发者根据交互协议来自行开发客户端组件。这就要求内网穿透组件提供客户端与服务端的交互协议,且最好是设计为非常简单的协议。

    2 CYarp出场#

    CYarp基于Yarp的http内网穿透中间件,支持tcp、http/2.0或http/3.0作为http/1.1的传输层,其具有以下特征

    1. 是一个标准的asp.netcore中间件
    2. 能完整使用asp.netcore框架和其它中间件
    3. 使用服务端的tls(https)做为安全传输层
    4. 单连接多路复用,无需客户端提供http2服务器
    5. 协议透明简单,参考了WebSocket升级和Bootstrapping WebSockets with HTTP/2

    2.1 服务端开发#

    CYarp中间件其依赖于Authentication身份认证中间件,使用如下方法进行注册和中间件的配置。

    Copy
    builder.Services.AddCYarp(cyarp=> { ... });

    中间件配置顺序如下:

    Copy
    ... app.UseAuthentication(); ... app.UseCYarp(); ...

    最后在Controller、minapi的处理者或中间件中处理http转发

    Copy
    // 请求者的授权验证 [Authorize(Roles = "Mobile")] public class CYarpController : ControllerBase { private static readonly string clientIdClaimType = "ClientId"; /// /// 处理cyarp /// 核心操作是从请求上下文获取clientId /// 然后使用clientId从clientManager获取client来转发http /// /// /// [Route("/{**cyarp}")] public async Task InvokeAsync([FromServices] IClientManager clientManager) { var clientId = this.User.FindFirstValue(clientIdClaimType); if (clientId != null && clientManager.TryGetValue(clientId, out var client)) { this.Request.Headers.Remove(HeaderNames.Authorization); await client.ForwardHttpAsync(this.HttpContext); } else { this.Response.StatusCode = StatusCodes.Status502BadGateway; } } }

    2.2 客户端开发#

    使用CYary.Client.CYarpClient很方便完成客户端开发

    Copy
    using var client = new CYarpClient(); while (true)) { await client.TransportAsync(this.clientOptions.CurrentValue, stoppingToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); }

    2.3 客户端协议#

    由于篇幅有限,不在这里展开,可以查阅CYarp握手协议

    3 同源产品#

    Yarp是dotnet平台下堪比nginx的一个组件,其它融入asp.netcore框架作为里面的中间件共享asp.netcore生态。

    davidfowl大神也曾经小手一挥造就了YarpTunnelDemo项目,也是实现了http内网穿透的能力。但是他的实现方案要求客户端方能要运行asp.netcore监听做为客户端组件,由于asp.netcore的runtime只适配了桌面系统,且编译出的二进制文件很大,此方法自然无法在物联网设备中运行了。

  • 相关阅读:
    学习笔记:机器学习之支持向量机(六、非线性支持向量机与核函数引入)
    Promise的异步调用
    iTOP-RK3399开发板驱动模块传数组
    【潮流计算】基于matlab粒子群算法优化电力系统潮流计算【含Matlab源码 2157期】
    猿创征文|【云原生之Docker】使用Docker部署Flare个人导航网页
    Pyecharts绘图笔记
    python基础05 循环 变量 函数组合案例
    InnoDB数据页结构(3)之记录头信息分析
    倒计时9天|Zabbix中国峰会15位重磅嘉宾抢先看!
    Java Heap Space问题解析与解决方案(InsCode AI 创作助手)
  • 原文地址:https://www.cnblogs.com/kewei/p/18084123