multiplexer: Multiplexeur de service de port transparent pour le sous-système de flux
Installation
Si vous n'avez pas configuré l'abonnement au dépôt RPM, inscrivez-vous. Ensuite, vous pouvez procéder avec les étapes suivantes.
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
Pour utiliser cette bibliothèque Lua avec NGINX, assurez-vous que nginx-module-lua est installé.
Ce document décrit lua-resty-multiplexer v0.2 publié le 31 août 2020.
Cette bibliothèque implémente un multiplexeur de service de port transparent, qui peut être utilisé pour exécuter plusieurs services TCP sur le même port.
Notez que le module de flux nginx et le module stream-lua-nginx-module sont requis.
Testé sur Openresty >= 1.13.6.1.
Avec OpenResty 1.13.6.1, un patch personnalisé de @fcicq est nécessaire. La discussion d'origine peut être trouvée ici. Et le proxy natif n'est pas pris en charge car reqsock:peek est manquant.
À partir d'OpenResty 1.15.8.1, seul le proxy natif est pris en charge et aucun patch n'est nécessaire. Le proxy Lua sera possible lorsque le module stream-lua-nginx-module implémentera tcpsock:receiveany.
Synopsis
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;
# pour OpenResty >= 1.13.6.1, proxy Nginx natif
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;
}
# pour OpenResty < 1.13.6.1, proxy 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()
}
}
}
}
Ce module se compose de deux parties : les identifiants de protocole et les correspondances.
Les identifiants de protocole doivent être chargés via load_protocols dans la directive init_by_lua_block. Voir la section protocole pour les protocoles actuellement pris en charge et le guide pour ajouter un nouveau protocole.
Les règles sont définies via set_rules pour acheminer le trafic vers différents upstreams. Pour chaque correspondance définie dans la règle, la correspondance correspondante est chargée automatiquement. Voir la section matcher pour les correspondances actuellement implémentées et le guide pour ajouter un nouveau matcher.
Voir la section API pour la syntaxe de load_protocols et set_rules.
Les règles définies sont prioritaires. Dans l'exemple ci-dessus, nous avons défini une règle telle que :
- Si l'adresse du client est
10.0.0.1, proxy vers internal-host.com:80 - Si le protocole est
HTTPet l'adresse du client est10.0.0.2, proxy vers internal-host:8001 - Si le protocole est
SSH, proxy vers github.com:22 - Si le protocole est
DNS, proxy vers 1.1.1.1:53 - Si le protocole est
SSL/TLSet que la minute actuelle est entre 0 et 30, proxy vers twitter:443 - Si le protocole est
SSL/TLSet que la minute actuelle est entre 31 et 59, proxy vers www.google.com:443 - Sinon, proxy vers 127.0.0.1:80
Protocole
La partie protocole analyse la première requête envoyée par le client et essaie de la faire correspondre en utilisant des signatures de protocole connues.
Actuellement pris en charge : dns, http, ssh, tls, xmpp. En fonction des octets de la signature, chaque protocole peut avoir différentes possibilités d'être faussement identifié.
| Protocole | Longueur de la signature | Taux de faux |
|---|---|---|
| dns | 9 1/4 | 5.29e-23 |
| http | 4 | 2.33e-10 |
| ssh | 4 | 2.33e-10 |
| tls | 6 | 3.55e-15 |
| xmpp | 6 dans 8 1/4 | ? |
Ajouter un nouveau protocole
Créez un nouveau fichier protocol_name.lua sous resty/multiplexer/protocol au format :
return {
required_bytes = ?,
check = function(buf)
-- vérifier avec le buf et retourner true si le protocole est identifié
end
}
required_bytes est la longueur des octets que nous devons lire avant d'identifier le protocole.
Matcher
client-host
Correspond si $remote_addr est égal à la valeur attendue.
protocol
Correspond si le protocole est égal à la valeur attendue.
time
Correspond si l'heure actuelle est dans la plage configurée dans mul.matcher_config.time. Si aucune plage n'est définie, le matcher renverra toujours false.
Par exemple, pour correspondre à l'année 2018, janvier et mars et à l'heure 6 à 24 sauf pour l'heure 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 = {}, -- jour du mois
day_not_match = {},
hour_match = {{6, 24}},
hour_not_match = {{12}},
minute_match = {},
minute_not_match = {},
second_match = {},
second_not_match = {},
}
}
default
Correspond toujours.
Ajouter un nouveau matcher
Créez un nouveau fichier matcher_name.lua sous resty/multiplexer/matchers au format :
local _M = {}
function _M.match(protocol, expected)
-- retourner true si c'est une correspondance
end
return _M
Où protocol est le protocole identifié sous forme de chaîne en minuscules, et expected est la valeur attendue pour ce matcher définie dans set_rules.
API
multiplexer.new
syntax: multiplexer:new(connect_timeout, send_timeout, read_timeout)
Initialise l'instance du multiplexeur. Et définit le seuil de délai de connexion, le seuil de délai d'envoi et le seuil de délai de lecture, comme dans tcpsock:settimeouts.
multiplexer.load_protocols
syntax: multiplexer:load_protocols("protocol-1", "protocol-2", ...)
Charge les modules de protocole en mémoire.
Les protocoles pris en charge peuvent être trouvés dans protocol.
multiplexer.set_rules
syntax: multiplexer:set_rules(rule1, rule2, ...)
Charge les règles dans l'ordre. Chaque règle est un tableau qui a le format :
{{"matcher-1", "expected-value-1"}, {"matcher-2", "expected-value-2"}, ..., "upstream_host", upstream_port}
Les matchers pris en charge peuvent être trouvés dans matcher.
Voir aussi
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-multiplexer.