
WAF de alto desempenho construído sobre a stack OpenResty
lua-resty-waf - WAF de alto desempenho construído sobre a stack OpenResty
NOTE: lua-resty-waf está essencialmente abandonado. Este projeto foi útil numa época em que o ModSecurity para Nginx não era uma opção viável; isso não é mais o caso. Houve uma tentativa de revitalizar o projeto em 2020, mas não tenho os recursos para concluí-la; esse trabalho está parcialmente completo no branch redux.
lua-resty-waf é um WAF de proxy reverso construído usando a stack OpenResty. Ele usa a API Lua do Nginx para analisar informações de requisições HTTP e processá-las contra uma estrutura de regras flexível. O lua-resty-waf é distribuído com um conjunto de regras que imita o CRS do ModSecurity, além de algumas regras personalizadas criadas durante o desenvolvimento e testes iniciais, e um pequeno patchset virtual para ameaças emergentes. Além disso, o lua-resty-waf é distribuído com ferramentas para traduzir automaticamente regras ModSecurity existentes, permitindo que os usuários estendam a implementação do lua-resty-waf sem a necessidade de aprender uma nova sintaxe de regras.
O lua-resty-waf foi inicialmente desenvolvido por Robert Paprocki para sua dissertação de mestrado na Western Governor's University.
O lua-resty-waf requer vários módulos Lua resty de terceiros, embora todos estejam empacotados com o lua-resty-waf e, portanto, não precisem ser instalados separadamente. É recomendável instalar o lua-resty-waf em um sistema que execute o pacote de software OpenResty; o lua-resty-waf não foi testado em plataformas construídas com pacotes separados do código-fonte do Nginx e do módulo Lua do Nginx.
Para obter desempenho ideal de compilação de regex, é recomendável compilar Nginx/OpenResty com uma versão do PCRE que suporte compilação JIT. Se o seu SO não fornecer isso, você pode compilar um PCRE com suporte a JIT diretamente no seu build Nginx/OpenResty. Para fazer isso, referencie o caminho para o código-fonte do PCRE na flag de configuração --with-pcre. Por exemplo:```sh
Você pode baixar o código-fonte do PCRE no [site do PCRE](http://www.pcre.org/). Consulte também esta [postagem no blog](https://www.cryptobells.com/building-openresty-with-pcre-jit/) para um guia passo a passo sobre como compilar o OpenResty com uma biblioteca PCRE com JIT habilitado.
## Desempenho
O lua-resty-waf foi projetado tendo em mente eficiência e escalabilidade. Ele aproveita o modelo de processamento assíncrono do Nginx e um design eficiente para processar cada transação o mais rápido possível. Testes de carga mostraram que implantações que implementam todos os conjuntos de regras fornecidos, que são projetados para imitar a lógica por trás do CRS do ModSecurity, processam transações em aproximadamente 300-500 microssegundos por requisição; isso equivale ao desempenho anunciado pelo [WAF da Cloudflare](https://www.cloudflare.com/waf). Os testes foram executados em uma configuração de hardware razoável (CPU E3-1230, 32 GB de RAM, 2 x 840 EVO em RAID 0), atingindo um máximo de aproximadamente 15.000 requisições por segundo. Consulte [esta postagem no blog](http://www.cryptobells.com/freewaf-a-high-performance-scalable-open-web-firewall) para mais informações.
A carga de trabalho do lua-resty-waf é quase exclusivamente limitada pela CPU. A pegada de memória na VM Lua (excluindo o armazenamento persistente apoiado por `lua-shared-dict`) é de aproximadamente 2 MB.
## Instalação
Um Makefile simples é fornecido:```
# make && sudo make install
Alternativamente, instale via Luarocks:```
lua-resty-waf utiliza o gerenciador de pacotes [OPM](https://github.com/openresty/opm), disponível nas distribuições modernas do OpenResty. As ferramentas cliente do OPM exigem que a ferramenta de linha de comando `resty` esteja disponível na variável de ambiente `PATH` do seu sistema.
Observe que, por padrão, o lua-resty-waf executa no modo SIMULATE, para evitar afetar imediatamente uma aplicação; usuários que desejam habilitar as ações de regras devem definir explicitamente o modo operacional para ACTIVE.
## Sinopse```lua
http {
init_by_lua_block {
-- use resty.core for performance improvement, see the status note above
require "resty.core"
-- require the base module
local lua_resty_waf = require "resty.waf"
-- perform some preloading and optimization
lua_resty_waf.init()
}
server {
location / {
access_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
-- define options that will be inherited across all scopes
waf:set_option("debug", true)
waf:set_option("mode", "ACTIVE")
-- this may be desirable for low-traffic or testing sites
-- by default, event logs are not written until the buffer is full
-- for testing, flush the log buffer every 5 seconds
--
-- this is only necessary when configuring a remote TCP/UDP
-- socket server for event logs. otherwise, this is ignored
waf:set_option("event_log_periodic_flush", 5)
-- run the firewall
waf:exec()
}
header_filter_by_lua_block {
local lua_resty_waf = require "resty.waf"
-- note that options set in previous handlers (in the same scope)
-- do not need to be set again
local waf = lua_resty_waf:new()
waf:exec()
}
body_filter_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
waf:exec()
}
log_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
waf:exec()
}
}
}
}
Traduzir e inicializar um arquivo de regras SecRules do ModSecurity a partir do disco. Observe que isso ainda exige que o ruleset seja adicionado via add_ruleset (o nome base do arquivo deve ser fornecido como a chave).
Exemplo:```lua http { init_by_lua_block { local lua_resty_waf = require "resty.waf"
-- this translates and calculates a ruleset called 'ruleset_name'
local ok, errs = pcall(function()
lua_resty_waf.load_secrules("/path/to/secrules/ruleset_name")
end)
-- errs is an array-like table
if errs then
for i = 1, #errs do
ngx.log(ngx.ERR, errs[i])
end
end
}
server {
location / {
access_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
-- in order to use the loaded ruleset, it must be added via
-- the 'add_ruleset' option
waf:set_option("add_ruleset", "ruleset_name")
}
}
}
}
Além disso, `load_secrules` pode aceitar um segundo argumento opcional como uma tabela de opções a serem passadas para várias funções de tradução. As seguintes opções são reconhecidas:
* *path*: Define um caminho no sistema de arquivos para procurar arquivos de dados para operadores como @pmFromFile. Se nenhuma chave desse tipo estiver definida, o diretório de trabalho atual (`.`) é usado
* *force*: Não gera erro e não aborta ao falhar na tradução de uma variável de regra
* *loose*: Não gera erro e não aborta ao falhar na tradução de uma ação de regra
* *quiet*: Não gera erro ou aviso ao falhar na tradução de uma ação de regra
Esta função também pode aceitar uma terceira opção como tabela para capturar erros de tradução, para processamento posterior. Se essa opção não estiver presente ou não for uma tabela, os erros de tradução serão registrados no log de erros.
### lua-resty-waf.init()
Executa algum pré-processamento de regras e conjuntos de regras, com base no que foi disponibilizado por meio dos conjuntos de regras distribuídos padrão. É recomendado, mas não obrigatório, chamar esta função (não fazê-lo resultará em uma pequena penalidade de desempenho). Esta função nunca deve ser chamada fora deste escopo.
*Exemplo*:```lua
http {
init_by_lua_block {
local lua_resty_waf = require "resty.waf"
lua_resty_waf.init()
}
}
Instancie uma nova instância de lua-resty-waf. Você deve chamar este método em todas as fases do manipulador de requisições em que deseja executar o lua-resty-waf, e usar o resultado retornado para chamar outros métodos do objeto.
Exemplo:```lua location / { access_by_lua_block { local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
}
}
### lua-resty-waf:set_option()
Configure uma opção em uma base por escopo.
*Exemplo*:```lua
location / {
access_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
-- enable debug logging only for this scope
waf:set_option("debug", true)
}
}
Define uma variável de transação (armazenada na coleção de variáveis TX) antes de executar o WAF. Isso pode ser usado para definir variáveis utilizadas por conjuntos de regras complexos, como o OWASP CRS.
Exemplo:```lua location / { access_by_lua_block { local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
waf:set_var("FOO", "bar")
}
}
Observe que, como com qualquer outra regra do ModSecurity, a existência de uma variável não acarreta nenhuma mudança funcional no processamento do WAF; é responsabilidade do autor da regra entender e usar as variáveis `TX`.
### lua-resty-waf:sieve_rule()
Define uma exclusão de coleção para uma determinada regra.
*Exemplo*:```lua
location / {
access_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
local sieves = {
{
type = "ARGS",
elts = "foo",
action = "ignore",
}
}
waf:sieve_rule("12345", sieves)
}
}
Consulte a página da wiki rule sieves para obter detalhes e exemplos de uso avançado.
Executar o mecanismo de regras. Por padrão, o mecanismo é executado de acordo com a fase atualmente em execução. Uma tabela opcional pode ser passada, permitindo que os usuários "simulem" a execução de uma fase diferente.
Exemplo:```lua location / { access_by_lua_block { local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
-- execute according to access phase collections and rules
waf:exec()
}
content_by_lua_block {
local lua_resty_waf = require "waf"
local waf = lua_resty_waf:new()
-- execute header_filter rules, passing in a table of additional collections
-- this assumes the 'request_headers' and 'status' Lua variables were
-- declared and initialized elsewhere
local opts = {
phase = 'header_filter',
collections = {
REQUEST_HEADERS = request_headers,
STATUS = status,
}
}
waf:exec(opts)
}
}
### lua-resty-waf:write_log_events()
Grava quaisquer entradas de log de auditoria geradas a partir da transação. Isso só é opcional quando `exec` é chamado em um manipulador `log_by_lua`.
*Exemplo*:```lua
location / {
log_by_lua_block {
local lua_resty_waf = require "resty.waf"
local waf = lua_resty_waf:new()
-- write out any event log entries to the
-- configured target, if applicable
waf:write_log_events()
}
}
Padrão: nenhum
Adiciona um conjunto de regras adicional a ser usado durante o processamento. Isso permite que os usuários implementem conjuntos de regras personalizados sem sobrescrever o diretório de regras incluído. Conjuntos de regras adicionais devem residir em uma pasta chamada "rules" que esteja dentro do lua_package_path.
Exemplo:```lua http { -- the rule file 50000.json must live at -- /path/to/extra/rulesets/rules/50000.json lua_package_path '/path/to/extra/rulesets/?.lua;;';
server {
location / {
access_by_lua_block {
waf:set_option("add_ruleset", "50000_extra_rules")
}
}
}
}
Vários rulesets podem ser adicionados passando uma tabela de valores para `set_option`. Observe que os nomes dos rulesets são ordenados antes do processamento. Os rulesets são processados em ordem crescente.
### add_ruleset_string
*Padrão*: nenhum
Adiciona um ruleset extra para ser usado durante o processamento. Isso permite que os usuários implementem rulesets personalizados sem sobrescrever o diretório de regras incluído. Os rulesets são definidos inline como uma string Lua, na forma de uma estrutura JSON de um ruleset traduzido.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("add_ruleset_string", "70000_extra_rules", [=[{"access":[{"action":"DENY","id":73,"operator":"REGEX","opts":{},"pattern":"foo","vars":[{"parse":{"values":1},"type":"REQUEST_ARGS"}]}],"body_filter":[],"header_filter":[]}]=])
}
}
Note que os nomes dos rulesets são classificados antes do processamento e devem ser fornecidos como strings. Os rulesets são processados em ordem crescente de classificação.
Padrão: false
Instrui o lua-resty-waf a continuar processando a requisição quando um cabeçalho Content-Type foi enviado que não está na tabela allowed_content_types. Tais requisições não terão seu corpo de requisição processado pelo lua-resty-waf (a coleção REQUEST_BODY será nula). Dessa forma, os usuários não precisam colocar explicitamente na lista de permissões todos os possíveis cabeçalhos Content-Type que possam encontrar.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("allow_unknown_content_types", true) } }
### allowed_content_types
*Padrão*: nenhum
Define um ou mais cabeçalhos Content-Type que serão permitidos, além dos Content-Types padrão `application/x-www-form-urlencoded` e `multipart/form-data`. Uma requisição cujo tipo de conteúdo corresponda a um dos `allowed_content_types` definirá a coleção `REQUEST_BODY` como uma única string contendo (em vez de uma tabela); uma requisição cujo tipo de conteúdo não corresponda a nenhum desses valores, ou `application/x-www-form-urlencoded` ou `multipart/form-data`, será rejeitada.
*Exemplo*:```lua
location / {
access_by_lua_block {
-- define a single allowed Content-Type value
waf:set_option("allowed_content_types", "text/xml")
-- defines multiple allowed Content-Type values
waf:set_option("allowed_content_types", { "text/html", "text/json", "application/json" })
}
}
Note that mutiple set_option calls with a parameter of allowed_content_types will simply override the existing options table, so if you want to define multiple allowed content types, you must define them as a Lua table as shown above.
Default: false
Desativa/ativa o registro de depuração. As instruções de log de depuração são impressas no error_log. Observe que o registro de depuração é muito caro e não deve ser usado em ambientes de produção.
Example:```lua location / { access_by_lua_block { waf:set_option("debug", true) } }
### debug_log_level
*Padrão*: ngx.INFO
Define a constante de nível de log do nginx usada para registro de depuração.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("debug_log_level", ngx.DEBUG)
}
}
Padrão: ngx.HTTP_FORBIDDEN
Define o status a ser usado ao negar requisições.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("deny_status", ngx.HTTP_NOT_FOUND) } }
### disable_pcre_optimization
*Padrão*: false
Remove os sinalizadores `oj` de todas as chamadas `ngx.re.match`, `ngx.re.find` e `ngx.re.sub`. Isso pode ser útil em alguns casos em que bibliotecas PCRE mais antigas são usadas, mas causará uma degradação severa de desempenho, portanto seu uso é fortemente desaconselhado; em vez disso, os usuários são incentivados a compilar o OpenResty com uma biblioteca PCRE moderna e compatível com JIT.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("disable_pcre_optimization", true)
}
}
Nota: Este comportamento está obsoleto e será removido em versões futuras.
Padrão: true
Determina se devem ser gravadas entradas de log para correspondências de regras em uma transação que não foi alterada pelo lua-resty-waf. "Alterada" é definida como o lua-resty-waf agindo em uma regra cuja ação é ACCEPT ou DENY. Quando esta opção não está definida, o lua-resty-waf registrará correspondências de regras mesmo que a transação não tenha sido alterada. Por padrão, o lua-resty-waf só gravará entradas de log para correspondências se a transação tiver sido alterada.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_altered_only", false) } }
Observe que `mode` não terá efeito na determinação de se uma transação é considerada alterada. Ou seja, se uma regra com ação `DENY` for correspondida, mas o lua-resty-waf estiver em execução no modo `SIMULATE`, a transação ainda será considerada alterada, e as correspondências de regras serão registradas.
### event_log_buffer_size
*Padrão*: 4096
Define o tamanho limite, em bytes, do buffer usado para manter os logs de eventos. O buffer será liberado quando esse limite for atingido.
*Exemplo*:```lua
location / {
access_by_lua_block {
-- 8 KB event log message buffer
waf:set_option("event_log_buffer_size", 8192)
}
}
Padrão: ngx.INFO
Define a constante de nível de log do nginx usada para registro de eventos.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_level", ngx.WARN) } }
### event_log_ngx_vars
*Padrão*: vazio
Define quais variáveis extras de `ngx.var` são colocadas no evento de log. Esta é uma forma genérica de estender o alerta com contexto extra. O nome da variável será a chave da entrada sob uma chave `ngx` na entrada de log. Se a variável não estiver presente como uma variável nginx, nenhum item é adicionado ao evento.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("event_log_ngx_vars", "host")
waf:set_option("event_log_ngx_vars", "request_id")
}
}
O evento resultante tem estes itens extras:```json { "ngx": { "host": "example.com", "request_id": "373bcce584e3c18a" } }
### event_log_periodic_flush
*Padrão*: nenhum
Define um intervalo, em segundos, no qual o buffer do log de eventos será liberado periodicamente. Se nenhum valor for configurado, o buffer não será liberado periodicamente e só será liberado quando o limite de `event_log_buffer_size` for atingido. Configure esta opção para sites de tráfego muito baixo que possam não receber nenhum dado de log de eventos por um longo período, para evitar que dados obsoletos fiquem no buffer.
*Exemplo*:```lua
location / {
access_by_lua_block {
-- flush the event log buffer every 30 seconds
waf:set_option("event_log_periodic_flush", 30)
}
}
Padrão: false
Quando definido como true, as entradas de log contêm os argumentos da requisição sob a chave uri_args.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_request_arguments", true) } }
### event_log_request_body
*Padrão*: false
Quando definido como true, as entradas de log contêm o corpo da requisição sob a chave `request_body`.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("event_log_request_body", true)
}
}
Padrão: false
Os cabeçalhos da solicitação HTTP são copiados para o evento de log, sob a chave request_headers.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_request_headers", true) } }
O evento resultante tem estes itens extras:```json
{
"request_headers": {
"accept": "*/*",
"user-agent": "curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3"
}
}
Padrão: false
Habilitar conexões SSL ao registrar via TCP/UDP.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_ssl", true) } }
### event_log_ssl_sni_host
*Padrão*: nenhum
Define o host SNI para conexões `lua-resty-logger-socket`.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("event_log_ssl_sni_host", "loghost.example.com")
}
}
Padrão: false
Habilita a verificação de certificado para conexões SSL ao registrar via TCP/UDP.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_ssl_verify", true) } }
### event_log_socket_proto
*Padrão*: udp
Define qual protocolo IP usar (TCP ou UDP) ao enviar logs de eventos por meio de um socket remoto. A mesma lógica de buffering e flush recorrente será usada independentemente do protocolo.
*Exemplo*:```lua
location / {
access_by_lua_block {
-- send logs via TCP
waf:set_option("event_log_socket_proto", "tcp")
}
}
Padrão: error
Define o destino para os logs de eventos. O lua-resty-waf atualmente suporta o registro no log de erros, em um arquivo separado no sistema de arquivos local, ou em um servidor remoto TCP ou UDP. Nos dois últimos casos, os logs de eventos são armazenados em buffer e liberados quando um limite definido é atingido (veja abaixo para mais opções sobre as opções de registro de eventos).
Exemplo:```lua location / { access_by_lua_block { -- send event logs to the server's error_log location (default) waf:set_option("event_log_target", "error")
-- send event logs to a local file on disk
waf:set_option("event_log_target", "file")
-- send event logs to a remote server
waf:set_option("event_log_target", "socket")
}
}
Observe que, devido a uma limitação na biblioteca de registo utilizada, apenas um único socket de destino pode ser definido. Ou seja, você só pode configurar um destino `socket` com uma combinação específica de host/porta; se você configurar uma segunda combinação host/porta, os dados não serão registrados corretamente.
### event_log_target_host
*Padrão*: nenhum
Define o servidor de destino para logs de eventos destinados a um servidor remoto.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("event_log_target_host", "10.10.10.10")
}
}
Padrão: nenhum
Define o caminho de destino para logs de eventos que visam um local no sistema de arquivos local.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("event_log_target_path", "/var/log/lua-resty-waf/event.log") } }
Este caminho deve estar em um local gravável pelo usuário nginx. Observe que, por natureza, o registro em disco pode causar degradação significativa de desempenho em ambientes de alta concorrência.
### event_log_target_port
*Padrão*: nenhum
Define a porta de destino para logs de eventos direcionados a um servidor remoto.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("event_log_target_port", 9001)
}
}
Padrão: none
Substitui a funcionalidade das ações executadas quando uma regra é correspondida. Veja o exemplo para mais detalhes
Exemplo:```lua
location / {
access_by_lua_block {
local deny_override = function(waf, ctx)
ngx.log(ngx.INFO, "Overriding DENY action")
ngx.status = 404
end
-- override the DENY action with the function defined above
waf:set_option("hook_action", "DENY", deny_override)
}
}
### ignore_rule
*Padrão*: nenhum
Instrui o módulo a ignorar um ID de regra especificado. Observe que ignorar uma regra em uma cadeia resultará em toda a cadeia ser ignorada, e o processamento continuará para a próxima regra após a cadeia.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("ignore_rule", 40294)
waf:set_option("ignore_rule", {40002, 41036})
}
}
Várias regras podem ser ignoradas passando uma tabela de IDs de regras para set_option.
Padrão: nenhum
Instrui o módulo a ignorar um ruleset inteiro. Isso pode ser útil quando alguns rulesets (como os rulesets SQLi ou XSS CRS) são muito propensos a falsos positivos, ou não são aplicáveis à sua aplicação.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("ignore_ruleset", "41000_sqli") } }
### mode
*Padrão*: SIMULATE
Define o modo operacional do módulo. As opções são ACTIVE, INACTIVE e SIMULATE. No modo ACTIVE, as correspondências de regras são registradas e as ações são executadas. No modo SIMULATE, o lua-resty-waf percorre cada regra habilitada e registra as correspondências de regras, mas não conclui a ação especificada em uma determinada execução. O modo INACTIVE impede que o módulo seja executado.
Por padrão, SIMULATE é selecionado se um modo não for definido explicitamente; isso exige que novos usuários implementem ativamente o bloqueio definindo o modo como ACTIVE.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("mode", "ACTIVE")
}
}
Padrão: nenhum
Define o(s) resolvedor(es) DNS a serem usados para consultas RBL. Atualmente, apenas o tráfego UDP/53 é suportado. Esta opção deve ser definida como um endereço numérico, não um hostname. Se esta opção não for definida, todas as regras de consulta RBL retornarão false.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("nameservers", "10.10.10.10") } }
### process_multipart_body
*Padrão* true
Habilita o processamento de corpos de requisições multipart/form-data (quando presentes), usando o módulo `lua-resty-upload`. No futuro, o lua-resty-waf pode usar esse processamento para realizar verificações mais rigorosas de corpos de upload; por enquanto, este módulo executa apenas verificações mínimas de sanidade no corpo da requisição e não registrará um evento se o corpo da requisição for inválido. Desative esta opção se você não precisar dessa verificação, ou se bugs no módulo upstream estiverem causando problemas com uploads HTTP.
*Exemplo*:```lua
location / {
access_by_lua_block {
-- disable processing of multipart/form-data requests
-- note that the request body will still be sent to the upstream
waf:set_option("process_multipart_body", false)
}
}
Padrão: false
Define um cabeçalho HTTP X-Lua-Resty-WAF-ID na requisição upstream, com o valor sendo o ID da transação. Esse ID se correlacionará com o ID da transação presente nos logs de depuração (se definido). Isso pode ser útil para rastreamento de requisições ou fins de depuração.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("req_tid_header", true) } }
### res_body_max_size
*Padrão*: 1048576 (1 MB)
Define o limite de comprimento de conteúdo acima do qual os corpos de resposta não serão processados. Esse tamanho do corpo de resposta é determinado pelo cabeçalho de resposta Content-Length. Se esse cabeçalho não existir na resposta, o corpo de resposta nunca será processado.
*Exemplo*:```lua
location / {
access_by_lua_block {
-- increase the max response size to 2 MB
waf:set_option("res_body_max_size", 1024 * 1024 * 2)
}
}
Note que, por natureza, é necessário armazenar em buffer o corpo inteiro da resposta para usar corretamente a resposta como uma coleção, portanto, aumentar significativamente esse número não é recomendado sem justificativa (e amplos recursos de servidor).
Default: "text/plain", "text/html"
Define os tipos MIME com os quais o lua-resty-waf processará o corpo da resposta. Esse valor é determinado pelo cabeçalho Content-Type. Se esse cabeçalho não existir, ou se o tipo de resposta não estiver nesta lista, o corpo da resposta não será processado. Definir esta opção adicionará o tipo MIME fornecido aos padrões existentes de text/plain e text/html.
Exemplo:```lua location / { access_by_lua_block { -- mime types that will be processed are now text/plain, text/html, and text/json waf:set_option("res_body_mime_types", "text/json") } }
Múltiplos tipos MIME podem ser adicionados passando uma tabela de tipos para `set_option`.
### res_tid_header
*Padrão*: false
Define um cabeçalho HTTP `X-Lua-Resty-WAF-ID` na resposta downstream, com o valor como o ID da transação. Esse ID será correlacionado com o ID da transação presente nos logs de depuração (se definido). Isso pode ser útil para rastreamento de solicitações ou fins de depuração.
*Exemplo*:```lua
location / {
access_by_lua_block {
waf:set_option("res_tid_header", true)
}
}
Padrão: 5
Define o limite para a pontuação de anomalias. Quando o limite é atingido, o lua-resty-waf negará a requisição.
Exemplo:```lua location / { access_by_lua_block { waf:set_option("score_threshold", 10) } }
### storage_backend
*Padrão*: dict
Defina um mecanismo a utilizar para o armazenamento persistente de variáveis. As opções atuais disponíveis são *dict* (zona de memória compartilhada do ngx_lua), *memcached* e *redis*.
*Exemplo*:```lua
location / {
acccess_by_lua_block {
waf:set_option("storage_backend", "memcached")
}
}
Padrão: true
Ativar ou desativar o keepalive TCP para conexões com hosts remotos de armazenamento persistente.
Exemplo:```lua location / { acccess_by_lua_block { waf:set_option("storage_keepalive", false) } }
### storage_keepalive_timeout
*Padrão*: 10000
Configura o tempo limite (em milissegundos) para o pool de keepalive cosocket para hosts remotos de armazenamento persistente.
*Exemplo*:```lua
location / {
acccess_by_lua_block {
waf:set_option("storage_keepalive_timeout", 30000)
}
}
Padrão: 100
Configure o tamanho do pool para o pool de keepalive cosocket para hosts remotos de armazenamento persistente.
Exemplo:```lua location / { acccess_by_lua_block { waf:set_option("storage_keepalive_pool_size", 50) } }
### storage_memcached_host
*Padrão*: 127.0.0.1
Define um host a usar ao utilizar memcached como um mecanismo de armazenamento persistente de variáveis.
*Exemplo*:```lua
location / {
acccess_by_lua_block {
waf:set_option("storage_memcached_host", "10.10.10.10")
}
}
Padrão: 11211
Define uma porta a ser usada ao utilizar memcached como mecanismo de armazenamento persistente de variáveis.
Exemplo:```lua location / { acccess_by_lua_block { waf:set_option("storage_memcached_port", 11221) } }
### storage_redis_host
*Padrão*: 127.0.0.1
Defina um host para usar quando o redis for usado como mecanismo de armazenamento de variáveis persistentes.
*Exemplo*:```lua
location / {
acccess_by_lua_block {
waf:set_option("storage_redis_host", "10.10.10.10")
}
}
Padrão: 6379
Define uma porta a ser usada ao usar redis como mecanismo de armazenamento persistente de variáveis.
Exemplo:```lua location / { acccess_by_lua_block { waf:set_option("storage_redis_port", 6397) } }
### storage_zone
*Padrão*: nenhum
Define o `lua_shared_dict` que será usado para armazenar dados de armazenamento persistente. Esta zona deve ser definida no bloco `http{}` da configuração.
*Exemplo*:_```lua
http {
-- define a 64M shared memory zone to hold persistent storage data
lua_shared_dict persistent_storage 64m;
}
location / {
access_by_lua_block {
waf:set_option("storage_zone", "persistent_storage")
}
}
Várias zonas compartilhadas podem ser definidas e utilizadas, embora apenas uma zona possa ser definida por local de configuração. Se uma zona ficar cheia e a interface de dicionário compartilhado não puder adicionar mais chaves, o seguinte será registrado no log de erros:
Error adding key to persistent storage, increase the size of the lua_shared_dict
O lua-resty-waf é projetado para executar em múltiplas fases do ciclo de vida da requisição. As regras podem ser processadas nas seguintes fases:
Essas fases correspondem aos seus respectivos handlers lua do Nginx (access_by_lua, header_filter_by_lua, body_filter_by_lua e log_by_lua, respectivamente). Observe que executar o lua-resty-waf em um handler de fase lua que não esteja nesta lista resultará em comportamento quebrado. Todos os dados disponíveis em uma fase anterior estão disponíveis em uma fase posterior. Ou seja, os dados disponíveis na fase access também estão disponíveis nas fases header_filter e body_filter, mas não o contrário.
O lua-resty-waf é distribuído com diversos conjuntos de regras projetados para imitar a funcionalidade do ModSecurity CRS. Para referência, esses conjuntos de regras estão listados aqui:
O lua-resty-waf analisa definições de regras a partir de blobs JSON armazenados em disco. As regras são agrupadas com base em finalidade e gravidade, definidas como um conjunto de regras. Os conjuntos de regras incluídos foram criados para imitar parte da funcionalidade do ModSecurity CRS, particularmente as definições base_rules. Além disso, o script incluído modsec2lua-resty-waf.pl pode ser usado para traduzir conjuntos de regras adicionais ou personalizados para um blob JSON compatível com lua-resty-waf.
Observe que existem várias limitações no script de tradução, no que diz respeito a ações, coleções e operadores não suportados. Consulte esta página da wiki para obter uma lista atualizada de incompatibilidades conhecidas.
Existe um canal IRC #lua-resty-waf na Freenode. O Travis CI envia notificações para este canal; sinta-se à vontade para fazer perguntas/deixar comentários neste canal também.
Além disso, Q/A está disponível no CodeWake:
Por favor, direcione todos os pull requests para o branch de desenvolvimento, ou para um branch de funcionalidade se o PR for uma mudança significativa. Commits no master devem ocorrer apenas na forma de atualizações de documentação ou outras alterações que não tenham impacto no próprio módulo (e que possam ser mesclados de forma limpa no desenvolvimento).
O lua-resty-waf está em constante desenvolvimento e melhoria e, como tal, pode ter limitações em sua funcionalidade e desempenho. As limitações atualmente conhecidas podem ser encontradas no rastreador de problemas do GitHub deste repositório.
Este programa é software livre: você pode redistribuí-lo e/ou modificá-lo sob os termos da GNU General Public License conforme publicada pela Free Software Foundation, seja a versão 3 da Licença, ou (a seu critério) qualquer versão posterior.
Este programa é distribuído na esperança de que seja útil, mas SEM QUALQUER GARANTIA; sem sequer a garantia implícita de COMERCIALIZAÇÃO ou ADEQUAÇÃO A UM DETERMINADO FIM. Veja a GNU General Public License para mais detalhes.
Você deve ter recebido uma cópia da GNU General Public License junto com este programa. Se não, veja http://www.gnu.org/licenses/
Por favor, reporte bugs criando um ticket no rastreador de problemas do GitHub.