搜索

查看: 3079|回复: 11

[ASP.NET] .Net反向代理组件Yarp用法详解

[复制链接]
发表于 2023-5-4 11:30:53 | 显示全部楼层 |阅读模式
Editor 2023-5-4 11:30:53 3079 11 看全部
目录
  • 简介
  • 基础使用
  • 1、创建 ASP.NET Core 空项目
  • 2、 修改代码 Program.cs 文件
  • 3、修改配置文件 appsettings.json
  • 4、启动项目
  • 5、问题整理
  • 进阶探索
  • 1、多地址代理
  • 2、规则匹配
  • 3、问题整理
  • 小试牛刀
  • 踩坑集锦
  • 1、non-ASCII
    简介
    Yarp 是微软团队开发的一个反向代理组件, 除了常规的 http 和 https 转换通讯,它最大的特点是可定制化,很容易根据特定场景开发出需要的定制代理通道。
    详细介绍:https://devblogs.microsoft.com/dotnet/announcing-yarp-1-0-release
    源码仓库:https://github.com/microsoft/reverse-proxy
    文档地址 :https://microsoft.github.io/reverse-proxy/

    基础使用
    1、创建 ASP.NET Core 空项目
    使用 Visual Studio :

    2022092411425438.png

    2022092411425438.png


    使用 .NET CLI 命令行创建:
    dotnet new web -o MyProxy
    2、 修改代码 Program.cs 文件
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddReverseProxy()
        .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
    var app = builder.Build();
    app.MapGet("/Ping", () => "Hello World!");
    app.MapReverseProxy();
    app.Run();
    3、修改配置文件 appsettings.json
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "ReverseProxy": {
        "Routes": {
          "routeAll": {
            "ClusterId": "clusterBaidu",
            "Match": {
              "Path": "{**catch-all}"
            }
          }
        },
        "Clusters": {
          "clusterBaidu": {
            "Destinations": {
              "baidu": {
                "Address": "https://www.baidu.com/"
              }
            }
          }
        }
      }
    }
    这里的配置是将所有的请求都转发到百度。
    在 Program.cs 里,还注册了一个 Get 路由 Ping 。

    4、启动项目

    2022092411425439.png

    2022092411425439.png


    能够看到在浏览器访问程序监听的端口号后,显示的是百度的页面。打开 F12 ,看到请求头也是本地的,并不是百度的域名。
    测试手动注册的路由 Ping :

    2022092411425440.png

    2022092411425440.png


    能够显示正常。

    5、问题整理
  • (1) Yarp 是不是只能做这种简单的转发?
    不是,往下有配置文件说明。
  • (2) JSON 配置文件里有什么要注意的地方吗?
    有。在这个演示的配置文件中 ReverseProxy:Clusters:cluster1:Destinations:destination1:Address 对应的值是:https://www.baidu.com/ ,如果去掉 www ,在项目启动后会跳转到百度首页,不是代理转发。去掉末尾的 / 符合没有任何影响。
  • (3) Yarp 会影响到程序中注册的路由吗?
    不会影响到程序内部注册的路由。在 Program.cs 中无论 app.MapReverseProxy(); 在上还是在下,在访问 Ping 的时候,都是返回 Hello World!
    var app = builder.Build();
    app.MapReverseProxy();
    app.MapGet("/Ping", () => "Hello World!");
    app.Run();
    进阶探索
    1、多地址代理
    修改配置文件 appsettings.json ,实现默认路由跳转百度,当访问 /movie 是访问 b站。
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "ReverseProxy": {
        "Routes": {
          "routeBaidu": {
            "ClusterId": "clusterBaidu",
            "Match": {
              "Path": "{**catch-all}"
            }
          },
          "routeBiliBili": {
            "ClusterId": "clusterBiliBili",
            "Match": {
              "Path": "/movie/{**catch-all}"
            }
          }
        },
        "Clusters": {
          "clusterBaidu": {
            "Destinations": {
              "baidu": {
                "Address": "https://www.baidu.com/"
              }
            }
          },
          "clusterBiliBili": {
            "Destinations": {
              "bilibili": {
                "Address": "https://www.bilibili.com/"
              }
            }
          }
        }
      }
    }
    测试结果:

    2022092411425441.png

    2022092411425441.png


    2022092411425442.png

    2022092411425442.png


    在后面输入路由 /movie 后能够跳转到b站。但是b站网页没有完整显示,图片都没有,这是网站上的策略问题,对于数据接口没有这些问题。

    2022092411425443.png

    2022092411425443.png


    详细的配置文件说明,可以查看 https://microsoft.github.io/reverse-proxy/articles/config-files.html

    2、规则匹配
    网页上太多资源,为了方便测试,启用两个 api 接口。地址分别是:http://localhost:5241/ 和 https://localhost:7184/
    两个 api 接口中分别注册 /test 路由。
    // http://localhost:5241/
    app.MapGet("/test", () => "Welcome to Api111!");
    // https://localhost:7184/
    app.MapGet("/test", () => "Welcome to Api222!");
    启动两个 api 程序。
    C:\Users\Test>curl http://localhost:5241/test
    Welcome to Api111!
    C:\Users\Test>curl https://localhost:7184/test
    Welcome to Api222!
    修改 MyProxy 项目的配置文件 appsettings.json
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "ReverseProxy": {
        "Routes": {
          "routeOne": {
            "ClusterId": "clusterOne",
            "Match": {
              "Path": "/test/{**catch-all}",
              "QueryParameters": [
                {
                  "Name": "number",
                  "Values": [ "1" ]
                }
              ]
            }
          },
          "routeTwo": {
            "ClusterId": "clusterTwo",
            "Match": {
              "Path": "/test/{**catch-all}",
              "QueryParameters": [
                {
                  "Name": "number",
                  "Values": [ "2" ]
                }
              ]
            }
          },
          "routeBaidu": {
            "ClusterId": "clusterBaidu",
            "Match": {
              "Path": "{**catch-all}"
            }
          }
        },
        "Clusters": {
          "clusterOne": {
            "Destinations": {
              "apiOne": {
                "Address": "http://localhost:5241/"
              }
            }
          },
          "clusterTwo": {
            "Destinations": {
              "apiTwo": {
                "Address": "https://localhost:7184/"
              }
            }
          },
          "clusterBaidu": {
            "Destinations": {
              "baidu": {
                "Address": "https://www.baidu.com/"
              }
            }
          }
        }
      }
    }
  • Path :监听路由地址。
  • QueryParameters:匹配参数。
  • QueryParameters:Name:参数名。
  • QueryParameters:Values:参数值。
    MyProxy 的监听端口是 http://localhost:5024/ 访问结果如下:
    C:\Users\Test>curl http://localhost:5024/ping
    Hello World!
    C:\Users\Test>curl http://localhost:5024/test

    404 Not Found

    Not Found
    The requested URL /test was not found on this server.

    C:\Users\Test>curl http://localhost:5024/test?number=1
    Welcome to Api111!
    C:\Users\Test>curl http://localhost:5024/test?number=2
    Welcome to Api222!
    能够根据参数以及参数值导向对应的地址。

    3、问题整理
  • (1)为什么访问 /movie 不能正常显示网页。
    因为 b站某些接口开启了防盗链,还有跨域检测。

    2022092411425444.png

    2022092411425444.png


    2022092411425445.png

    2022092411425445.png


  • (2)在根据参数匹配中,如果匹配的路由一样,监听的参数一样,参数值也一样会怎么样?
    访问该路由地址会报错。
  • (3)路由匹配的优先级?
    程序内注册的路由优先级最高,其次才是 Yarp 在配置文件里加载的。

    小试牛刀
    最近的工作是做企业内数据安全方面的。推动公司数据安全体系,通过技术手段提升公司信息安全。
    有一个很老的OA系统,十几年了, .NET Framework 2.0 写的。漏洞一大堆,包括不限于xss、sql注入等,权限只到表单级别。浏览器上按下 F12 能查看到表单链接,直接复制出去,别人也能访问。
    在这个系统上要做安全,我想的是在中间加代理,正好适合使用 Yarp 来完成,也方便写业务处理代码。嗯,很真实, .NET Core 写的,方便写业务代码。
    用户登录成功后,会记录下用户的 Host 和 Cookie,每次访问的时候系统的时候,在 Yarp 这里都校验一下是否与用户登录时的匹配。
    解决了两个问题:
    1、从网络层捕获到所有的请求,方便后面做排查。参数、传值,出了事故可以找到责任人。
    2、隔离真实的站点地址,杜绝弱安全等级网站暴露后被坏人攻击的风险。

    2022092411425446.png

    2022092411425446.png


    踩坑集锦
    1、non-ASCII
    项目要代理某网页,在使用下载功能的时候,接口返回 502 。
    info: Yarp.ReverseProxy.Forwarder.HttpForwarder[48]
          ResponseHeaders: The destination returned a response that cannot be proxied back to the client.
          System.InvalidOperationException: Invalid non-ASCII or control character in header: 0x00E4
             at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowInvalidHeaderCharacter(Char ch)
             at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ValidateHeaderValueCharacters(StringValues headerValues)
             at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseHeaders.SetValueFast(String key, StringValues value)
             at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(String key, StringValues value)
             at Yarp.ReverseProxy.Forwarder.HttpTransformer.CopyResponseHeaders(HttpHeaders source, IHeaderDictionary destination)
             at Yarp.ReverseProxy.Forwarder.HttpTransformer.TransformResponseAsync(HttpContext httpContext, HttpResponseMessage proxyResponse)
             at Yarp.ReverseProxy.Transforms.Builder.StructuredTransformer.TransformResponseAsync(HttpContext httpContext, HttpResponseMessage proxyResponse)
             at Yarp.ReverseProxy.Forwarder.HttpForwarder.SendAsync(HttpContext context, String destinationPrefix, HttpMessageInvoker httpClient, ForwarderRequestConfig requestConfig, HttpTransformer transformer)
    去 GitHub 翻 Issues

    2022092411425547.png

    2022092411425547.png


    下载接口能正常访问,文件流也能完整地拿到。重写了所有的响应头没有用。这种不开源的商业站点,也猜不到字符编码。
    最后妥协了,用了一个 .NET 服务在服务器上下载后再转发。
    代理非常规服务接口时,一定要多测试。
    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对知鸟论坛的支持。如果你想了解更多相关内容请查看下面相关链接
  • 回复

    使用道具 举报

    发表于 2023-6-28 19:52:54 | 显示全部楼层
    胡37 2023-6-28 19:52:54 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    回复

    使用道具 举报

    发表于 2023-6-29 01:19:53 | 显示全部楼层
    计划你大爷计j 2023-6-29 01:19:53 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    发表于 2023-6-29 14:40:07 | 显示全部楼层
    素色流年783 2023-6-29 14:40:07 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-29 15:47:38 | 显示全部楼层
    123456848 2023-6-29 15:47:38 看全部
    我看不错噢 谢谢楼主!知鸟论坛越来越好!
    回复

    使用道具 举报

    发表于 2023-6-29 16:18:56 | 显示全部楼层
    塞翁364 2023-6-29 16:18:56 看全部
    感谢楼主的无私分享!要想知鸟论坛好 就靠你我他
    回复

    使用道具 举报

    发表于 2023-6-29 16:50:11 | 显示全部楼层
    尘埃416 2023-6-29 16:50:11 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    发表于 2023-6-30 20:44:38 | 显示全部楼层
    惜颜705 2023-6-30 20:44:38 看全部
    感谢楼主的无私分享!要想知鸟论坛好 就靠你我他
    回复

    使用道具 举报

    发表于 2023-7-1 00:53:29 | 显示全部楼层
    墙和鸡蛋 2023-7-1 00:53:29 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-7-3 06:42:36 | 显示全部楼层
    幸福341 2023-7-3 06:42:36 看全部
    楼主,我太崇拜你了!我想我是一天也不能离开知鸟论坛
    回复

    使用道具 举报

    • 您可能感兴趣
    点击右侧快捷回复 【请勿灌水】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| SiteMap| 小黑屋| 知鸟论坛
    联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表