基于OpenResty的WAF原理与实践 – 作者:糖果L5Q

第1章 OpenrResty

1.1  OpenResty简介

Web防火墙在安全领域出现的频率很高,安全人员基于各种技术创建WAF系统用来实现Web防火墙功能,基于Java、Go语言、OpenResty等多种形式的实现方案,而基于OpenrResty的WAF系统实现,根据业务规模需求规模不同,系统实现的代码工程规模各异,功能复杂,可以实现一个交互体验良好的检测管理系统,功能简单,实现黑白名单亦可,高投入产出比高,伸缩性很强。

OpenResty的发呢源于Nginx,Nginx是一个性能强悍的Web服务器,最开始基于对Nginx服务的扩展,大多数情况都用C语言来完成。C语言属于一种“中级”计算机语言,因可通过指针控制对计算机底层的操作处理,让C语言同比其他高级语言,学习曲线更陡峭,更容易在生产编码中出错,维护起来相对Python、Lua这种业务型的,抽象程度高的计算机语言来说,更复杂,同比实现同样功能的代码完成行数与时间更多更长一些。

OpenResty的作者在Nginx的基础上引入的Lua语言,通过Nginx Lua Module这个模块,让Nginx可以通过Lua语言对Nginx进行功能扩展,并且同时实现了大量的Nginx扩展模块对其支持,完备的Nginx的工具与功能生态,在这些基础之上作者发布了一个新的Nginx发行版本:OpenResty。

OpenResty为Nginx提供了强大的Lua业务描述语言工具,提供了一些可调用的API功能,Lua相比C语言,语言抽象程度更高,短短的几行话,就可以实现一个原来需要Nginx C扩展模板实现的功能,省去了编译C语言所需要的时间,直接用Lua语言动态实现,在调试阶段甚至可以不用重启Nginx服务,可修改Lua源码,变更功能代码简单方便。

OpenResty在国内社区的发展的脉络,简单回顾的话,主要以OpenResty发展为主线,周边衍生出多种的社会产品,包括第三方模块、Web框架、网关产品等产品。

进入Lua的Web世界,有几个关键型开源项目要提及,一位是OpenResty作者(很帅),还有一位是MoonScript的作者,同时是也OpenResty Web框架的作者Leafo老师,Luarocks的维护者,Luarocks提供了大量的Lua语言基础库,整合了大量Lua实现的库。

MoonScript语言之于Lua来说, 就像CoffeScript与JavaScript的关系,MoonScipt提供了更高抽象程度的语言工具,MoonScirpt最后会被翻译成Lua语言,相对一个复杂的Lua语言实现的功能,可以通过 MoonScript更简洁的实同,MoonScript采用的类似Python语言的缩进方式。

文件app.moon,内容,如下 :

apis = require "lapis"

class extends lapis.Application

  "/": =>

    "Welcome to Lapis #{require "lapis.version"}!"

文件app.lua,内容,如下:

local lapis = require("lapis")

do

  local _class_0

  local _parent_0 = lapis.Application

  local _base_0 = {

    ["/"] = function(self)

      return "Welcome to Lapis " .. tostring(require("lapis.version")) .. "!"

    end

  }

  _base_0.__index = _base_0

  setmetatable(_base_0, _parent_0.__base)

  _class_0 = setmetatable({

    __init = function(self, ...)

      return _class_0.__parent.__init(self, ...)

    end,

    __base = _base_0,

    __name = nil,

    __parent = _parent_0

  }, {

    __index = function(cls, name)

      local val = rawget(_base_0, name)

      if val == nil then

        local parent = rawget(cls, "__parent")

        if parent then

          return parent[name]

        end

      else

        return val

      end

    end,

    __call = function(cls, ...)

      local _self_0 = setmetatable({}, _base_0)

      cls.__init(_self_0, ...)

      return _self_0

    end

  })

  _base_0.__class = _class_0

  if _parent_0.__inherited then

    _parent_0.__inherited(_parent_0, _class_0)

  end

  return _class_0

end

app.moon的源代码需要MoonScript编译器程序moonc,对源文件进行翻译,MoonScript语言直接支持的简单的OO面向对象编程特性,这也是原生Lua语言不具备的功能,但可以通过Lua原表功能进行模拟,OpenResty+lua的模式可以进行OpenResty的控制逻辑编写,同样也可以通过简洁的MoonScript语言进行OpenResty服务器编程,需要增加的一个步骤就是需要对MoonScript脚本编写的程序翻译成Lua脚本,这样OpenResty即可识别执行。

MoonScript有配套的Web框架:Lapis,Lapis作为一个有OpenResty 的Web语言框架集合了很多OpenResty功能模块,可以让用户通过MoonScript便捷的使用这些库功能,Lapis提供了命令行脚手架程序,可以快速的OpenResty的整套脚手架代码,上面的app.moon就是Lapis命令行程序自动生成,Lapis让OpenResty的Web编程更简单,可以让用户快速的入门OpenResty Lua编程,将注意力快速带入到业务逻辑编写,下面是Lapis自动生成的nginx.conf配置文件,如下:

env LAPIS_ENVIRONMENT=development;

worker_processes 1;

error_log stderr notice;

daemon off;

pid logs/nginx.pid;

 

events {

  worker_connections 1024;

}

 

http {

  include mime.types;

 

  server {

    listen 8080;

    lua_code_cache off;

 

    location / {

      default_type text/html;

      content_by_lua_block {

        require("lapis").serve("app")

      }

    }

 

    location /static/ {

      alias static/;

    }

 

    location /favicon.ico {

      alias static/favicon.ico;

    }

  }

}

在2015开始就有国内的作者开始编写国产化的Lua框架,比如:Lor、Vanila同时代用的比较多Lua Web框架,Lor框架在某些业务的生产系统上也工作了很多年,并且后来还基于Lor框架,产生国产网关产品Orange。

因为Lapis作为Web框架,对应OpenResty的7个工作阶段中的content_by_lua阶段,在网上可以经常看到的一张图,如下:

1604569049_5fa3c7d9815649dba3df5.png!small?1604569050028

基于OpenResty的WAF系统,与传统OpenResty Web的区别是,WAF代码在access_by_lua阶段被执行,当发现用户访问的异常之后,执行请求的拒绝或是跳转,不进行更具体的内容信息的渲染。

随着新的OpenResty新版本的发布,上面这张处理阶段也需要更新, OpenResty1.19.3版本发布中加入了exit_worker_by_*阶段,可以更方便的在worker退出的阶段执行任务。在某些版本中对特定数据处理部分的进行性能优化,提高了20%的性能,在ngx.balancer模块中增加了recreate_request() API,可在balancer阶段改写请求信息,目前这个版本提供给社区使用的,不推荐生产环境使用。

1.1.1  MoonScript与Lua

OpenResty服务即可用于实现网关应用,也可以实现WAF防护墙,有人可能会对MoonScript的性能产生怀疑,直接用Lua进行WAF模块的编写,而经过实践,用MoonScript翻译成的Lua代码执行的性能就差,也不是绝对的,所以,接着上一节的对MoonScript的内容,对MoonScript语言编程进行详细一些的介绍,如何可以通过MoonScript“操控”OpenResty,如下:

Coffescript是一种中间的脚本,可以把这种脚本翻译成JavaScript。而MoonScript,是可以翻译成lua语言的中间脚本。

1.安装MoonScript

sudo luarocks install moonscript

2.创建.moon源文件app.moon

lapis = require "lapis"  

class extends lapis.Application  

  "/": =>

"Welcome to Lapis #{require "lapis.version"}!"

3.安装MoonScript语法高亮的插件。

来源:freebuf.com 2020-11-05 17:32:33 by: 糖果L5Q

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论