网站首页 文章专栏 soul网关 - 之waf插件,流量防火墙
soul网关 - 之waf插件,流量防火墙

一. waf插件是什么

waf插件,是网关的用来对流量实现防火墙功能的核心实现。

二. waf插件设计目的是什么,什么场景下应用

主要用来拦截非法请求,或者异常请求,并且给与相关的拒绝策略。当面对重放攻击时,你可以根据ip或者host来进行匹配,拦截掉非法的ip与host,设置reject策略。设置黑名单。

三. waf使用体验

首先像之前讲解的插件一样,需要到控制台开启插件。

image.png

这里 model 的值默认为 black,可以设置的值为 black 和 mix,虽然我也不知道明明就是不能填别的值,为什么不搞成下拉框?用户不详细看文档,都不知道填什么


    1>. 当 module 设置为 black 模式的时候,只有匹配的流量才会执行拒绝策略,不匹配的,直接会跳过。

    2>. 当 module 设置为 mixed 模式的时候,所有的流量都会通过 waf插件,针对不同的匹配流量,用户可以设置是 拒绝,还是通过。


然后,需要在网关加上pom依赖:

<!-- soul waf plugin start-->
  <dependency>
      <groupId>org.dromara</groupId>
      <artifactId>soul-spring-boot-starter-plugin-waf</artifactId>
      <version>${last.version}</version>
  </dependency>
  <!-- soul waf plugin end-->

然后需要在控制台设置规则选择器:

image.png

具体的方式跟其他插件都差不多,类型如果为full,则全部代理,customer就是匹配选择器规则代理

比如我想让某个接口不被访问,就可以再uri写上接口路径,比如不想让某个ip或者host访问,就可以选ip,host的规则,这里演示uri路径。

然后新建规则,规则是更细力度的匹配,并且可以让匹配的规则通过,还是不通过,也就实现了黑白名单。

image.png

这里我新建了一个路径为 “/order/findById”的路径,设置的规则是放行,并且可以自定义code。

image.png

再新建一个路径为 "/http/test/findByUserId" 的请求,并且设置的规则是不通过,code为401


注意一下,这里的执行顺序是指,多条规则下的执行顺序,当选择器为 full全流量匹配时,会使用最大的执行顺序作为rule。


接下来测试这两个规则:

1). 调用业务接口:“http://localhost:9195/http/order/findById?id=yangxing”,这个接口会匹配第一个规则,也就是放行,我们看下效果

{
    "id": "yangxing",
    "name": "hello world findById"
}

响应了,结果没毛病。

2).在测试下另一个: "http://localhost:9195/http/test/findByUserId?userId=2"

{
    "code": 401,
    "message": " You are forbidden to visit",
    "data": null
}

发现被拒绝了,而且code就是我们自定义的。

我们把code改为2500时,code也就是2500,但是不能为字符串,会报错。。。

四. 详解waf源码,如何实现

waf和其他插件一样,逻辑甚至更简单,基本就三个类就完事了。

WafConfig,配置类,也就是控制台配置的 black 和 mix值

WafPluginDataHandler 数据同步用的,控制台修改配置waf插件的配置,及时得知

WafPlugin核心功能,插件链中的一员

protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
    WafConfig wafConfig = Singleton.INST.get(WafConfig.class);
    if (Objects.isNull(selector) && Objects.isNull(rule)) {
        if (WafModelEnum.BLACK.getName().equals(wafConfig.getModel())) {
            return chain.execute(exchange);
        }
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        Object error = SoulResultWrap.error(403, Constants.REJECT_MSG, null);
        return WebFluxResultUtils.result(exchange, error);
    }
    String handle = rule.getHandle();
    WafHandle wafHandle = GsonUtils.getInstance().fromJson(handle, WafHandle.class);
    if (Objects.isNull(wafHandle) || StringUtils.isBlank(wafHandle.getPermission())) {
        log.error("waf handler can not configuration:{}", handle);
        return chain.execute(exchange);
    }
    if (WafEnum.REJECT.getName().equals(wafHandle.getPermission())) {
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        Object error = SoulResultWrap.error(Integer.parseInt(wafHandle.getStatusCode()), Constants.REJECT_MSG, null);
        return WebFluxResultUtils.result(exchange, error);
    }
    return chain.execute(exchange);
}

1). 逻辑就是在 AbstractSoulPlugin 的时候,匹配具体的选择器以及规则,在规则里面有相关拒绝策略信息,是放行,还是通过

2). 到达waf插件后,根据选择器和规则是否不为null,以及是否为mix模式,当为mix模式,而规则没有匹配,就直接返回默认的拒绝403

3). 如果选择器,规则都匹配,那么就根据规则的值,是否放行去走放行,还是拒绝


总的来说: waf逻辑还是挺清晰的,而且没有那么复杂,加入的mix策略也很有用,这么方便的原因在于选择器以及规则那里做的很通用,很方便拓展插件。




版权声明:本文由星尘阁原创出品,转载请注明出处!

本文链接:http://www.52xingchen.cn/detail/71




赞助本站,网站的发展离不开你们的支持!
来说两句吧
大侠留个名吧,或者可以使用QQ登录。
: 您已登陆!可以继续留言。
最新评论