freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

envoy代理下使用wasm开发WAF
2021-08-30 21:57:11

本文作者:常箭@涂鸦智能安全实验室

一、简介

envoy : Envoy Proxy是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线。

wasm : WebAssembly的缩写。是一种用于基于堆栈的虚拟机的二进制指令格式。Wasm 被设计为编程语言的可移植编译目标,支持在 Web 上部署客户端和服务器应用程序。

TinyGo : 一个Go编译器,旨在用于微控制器,WebAssembly(WASM)和命令行工具等小型场景。

envoy代理项目本身并未设计WAF项目,但是根据其HTTP filters阶段,可以编写wasm插件,获取http流量,进行过滤操作。

二 、envoy配置 

根据官方文档(https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/wasm_filter),wasm插件应按照如下配置:

http_filters:
           - name: envoy.filters.http.wasm
             typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
               config:
                 name: "my_plugin"
                 root_id: "my_root_id"
                configuration:
                  "@type": "type.googleapis.com/google.protobuf.StringValue"
                  value: |
                    {}
                vm_config:
                  runtime: "envoy.wasm.runtime.v8"
                  vm_id: "my_vm_id"
                  code:
                    local:
                      filename: "lib/envoy_filter_http_wasm_example.wasm"
         - name: envoy.filters.http.router

filename参数即为编译好的wasm插件路径。

三、wasm插件开发

根据其官网介绍,wasm_filter目前是实验性的,正在积极开发,且不能在Windows机器中使用。官网给出了envoy下wasm C++ SDK (https://github.com/proxy-wasm/proxy-wasm-cpp-sdk),由于笔者对C有天生恐惧,所以使用了针对其C++ SDK的go版本实现(https://github.com/tetratelabs/proxy-wasm-go-sdk)。

根据go SDK的demo样例(https://github.com/tetratelabs/proxy-wasm-go-sdk/blob/main/examples/helloworld/main.go),可以看到go wasm SDK导出了以下http阶段函数供我们使用:

func (*DefaultHttpContext) OnHttpRequestHeaders(int, bool) Action

接收到http headers阶段,此阶段还未开始接受POST数据。

func (*DefaultHttpContext) OnHttpRequestBody(int, bool) Action

接收到http POST数据阶段,第一个参数为bodySize,即接收到的数据大小,第二个参数为endOfStream,即是否接收完毕。若未接收完毕,可直接返回types.ActionPause继续接收,亦可判断总的bodySize是否超过限制要求,超过限制的请求可以忽略过滤,也可以选择直接阻断防止攻击者发送超大封包绕过。

func (*DefaultHttpContext) OnHttpRequestTrailers(int) Action

分块消息

func (*DefaultHttpContext) OnHttpResponseHeaders(int, bool) Action

返回headers阶段

func (*DefaultHttpContext) OnHttpResponseBody(int, bool) Action 

返回体阶段。此阶段可用作检测敏感数据(例如身*证号,手*号等)是否有明文返回的不规范场景。

func (*DefaultHttpContext) OnHttpResponseTrailers(int) Action

分块消息

func (*DefaultHttpContext) OnHttpStreamDone()

完成请求阶段。

其他可用的导出函数

func (*DefaultPluginContext) OnTick()

定时任务函数,此过程可用于定时规则更新、定时日志输出等场景。使用此函数需要在OnPluginStart阶段进行注册 。

SDK提供了proxywasm包,用于获取请求的各种信息:

proxywasm.SetTickPeriodMilliSeconds(millSec uint32)   //用于注册定时任务

proxywasm.GetHttpRequestHeaders() ([][2]string, error)  //用于获取http headers,返回header map

proxywasm.GetHttpRequestHeader(key string) (string, error) //获取某个header key的值

proxywasm.GetHttpRequestBody(start, maxSize int) ([]byte, error) //获取POST数据

proxywasm.SendHttpResponse(statusCode uint32, headers [][2]string, body []byte) error //主动发送返回 ,可以用于阻断攻击请求。

proxywasm.DispatchHttpCall  //非阻塞的http请求,可以用于请求API,获取规则集。

更多的示例插件代码,读者可以进行参考。

四、插件编译

根据SDK文档,编译需要使用者安装go以及TinyGo,编译过程需要使用TinyGo的wasi方式进行编译。

tinygo build -o ./envoy.wasm  -target=wasi ./main.go

漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com)欢迎白帽子来探索。

招聘内推计划:涵盖安全开发、安全测试、代码审计、安全合规等所有方面的岗位,简历投递sec@tuya.com,请注明来源。

# WAF开发 # envoy
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录