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.
- lua_load_resty_core
- lua_code_cache
- lua_regex_cache_max_entries
- lua_package_path
- lua_package_cpath
- init_by_lua_block
- init_by_lua_file
- init_worker_by_lua_block
- init_worker_by_lua_file
- preread_by_lua_block
- preread_by_lua_file
- content_by_lua_block
- content_by_lua_file
- balancer_by_lua_block
- balancer_by_lua_file
- log_by_lua_block
- log_by_lua_file
- ssl_client_hello_by_lua_block
- ssl_client_hello_by_lua_file
- ssl_certificate_by_lua_block
- ssl_certificate_by_lua_file
- proxy_ssl_certificate_by_lua_block
- proxy_ssl_certificate_by_lua_file
- proxy_ssl_verify_by_lua_block
- proxy_ssl_verify_by_lua_file
- lua_shared_dict
- lua_socket_connect_timeout
- lua_socket_buffer_size
- lua_socket_pool_size
- lua_socket_keepalive_timeout
- lua_socket_log_errors
- lua_ssl_ciphers
- lua_ssl_crl
- lua_ssl_protocols
- lua_ssl_certificate
- lua_ssl_certificate_key
- lua_ssl_trusted_certificate
- lua_ssl_verify_depth
- lua_ssl_key_log
- lua_ssl_conf_command
- lua_upstream_skip_openssl_default_verify
- lua_check_client_abort
- lua_max_pending_timers
- lua_max_running_timers
- lua_sa_restart
- lua_add_variable
- lua_capture_error_log
- preread_by_lua_no_postpone
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.
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.
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.
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.
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.
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.
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.
-
Constantes de niveau de journal Nginx
ngx.ERR,ngx.WARN, etc. * print * ngx.ctx * ngx.balancer
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 :
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.
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
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.
- ngx.print
- ngx.say
- ngx.log
-
Cet appel ignore actuellement l'argument
waitet attend toujours que toute la sortie en attente soit complètement vidée (dans les tampons d'envoi du socket système). * ngx.exit * ngx.eof * ngx.sleep * ngx.escape_uri * ngx.unescape_uri * ngx.encode_args * ngx.decode_args * ngx.encode_base64 * ngx.decode_base64 * ngx.crc32_short * ngx.crc32_long * ngx.hmac_sha1 * ngx.md5 * ngx.md5_bin * ngx.sha1_bin * ngx.quote_sql_str * ngx.today * ngx.time * ngx.now * ngx.update_time * ngx.localtime * ngx.utctime * ngx.re.match * ngx.re.find * ngx.re.gmatch * ngx.re.sub * ngx.re.gsub * ngx.shared.DICT * ngx.socket.tcp * ngx.socket.udp * ngx.socket.connect * ngx.get_phase * ngx.thread.spawn * ngx.thread.wait * ngx.thread.kill * ngx.on_abort * ngx.timer.at * ngx.timer.running_count * ngx.timer.pending_count * ngx.config.debug * ngx.config.subsystemPrend toujours la valeur de chaîne Lua
"stream"dans ce module. * ngx.config.prefix * ngx.config.nginx_version * ngx.config.nginx_configure * ngx.config.ngx_lua_version * ngx.worker.exiting * ngx.worker.pid * ngx.worker.pids * ngx.worker.count * ngx.worker.id * coroutine.create * coroutine.resume * coroutine.yield * coroutine.wrap * coroutine.running * coroutine.status
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.