multiplexer: Multiplexador de serviço de porta transparente para subsistema de stream
Instalação
Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Em seguida, você pode prosseguir com os seguintes passos.
CentOS/RHEL 7 ou Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-multiplexer
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-multiplexer
Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua está instalado.
Este documento descreve lua-resty-multiplexer v0.2 lançado em 31 de agosto de 2020.
Esta biblioteca implementou um multiplexador de serviço de porta transparente, que pode ser usado para executar múltiplos serviços TCP na mesma porta.
Observe que o módulo stream do nginx e o stream-lua-nginx-module são necessários.
Testado no OpenResty >= 1.13.6.1.
Com o OpenResty 1.13.6.1, um patch personalizado de @fcicq é necessário. A discussão original pode ser encontrada aqui. E o proxy nativo não é suportado, pois reqsock:peek está ausente.
A partir do OpenResty 1.15.8.1, apenas o proxy nativo é suportado e nenhum patch é necessário. O proxy em Lua será possível quando o stream-lua-nginx-module implementar tcpsock:receiveany.
Sinopse
stream {
init_by_lua_block {
local mul = require("resty.multiplexer")
mul.load_protocols(
"http", "ssh", "dns", "tls", "xmpp"
)
mul.set_rules(
{{"client-host", "10.0.0.1"}, "internal-host", 80},
{{"protocol", "http"}, {"client-host", "10.0.0.2"}, "internal-host", 8001},
{{"protocol", "http"}, "example.com", 80},
{{"protocol", "ssh"}, "github.com", 22},
{{"protocol", "dns"}, "1.1.1.1", 53},
{{"protocol", "tls"}, {"time", nil}, "twitter.com", 443},
{{"protocol", "tls"}, "www.google.com", 443},
{{"default", nil}, "127.0.0.1", 80}
)
mul.matcher_config.time = {
minute_match = {0, 30},
minute_not_match = {{31, 59}},
}
}
resolver 8.8.8.8;
# para OpenResty >= 1.13.6.1, proxy nativo do Nginx
lua_add_variable $multiplexer_upstream;
server {
error_log /var/log/nginx/multiplexer-error.log error;
listen 443;
resolver 8.8.8.8;
preread_by_lua_block {
local mul = require("resty.multiplexer")
local mp = mul:new()
mp:preread_by()
}
proxy_pass $multiplexer_upstream;
}
# para OpenResty < 1.13.6.1, proxy em Lua
server {
error_log /var/log/nginx/multiplexer-error.log error;
listen 443;
resolver 8.8.8.8;
server {
listen 80;
content_by_lua_block {
local mul = require("resty.multiplexer")
local mp = mul:new()
mp:content_by()
}
}
}
}
Este módulo consiste em duas partes: identificadores de protocolo e correspondências.
Os identificadores de protocolo precisam ser carregados através de load_protocols na diretiva init_by_lua_block. Consulte a seção protocol para protocolos atualmente suportados e um guia para adicionar um novo protocolo.
As regras são definidas através de set_rules para rotear o tráfego para diferentes upstreams. Para cada correspondência que é definida na regra, a correspondência correspondente é carregada automaticamente. Consulte a seção matcher para correspondências atualmente implementadas e um guia para adicionar uma nova correspondência.
Consulte a seção API para a sintaxe de load_protocols e set_rules.
As regras definidas têm prioridade. No exemplo acima, definimos uma regra tal que:
- Se o endereço do cliente for
10.0.0.1, proxy para internal-host.com:80 - Se o protocolo for
HTTPe o endereço do cliente for10.0.0.2, proxy para internal-host:8001 - Se o protocolo for
SSH, proxy para github.com:22 - Se o protocolo for
DNS, proxy para 1.1.1.1:53 - Se o protocolo for
SSL/TLSe o minuto atual estiver entre 0 e 30, proxy para twitter:443 - Se o protocolo for
SSL/TLSe o minuto atual estiver entre 31 e 59, proxy para www.google.com:443 - Caso contrário, proxy para 127.0.0.1:80
Protocolo
A parte do protocolo analisa a primeira solicitação que é enviada do cliente e tenta correspondê-la usando assinaturas de protocolo conhecidas.
Atualmente suportados: dns, http, ssh, tls, xmpp. Com base nos bytes da assinatura, cada protocolo pode ter diferentes possibilidades de ser identificado erroneamente.
| Protocolo | Comprimento da assinatura | Taxa de erro |
|---|---|---|
| dns | 9 1/4 | 5.29e-23 |
| http | 4 | 2.33e-10 |
| ssh | 4 | 2.33e-10 |
| tls | 6 | 3.55e-15 |
| xmpp | 6 em 8 1/4 | ? |
Adicionar novo protocolo
Crie um novo arquivo protocol_name.lua em resty/multiplexer/protocol no formato:
return {
required_bytes = ?,
check = function(buf)
-- verificar com o buf e retornar true se o protocolo for identificado
end
}
required_bytes é o comprimento dos bytes que precisamos ler antes de identificar o protocolo.
Correspondência
client-host
Correspondência se $remote_addr for igual ao valor esperado.
protocol
Correspondência se o protocolo for igual ao valor esperado.
time
Correspondência se o horário atual estiver no intervalo configurado em mul.matcher_config.time. Se nenhum intervalo for definido, a correspondência sempre retornará false.
Por exemplo, para corresponder ao ano 2018, Janeiro e Março e hora 6 a 24, exceto para a hora 12:
init_by_lua_block {
local mul = require("resty.multiplexer")
mul.load_protocols(
"http", "ssh", "dns", "tls", "xmpp"
)
mul.set_rules(
{{"time", ""}, "twitter.com", 443}
)
mul.matcher_config.time = {
year_match = {2018},
year_not_match = {},
month_match = {{1}, {3}},
month_not_match = {},
day_match = {}, -- dia do mês
day_not_match = {},
hour_match = {{6, 24}},
hour_not_match = {{12}},
minute_match = {},
minute_not_match = {},
second_match = {},
second_not_match = {},
}
}
default
Sempre corresponde.
Adicionar nova correspondência
Crie um novo arquivo matcher_name.lua em resty/multiplexer/matchers no formato:
local _M = {}
function _M.match(protocol, expected)
-- retornar true se for uma correspondência
end
return _M
Onde protocol é o protocolo identificado em string minúscula, e expected é o valor esperado para esta correspondência definido em set_rules.
API
multiplexer.new
sintaxe: multiplexer:new(connect_timeout, send_timeout, read_timeout)
Inicializa a instância do multiplexador. E define o limite de tempo de conexão, limite de tempo de envio e limite de tempo de leitura, conforme em tcpsock:settimeouts.
multiplexer.load_protocols
sintaxe: multiplexer:load_protocols("protocol-1", "protocol-2", ...)
Carrega os módulos de protocolo na memória.
Os protocolos suportados podem ser encontrados em protocol.
multiplexer.set_rules
sintaxe: multiplexer:set_rules(rule1, rule2, ...)
Carrega regras na ordem. Cada regra é uma tabela de array que está no formato:
{{"matcher-1", "expected-value-1"}, {"matcher-2", "expected-value-2"}, ..., "upstream_host", upstream_port}
Os correspondentes suportados podem ser encontrados em matcher.
Veja Também
GitHub
Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório do GitHub para nginx-module-multiplexer.