Aller au contenu

stream-lua: Support de script Lua pour les flux NGINX

Installation

Vous pouvez installer ce module dans n'importe quelle distribution basée sur RHEL, y compris, mais sans s'y limiter :

  • RedHat Enterprise Linux 7, 8, 9 et 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 et Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-stream-lua
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 nginx-module-stream-lua

Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :

load_module modules/ngx_stream_lua_module.so;

Ce document décrit nginx-module-stream-lua v0.0.18 publié le 27 mars 2026.


Synopsis

events {
    worker_connections 1024;
}

stream {
    # définir un serveur TCP écoutant sur le port 1234 :
    server {
        listen 1234;

        content_by_lua_block {
            ngx.say("Hello, Lua!")
        }
    }
}

Configuration en tant que serveur TCP SSL :

stream {
    server {
        listen 4343 ssl;

        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
        ssl_certificate     /path/to/cert.pem;
        ssl_certificate_key /path/to/cert.key;
        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;

        content_by_lua_block {
            local sock = assert(ngx.req.socket(true))
            local data = sock:receive()  -- lire une ligne en aval
            if data == "thunder!" then
                ngx.say("flash!")  -- sortie des données
            else
                ngx.say("boom!")
            end
            ngx.say("the end...")
        }
    }
}

L'écoute sur un socket de domaine UNIX est également prise en charge :

stream {
    server {
        listen unix:/tmp/nginx.sock;

        content_by_lua_block {
            ngx.say("What's up?")
            ngx.flush(true)  -- vider toute sortie en attente et attendre
            ngx.sleep(3)  -- dormir pendant 3 sec
            ngx.say("Bye bye...")
        }
    }
}

Description

Ceci est un port de ngx_http_lua_module vers le sous-système "stream" de Nginx afin de prendre en charge des clients de flux/TCP génériques.

Les API Lua disponibles et les directives Nginx restent les mêmes que celles du module ngx_http_lua.

Directives

Les directives suivantes sont portées directement de ngx_http_lua. Veuillez consulter la documentation de ngx_http_lua pour plus de détails sur leur utilisation et comportement.

La directive send_timeout dans le sous-système Nginx "http" est absente dans le sous-système "stream". En tant que tel, ngx_stream_lua_module utilise la directive lua_socket_send_timeout à cette fin à la place.

Remarque : la directive de fermeture persistante qui existait dans les anciennes versions de stream_lua_nginx_module a été supprimée et peut désormais être simulée avec la nouvelle API tcpsock:shutdown si nécessaire.

preread_by_lua_block

syntax: preread_by_lua_block { lua-script }

context: stream, server

phase: preread

Agit comme un gestionnaire de phase preread et exécute la chaîne de code Lua spécifiée dans lua-script pour chaque connexion (ou paquet en mode datagramme). Le code Lua peut faire des appels API et est exécuté comme une nouvelle coroutine spawnée dans un environnement global indépendant (c'est-à-dire un bac à sable).

Il est possible d'acquérir le socket de requête brut en utilisant ngx.req.socket et de recevoir des données ou d'envoyer des données au client. Cependant, gardez à l'esprit que l'appel de la méthode receive() du socket de requête consommera les données du tampon et ces données consommées ne seront pas visibles par les gestionnaires plus bas dans la chaîne.

Le code preread_by_lua_block s'exécutera toujours à la fin de la phase de traitement preread à moins que preread_by_lua_no_postpone ne soit activé.

Cette directive a été introduite pour la première fois dans la version v0.0.3.

Retour au sommaire

preread_by_lua_file

syntax: preread_by_lua_file <path-to-lua-script-file>

context: stream, server

phase: preread

Équivalent à preread_by_lua_block, sauf que le fichier spécifié par <path-to-lua-script-file> contient le code Lua ou le bytecode LuaJIT à exécuter.

Des variables Nginx peuvent être utilisées dans la chaîne <path-to-lua-script-file> pour fournir de la flexibilité. Cela comporte cependant certains risques et n'est pas ordinairement recommandé.

Lorsqu'un chemin relatif comme foo/bar.lua est donné, il sera transformé en chemin absolu relatif au chemin de server prefix déterminé par l'option de ligne de commande -p PATH donnée lors du démarrage du serveur Nginx.

Lorsque le cache de code Lua est activé (par défaut), le code utilisateur est chargé une fois lors de la première connexion et mis en cache. La configuration Nginx doit être rechargée chaque fois que le fichier source Lua est modifié. Le cache de code Lua peut être temporairement désactivé pendant le développement en passant lua_code_cache à off dans nginx.conf pour éviter d'avoir à recharger Nginx.

Cette directive a été introduite pour la première fois dans la version v0.0.3.

Retour au sommaire

log_by_lua_block

syntax: log_by_lua_block { lua-script }

context: stream, server

phase: log

Exécute le code source Lua spécifié comme <lua-script> pendant la phase de traitement de la requête log. Cela ne remplace pas les journaux d'accès actuels, mais s'exécute avant.

Les API qui renvoient comme ngx.req.socket, ngx.socket.*, ngx.sleep, ou ngx.say ne sont pas disponibles dans cette phase.

Cette directive a été introduite pour la première fois dans la version v0.0.3.

Retour au sommaire

log_by_lua_file

syntax: log_by_lua_file <path-to-lua-script-file>

context: stream, server

phase: log

Équivalent à log_by_lua_block, sauf que le fichier spécifié par <path-to-lua-script-file> contient le code Lua ou le bytecode LuaJIT à exécuter.

Des variables Nginx peuvent être utilisées dans la chaîne <path-to-lua-script-file> pour fournir de la flexibilité. Cela comporte cependant certains risques et n'est pas ordinairement recommandé.

Lorsqu'un chemin relatif comme foo/bar.lua est donné, il sera transformé en chemin absolu relatif au chemin de server prefix déterminé par l'option de ligne de commande -p PATH donnée lors du démarrage du serveur Nginx.

Lorsque le cache de code Lua est activé (par défaut), le code utilisateur est chargé une fois lors de la première connexion et mis en cache. La configuration Nginx doit être rechargée chaque fois que le fichier source Lua est modifié. Le cache de code Lua peut être temporairement désactivé pendant le développement en passant lua_code_cache à off dans nginx.conf pour éviter d'avoir à recharger Nginx.

Cette directive a été introduite pour la première fois dans la version v0.0.3.

Retour au sommaire

lua_add_variable

syntax: lua_add_variable $var

context: stream

Ajoute la variable $var au sous-système "stream" et la rend modifiable. Si $var existe déjà, cette directive ne fera rien.

Par défaut, les variables ajoutées à l'aide de cette directive sont considérées comme "non trouvées" et les lire avec ngx.var renverra nil. Cependant, elles peuvent être réaffectées via l'API ngx.var.VARIABLE à tout moment.

Cette directive a été introduite pour la première fois dans la version v0.0.4.

Retour au sommaire

preread_by_lua_no_postpone

syntax: preread_by_lua_no_postpone on|off

context: stream

Contrôle s'il faut ou non désactiver le report des directives preread_by_lua* pour s'exécuter à la fin de la phase de traitement preread. Par défaut, cette directive est désactivée et le code Lua est reporté pour s'exécuter à la fin de la phase preread.

Cette directive a été introduite pour la première fois dans la version v0.0.4.

Retour au sommaire

Nginx API for Lua

De nombreuses fonctions API Lua sont portées de ngx_http_lua. Consultez le manuel officiel de ngx_http_lua pour plus de détails sur ces fonctions API Lua.

Ce module prend entièrement en charge le nouveau sous-système de variables à l'intérieur du noyau de flux Nginx. Vous pouvez accéder à n'importe quelle variable intégrée fournie par le noyau de flux ou d'autres modules de flux. * Constantes de base

`ngx.OK`, `ngx.ERROR`, etc.

Seuls les sockets de requête bruts sont pris en charge, pour des raisons évidentes. La valeur de l'argument raw est ignorée et le socket de requête brut est toujours retourné. Contrairement à ngx_http_lua, vous pouvez toujours appeler des fonctions API de sortie comme ngx.say, ngx.print, et ngx.flush après avoir acquis le socket de requête brut via cette fonction.

Lorsque le serveur de flux est en mode UDP, la lecture à partir du socket en aval retourné par l'appel ngx.req.socket ne renverra que le contenu d'un seul paquet. Par conséquent, l'appel de lecture ne bloquera jamais et renverra nil, "no more data" lorsque toutes les données du datagramme auront été consommées. Cependant, vous pouvez choisir d'envoyer plusieurs paquets UDP au client à l'aide du socket en aval.

Les sockets TCP bruts retournés par ce module contiendront la méthode supplémentaire suivante :

Retour au sommaire

reqsock:receiveany

syntax: data, err = reqsock:receiveany(max)

context: content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*

Cette méthode est similaire à la méthode tcpsock:receiveany

Cette méthode a été introduite dans stream-lua-nginx-module depuis v0.0.8.

Retour au sommaire

tcpsock:shutdown

syntax: ok, err = tcpsock:shutdown("send")

context: content_by_lua*

Ferme la partie écriture du socket de requête, empêche toute écriture supplémentaire vers le client et envoie TCP FIN, tout en gardant la moitié lecture ouverte.

Actuellement, seule la direction "send" est prise en charge. L'utilisation de tout paramètre autre que "send" renverra une erreur.

Si vous avez appelé des fonctions de sortie (comme ngx.say) avant d'appeler cette méthode, envisagez d'utiliser ngx.flush(true) pour vous assurer que tous les tampons occupés sont complètement vidés avant de fermer le socket. Si des tampons occupés sont détectés, cette méthode renverra nil avec le message d'erreur "socket busy writing".

Cette fonctionnalité est particulièrement utile pour les protocoles qui génèrent une réponse avant de réellement terminer la consommation de toutes les données entrantes. Normalement, le noyau enverra RST au client lorsque tcpsock:close est appelé sans vider d'abord le tampon de réception. L'appel de cette méthode vous permettra de continuer à lire à partir du tampon de réception et d'empêcher l'envoi de RST.

Vous pouvez également utiliser cette méthode pour simuler une fermeture persistante similaire à celle fournie par le ngx_http_core_module pour les protocoles ayant besoin d'un tel comportement. Voici un exemple :

local LINGERING_TIME = 30 -- 30 secondes
local LINGERING_TIMEOUT = 5000 -- 5 secondes

local ok, err = sock:shutdown("send")
if not ok then
    ngx.log(ngx.ERR, "échec de la fermeture : ", err)
    return
end

local deadline = ngx.time() + LINGERING_TIME

sock:settimeouts(nil, nil, LINGERING_TIMEOUT)

repeat
    local data, _, partial = sock:receive(1024)
until (not data and not partial) or ngx.time() >= deadline

Retour au sommaire

reqsock:peek

syntax: ok, err = reqsock:peek(size)

context: preread_by_lua*

Regarde dans le tampon preread qui contient les données en aval envoyées par le client sans les consommer. C'est-à-dire que les données retournées par cette API seront toujours transmises en amont dans les phases ultérieures.

Cette fonction prend un seul argument requis, size, qui est le nombre d'octets à examiner. Les appels répétés à cette fonction renvoient toujours des données du début du tampon preread.

Notez que la phase preread se produit après la poignée de main TLS. Si le serveur de flux a été configuré avec TLS activé, les données retournées seront en texte clair.

Si le tampon preread n'a pas la quantité de données demandée, alors le thread Lua actuel sera suspendu jusqu'à ce que plus de données soient disponibles, que preread_buffer_size ait été dépassé, ou que preread_timeout soit écoulé. Les appels réussis renvoient toujours la quantité demandée de données, c'est-à-dire qu'aucune donnée partielle ne sera retournée.

Lorsque preread_buffer_size a été dépassé, la session de flux actuelle sera immédiatement terminée avec le code d'état de session 400 par le module de noyau de flux, avec le message d'erreur "preread buffer full" qui sera imprimé dans le journal des erreurs.

Lorsque preread_timeout a été dépassé, la session de flux actuelle sera immédiatement terminée avec le code d'état de session 200 par le module de noyau de flux.

Dans les deux cas, aucun traitement supplémentaire sur la session n'est possible (sauf log_by_lua*). La connexion sera fermée par le module de noyau de flux automatiquement.

Notez que cette API ne peut pas être utilisée si la consommation des données du client a eu lieu. Par exemple, après avoir appelé reqsock:receive. Si une telle tentative a été faite, l'erreur Lua "attempt to peek on a consumed socket" sera levée. Consommer des données du client après avoir appelé cette API est autorisé et sûr.

Voici un exemple d'utilisation de cette API :

local sock = assert(ngx.req.socket())

local data = assert(sock:peek(1)) -- examiner le premier octet qui contient la longueur
data = string.byte(data)

data = assert(sock:peek(data + 1)) -- examiner la longueur + l'octet de taille

local payload = data:sub(2) -- retirer l'octet de longueur pour obtenir la charge utile réelle

ngx.log(ngx.INFO, "la charge utile est : ", payload)

Cette API a été introduite pour la première fois dans la version v0.0.6.

Retour au sommaire

Compatibilité Nginx

La dernière version de ce module est compatible avec les versions suivantes de Nginx :

  • 1.29.x (dernier test : 1.29.2)
  • 1.27.x (dernier test : 1.27.1)
  • 1.25.x (dernier test : 1.25.1)
  • 1.21.x (dernier test : 1.21.4)
  • 1.19.x (dernier test : 1.19.3)
  • 1.17.x (dernier test : 1.17.8)
  • 1.15.x (dernier test : 1.15.8)
  • 1.13.x (dernier test : 1.13.6)

Les noyaux Nginx plus anciens que 1.13.6 (exclusif) ne sont pas testés et peuvent ou non fonctionner. Utilisez à vos risques et périls !

indiquer au système de construction de nginx où trouver LuaJIT 2.1 :

export LUAJIT_LIB=/path/to/luajit/lib export LUAJIT_INC=/path/to/luajit/include/luajit-2.1

Ici, nous supposons que Nginx doit être installé sous /opt/nginx/.

./configure --prefix=/opt/nginx \ --with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/lib" \ --with-stream \ --with-stream_ssl_module \ --add-module=/path/to/stream-lua-nginx-module

Dépôt de code

Le dépôt de code de ce projet est hébergé sur GitHub à openresty/stream-lua-nginx-module.

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-stream-lua.