Yarp介绍

YARP是微软开源的用来代理服务器的反向代理组件,可实现的功能类似于nginx。

基于YARP,开发者可以非常快速的开发一个性能不错的小nginx,用于代理http(s)请求到上游的http(s)服务。

http穿透原理

同网现象

在http反向代理里,代理服务器总是上游服务的http客户端,为了网络性能,实际上上游服务总是和代理服务处在同一个局域网。试问一个问题:在公网的小nginx,如何把请求代理到局域网的http服务器?你会发现,小nginx做不到,因为小nginx所在公网服务器,无法直接与局域网的http服务器进行通信。

http穿透

在tcp里,进行连接时总是由客户端发起,但当连接之后客户端与服务端是平等的,他们之间可以双向收发数据。只要公网小nginx与局域网的http服务器存在tcp连接,我们可以使用这个连接做为httpClient的连接层,然后小nginx使用这个httpClient请求到局域网http服务器,而从达到http穿透效果。

完整流程

基于Yarp的http穿透

main连接

我们可以使用websocket协议,创建main连接,主要有以下好处:

  • 共享代理服务器监听的http(s)端口
  • 利用websocket的ping-pong实现连接检测
  • 利用websocket连接请求头进行身份认证

接收局域网创建的连接

我们可以为kestrel编写中间件,用获取获取局域网主动创建的tcp连接,这些连接与代理服务器与浏览器之间的连接共享同一个服务器端口,以下的listen.Use(transportService.OnConnectedAsync);是一个kestrel中间件。

public static IWebHostBuilder UseKestrelTransportChannel(this IWebHostBuilder hostBuilder)
{
return hostBuilder.UseKestrel(kestrel =>
{
var transportService = kestrel.ApplicationServices.GetRequiredService<TransportChannelService>();
var options = kestrel.ApplicationServices.GetRequiredService<IOptions<HttpMouseOptions>>().Value; var http = options.Listen.Http;
if (http != null)
{
kestrel.Listen(http.IPAddress, http.Port, listen =>
{
listen.Use(transportService.OnConnectedAsync);
});
} var https = options.Listen.Https;
if (https != null && File.Exists(https.Certificate.Path))
{
kestrel.Listen(https.IPAddress, https.Port, listen =>
{
listen.Protocols = HttpProtocols.Http1AndHttp2;
listen.UseHttps(https.Certificate.Path, https.Certificate.Password);
listen.Use(transportService.OnConnectedAsync);
});
}
});
}

绑定连接到HttpClient

Yarp进行代理时,需要指定HttpMessageInvoker,HttpMessageInvoker实际是SocketsHttpHandler的包装。而SocketsHttpHandler可以设置ConnectCallback属性,用于指定连接。

private static HttpMessageInvoker CreateHttpClient(TransportChannelService transportChannelService)
{
return new HttpMessageInvoker(new SocketsHttpHandler()
{
UseProxy = false,
UseCookies = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
ConnectCallback = transportChannelService.CreateChannelAsync,
SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = delegate { return true; }
}
});
}

Yarp直接转发

使用直接转发中间件

/// <summary>
/// 配置中间件
/// </summary>
/// <param name="app"></param>
/// <param name="connectionService"></param>
/// <param name="httpForwarderService"></param>
public void Configure(IApplicationBuilder app, IHostEnvironment hostEnvironment, ConnectionService connectionService, HttpForwarderService httpForwarderService)
{
app.UseWebSockets();
app.Use(connectionService.OnConnectedAsync);
app.Use(httpForwarderService.SendAsync);
}

通过请求的域名,找到局域网要转发的最终服务器地址,做为yarp的请求地址。

/// <summary>
/// 发送http数据
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public async Task SendAsync(HttpContext httpContext, Func<Task> next)
{
var clientDomain = httpContext.Request.Host.Host;
if (this.connectionService.TryGetClientUpStream(clientDomain, out var clientUpstream))
{
var destPrefix = clientUpstream.ToString();
if (this.options.CurrentValue.HttpRequest.TryGetValue(clientDomain, out var requestConfig) == false)
{
requestConfig = this.defaultRequestConfig;
}
await this.httpForwarder.SendAsync(httpContext, destPrefix, httpClient, requestConfig, this.transformer);
}
}

总结

基于kestrel和SocketsHttpHandler高度可定制化的扩展能力,结合Yarp组件,我们可以很方便的开发一个支持内网http穿透的公网http反向代理服务器。如果把泛域名指向公网反向代理服务器,最终实现一个二级域名绑定流量到一个局域网http服务器的一对多功能。

基于Yarp实现内网http穿透的更多相关文章

  1. 基于frp的内网穿透实例4-为本地的web服务实现HTTPS访问

    原文地址:https://wuter.cn/1932.html/ 一.想要实现的功能 目前已经实现将本地的web服务暴露到公网,现想要实现https访问.(前提:已经有相应的证书文件,如果没有就去申请 ...

  2. 后渗透阶段之基于MSF的内网主机探测

    当我们通过代理可以进入某内网,需要对内网主机的服务进行探测.我们就可以使用MSF里面的内网主机探测模块了. 在这之前,先修改 /etc/proxychains.conf ,加入我们的代理. 然后 pr ...

  3. 基于C#的内网穿透学习笔记(附源码)

    如何让两台处在不同内网的主机直接互连?你需要内网穿透!          上图是一个非完整版内外网通讯图由内网端先发起,内网设备192.168.1.2:6677发送数据到外网时候必须经过nat会转换成 ...

  4. 基于frp的内网穿透实例1-通过SSH访问内网机器

    原文地址:https://wuter.cn/1804.html/ 老母鸡终于到了,作为一个能运行linux系统的四核1G硬件,它还是比较小巧的. FRP 全名:Fast Reverse Proxy.F ...

  5. 内网ssh穿透

    公司服务器没有公网IP,只有内网IP,利用自己的阿里云服务器(有公网ip)做ssh内网穿透,使得外网可访问.方法如下: 环境: 公司服务器和阿里云服务器均为 Ubuntu 操作系统, 需要修改阿里云服 ...

  6. 搭建基于HTTP协议内网yum仓库

    目录 1. 前言 2. 把rpm包下载到本地 3. 配置nginx对外提供服务 4. 配置本地repo文件 5. 生成repodata信息 6. 检查及使用 7. 对管理机器上的仓库进行更新 参考资料 ...

  7. 使用frp工具实现内网的穿透以及配置多个ssh和web服务

    frp简介 FRP 项目地址 https://github.com/fatedier/frp/blob/master/README_zh.md frp 是一个可用于内网穿透的高性能的反向代理应用,支持 ...

  8. LanProxy 内网映射穿透

    前言:用过 ngrok 的人都知道,这是一个免费并且简便的内网映射工具,可是现在ngrok不知道弄啥?不能用了,那我们只能去找一些新的工具,下面是我跟我朋友一起弄的(主要是他教我(✪ω✪)),免费的, ...

  9. 基于frp的内网穿透实例2-通过自定义域名访问部署于内网的 web 服务

    原文地址:https://wuter.cn/1837.html/ 一.想要实现的功能 1.将部署在自己电脑上的网站用于公网访问. 2.将未备案域名解析至国内服务器(即我宿舍的老母鸡上). 二.服务端配 ...

随机推荐

  1. 怎样使用yum-cron为CentOS7自动更新重要的安全补丁

    怎样使用yum-cron为CentOS自动更新重要的安全补丁 2017年4月19日 | 分类: [技术] 参考:https://linux.die.net/man/8/yum-cron参考:http: ...

  2. centos7.0修改网卡名为ethx

    场景: 由于默认的centos7网卡名对于大多数习惯于原先的命名方式的人而言是一种折磨,因此我们需要让他恢复正常! 编辑/etc/sysconfig/grub文件 vim /etc/sysconfig ...

  3. Java 关键字详解

    Java 关键字是 Java 语言中被赋予特殊意义的一些单词(每个关键字都代表着不同场景下的不同含义),不可以把它当作标识符来使用(不能用作变量名.方法名.类名.包名和参数名等).Java 中的关键字 ...

  4. 5.1-5 uname、hostname、dmesg、stat、du

    5.1 uname:显示系统信息     uname命令用于显示系统相关信息,比如内核版本号.硬件架构等. -a    显示系统所有相关信息 -v    显示内核版本 -m    显示计算机硬件架构 ...

  5. [leetcode] 117. 填充同一层的兄弟节点 II

    117. 填充同一层的兄弟节点 II 与116. 填充同一层的兄弟节点完全一样,二叉树的层次遍历..这是这次不是完美二叉树了 class Solution { public void connect( ...

  6. gin使用validator库参数校验若干实用技巧

    validator库参数校验若干实用技巧 本文介绍了使用validator库做参数校验的一些十分实用的使用技巧,包括翻译校验错误提示信息.自定义提示信息的字段名称.自定义校验方法等. validato ...

  7. Fiddler抓包后转成jmeter脚本

    Fiddler的安装及使用 1.安装:无特别需要注意事项 2.使用: (1)目前我使用的是Fiddler 4版本,打开页面如下 (2)如下图,在界面右侧找到Filters tabs,根据需要进行设置, ...

  8. 人脸真伪验证与识别:ICCV2019论文解析

    人脸真伪验证与识别:ICCV2019论文解析 Face Forensics++: Learning to Detect Manipulated Facial Images 论文链接: http://o ...

  9. 【.NET 与树莓派】温度/湿度传感器——SHT30

    SHT3XX 系列的传感,常见的有三种:SHT 30.SHT 31.SHT 35.其中,比较便宜性价比较愉快的是 SHT 30. DHT 11 模块也是检测温度.湿度的,但SHT 11 使用的不是我们 ...

  10. Django(56)Mixins工具集的使用

    前言 mixins翻译成中文是混入,组件的意思.在DRF中,针对获取列表,检索,创建等操作,都有相应的mixin,一般我们自定义创建的类视图都会继承自GenericAPIView和Mixins一起使用 ...