Zum Inhalt

stream-lua: Lua-Skriptingunterstützung für NGINX-Streams

Installation

Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:

  • RedHat Enterprise Linux 7, 8, 9 und 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 und 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

Aktivieren Sie das Modul, indem Sie Folgendes an den Anfang von /etc/nginx/nginx.conf hinzufügen:

load_module modules/ngx_stream_lua_module.so;

Dieses Dokument beschreibt nginx-module-stream-lua v0.0.18 veröffentlicht am 27. März 2026.


Synopsis

events {
    worker_connections 1024;
}

stream {
    # definiere einen TCP-Server, der auf Port 1234 lauscht:
    server {
        listen 1234;

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

Als SSL-TCP-Server einrichten:

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()  -- lese eine Zeile von downstream
            if data == "thunder!" then
                ngx.say("flash!")  -- gebe Daten aus
            else
                ngx.say("boom!")
            end
            ngx.say("das Ende...")
        }
    }
}

Das Lauschen auf einem UNIX-Domain-Socket wird ebenfalls unterstützt:

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

        content_by_lua_block {
            ngx.say("Was geht?")
            ngx.flush(true)  -- alle ausstehenden Ausgaben leeren und warten
            ngx.sleep(3)  -- 3 Sekunden schlafen
            ngx.say("Tschüss...")
        }
    }
}

Beschreibung

Dies ist ein Port des ngx_http_lua_module zum Nginx "Stream"-Subsystem, um generische Stream/TCP-Clients zu unterstützen.

Die verfügbaren Lua-APIs und Nginx-Direktiven bleiben die gleichen wie die des ngx_http_lua-Moduls.

Direktiven

Die folgenden Direktiven wurden direkt von ngx_http_lua portiert. Bitte überprüfen Sie die Dokumentation von ngx_http_lua für weitere Details zu ihrer Verwendung und Verhalten.

Die send_timeout Direktive im Nginx "http" Subsystem fehlt im "stream" Subsystem. Daher verwendet ngx_stream_lua_module stattdessen die lua_socket_send_timeout Direktive für diesen Zweck.

Hinweis: Die lingering close-Direktive, die in älteren Versionen des stream_lua_nginx_module existierte, wurde entfernt und kann jetzt bei Bedarf mit der neu hinzugefügten tcpsock:shutdown API simuliert werden.

preread_by_lua_block

syntax: preread_by_lua_block { lua-script }

context: stream, server

phase: preread

Fungiert als Handler für die preread-Phase und führt den in lua-script angegebenen Lua-Code-String für jede Verbindung (oder Paket im Datagrammmodus) aus. Der Lua-Code kann API-Aufrufe machen und wird als neue, gestartete Coroutine in einer unabhängigen globalen Umgebung (d.h. einem Sandbox) ausgeführt.

Es ist möglich, den rohen Anfrage-Socket mit ngx.req.socket zu erwerben und Daten vom Client zu empfangen oder an den Client zu senden. Beachten Sie jedoch, dass der Aufruf der receive()-Methode des Anfrage-Sockets die Daten aus dem Puffer verbraucht und diese verbrauchten Daten von den Handlern weiter unten in der Kette nicht gesehen werden.

Der preread_by_lua_block-Code wird immer am Ende der preread-Verarbeitungsphase ausgeführt, es sei denn, preread_by_lua_no_postpone ist aktiviert.

Diese Direktive wurde erstmals in der v0.0.3 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

preread_by_lua_file

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

context: stream, server

phase: preread

Entspricht preread_by_lua_block, mit dem Unterschied, dass die Datei, die durch <path-to-lua-script-file> angegeben ist, den Lua-Code oder LuaJIT-Bytecode enthält, der ausgeführt werden soll.

Nginx-Variablen können im <path-to-lua-script-file>-String verwendet werden, um Flexibilität zu bieten. Dies birgt jedoch einige Risiken und wird normalerweise nicht empfohlen.

Wenn ein relativer Pfad wie foo/bar.lua angegeben wird, wird er in den absoluten Pfad relativ zum server prefix-Pfad umgewandelt, der durch die -p PATH-Befehlszeilenoption bestimmt wird, die beim Starten des Nginx-Servers angegeben wurde.

Wenn der Lua-Code-Cache aktiviert ist (standardmäßig), wird der Benutzer-Code einmal bei der ersten Verbindung geladen und zwischengespeichert. Die Nginx-Konfiguration muss jedes Mal neu geladen werden, wenn die Lua-Quelldatei geändert wird. Der Lua-Code-Cache kann während der Entwicklung vorübergehend deaktiviert werden, indem lua_code_cache auf off in nginx.conf umgeschaltet wird, um ein erneutes Laden von Nginx zu vermeiden.

Diese Direktive wurde erstmals in der v0.0.3 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

log_by_lua_block

syntax: log_by_lua_block { lua-script }

context: stream, server

phase: log

Führt den als <lua-script> angegebenen Lua-Quellcode während der log-Anforderungsverarbeitungsphase aus. Dies ersetzt nicht die aktuellen Zugriffsprotokolle, sondern wird vorher ausgeführt.

Yielding-APIs wie ngx.req.socket, ngx.socket.*, ngx.sleep oder ngx.say sind in dieser Phase nicht verfügbar.

Diese Direktive wurde erstmals in der v0.0.3 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

log_by_lua_file

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

context: stream, server

phase: log

Entspricht log_by_lua_block, mit dem Unterschied, dass die Datei, die durch <path-to-lua-script-file> angegeben ist, den Lua-Code oder LuaJIT-Bytecode enthält, der ausgeführt werden soll.

Nginx-Variablen können im <path-to-lua-script-file>-String verwendet werden, um Flexibilität zu bieten. Dies birgt jedoch einige Risiken und wird normalerweise nicht empfohlen.

Wenn ein relativer Pfad wie foo/bar.lua angegeben wird, wird er in den absoluten Pfad relativ zum server prefix-Pfad umgewandelt, der durch die -p PATH-Befehlszeilenoption bestimmt wird, die beim Starten des Nginx-Servers angegeben wurde.

Wenn der Lua-Code-Cache aktiviert ist (standardmäßig), wird der Benutzer-Code einmal bei der ersten Verbindung geladen und zwischengespeichert. Die Nginx-Konfiguration muss jedes Mal neu geladen werden, wenn die Lua-Quelldatei geändert wird. Der Lua-Code-Cache kann während der Entwicklung vorübergehend deaktiviert werden, indem lua_code_cache auf off in nginx.conf umgeschaltet wird, um ein erneutes Laden von Nginx zu vermeiden.

Diese Direktive wurde erstmals in der v0.0.3 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

lua_add_variable

syntax: lua_add_variable $var

context: stream

Fügt die Variable $var zum "Stream"-Subsystem hinzu und macht sie änderbar. Wenn $var bereits existiert, wird diese Direktive nichts tun.

Standardmäßig werden Variablen, die mit dieser Direktive hinzugefügt werden, als "nicht gefunden" betrachtet, und das Lesen von ihnen mit ngx.var gibt nil zurück. Sie können jedoch jederzeit über die ngx.var.VARIABLE API neu zugewiesen werden.

Diese Direktive wurde erstmals in der v0.0.4 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

preread_by_lua_no_postpone

syntax: preread_by_lua_no_postpone on|off

context: stream

Steuert, ob das Verschieben von preread_by_lua* Direktiven zum Ausführen am Ende der preread-Verarbeitungsphase deaktiviert werden soll oder nicht. Standardmäßig ist diese Direktive deaktiviert und der Lua-Code wird verschoben, um am Ende der preread-Phase ausgeführt zu werden.

Diese Direktive wurde erstmals in der v0.0.4 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

Nginx API für Lua

Viele Lua-API-Funktionen wurden von ngx_http_lua portiert. Überprüfen Sie das offizielle Handbuch von ngx_http_lua für weitere Details zu diesen Lua-API-Funktionen.

Dieses Modul unterstützt vollständig das neue Variablen-Subsystem im Nginx-Stream-Kern. Sie können auf alle built-in variables zugreifen, die vom Stream-Kern oder anderen Stream-Modulen bereitgestellt werden. * Core constants

`ngx.OK`, `ngx.ERROR`, usw.

Nur rohe Anfrage-Sockets werden aus offensichtlichen Gründen unterstützt. Der Wert des raw-Arguments wird ignoriert und der rohe Anfrage-Socket wird immer zurückgegeben. Im Gegensatz zu ngx_http_lua können Sie weiterhin Ausgabefunktionen wie ngx.say, ngx.print und ngx.flush aufrufen, nachdem Sie den rohen Anfrage-Socket über diese Funktion erworben haben.

Wenn der Stream-Server im UDP-Modus ist, gibt das Lesen vom downstream-Socket, der durch den ngx.req.socket-Aufruf zurückgegeben wird, nur den Inhalt eines einzelnen Pakets zurück. Daher wird der Leseaufruf niemals blockieren und gibt nil, "no more data" zurück, wenn alle Daten aus dem Datagramm verbraucht wurden. Sie können jedoch mehrere UDP-Pakete an den Client zurücksenden, indem Sie den downstream-Socket verwenden.

Die von diesem Modul zurückgegebenen rohen TCP-Sockets enthalten die folgende zusätzliche Methode:

Zurück zum Inhaltsverzeichnis

reqsock:receiveany

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

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

Diese Methode ähnelt der tcpsock:receiveany Methode.

Diese Methode wurde in stream-lua-nginx-module seit v0.0.8 eingeführt.

Zurück zum Inhaltsverzeichnis

tcpsock:shutdown

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

context: content_by_lua*

Schaltet den Schreibteil des Anfrage-Sockets ab, verhindert alle weiteren Schreibvorgänge an den Client und sendet TCP FIN, während die Lesehälfte offen bleibt.

Derzeit wird nur die Richtung "send" unterstützt. Die Verwendung anderer Parameter als "send" führt zu einem Fehler.

Wenn Sie vor dem Aufruf dieser Methode Ausgabefunktionen (wie ngx.say) aufgerufen haben, sollten Sie ngx.flush(true) verwenden, um sicherzustellen, dass alle beschäftigten Puffer vollständig geleert werden, bevor der Socket heruntergefahren wird. Wenn beschäftigte Puffer erkannt werden, gibt diese Methode nil mit der Fehlermeldung "socket busy writing" zurück.

Dieses Feature ist besonders nützlich für Protokolle, die eine Antwort generieren, bevor sie tatsächlich alle eingehenden Daten verbrauchen. Normalerweise sendet der Kernel RST an den Client, wenn tcpsock:close aufgerufen wird, ohne zuerst den Empfangspuffer zu leeren. Der Aufruf dieser Methode ermöglicht es Ihnen, weiterhin aus dem Empfangspuffer zu lesen und verhindert, dass RST gesendet wird.

Sie können diese Methode auch verwenden, um ein lingering close zu simulieren, ähnlich dem, bereitgestellt durch das ngx_http_core_module für Protokolle, die ein solches Verhalten benötigen. Hier ist ein Beispiel:

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

local ok, err = sock:shutdown("send")
if not ok then
    ngx.log(ngx.ERR, "Shutdown fehlgeschlagen: ", 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

Zurück zum Inhaltsverzeichnis

reqsock:peek

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

context: preread_by_lua*

Blickt in den preread Puffer, der die von dem Client gesendeten downstream-Daten enthält, ohne sie zu verbrauchen. Das heißt, die von dieser API zurückgegebenen Daten werden in späteren Phasen weiterhin upstream weitergeleitet.

Diese Funktion nimmt ein einzelnes erforderliches Argument, size, das die Anzahl der Bytes angibt, die eingesehen werden sollen. Wiederholte Aufrufe dieser Funktion geben immer Daten vom Anfang des preread-Puffers zurück.

Beachten Sie, dass die preread-Phase nach dem TLS-Handshake erfolgt. Wenn der Stream-Server mit aktiviertem TLS konfiguriert wurde, werden die zurückgegebenen Daten im Klartext sein.

Wenn der preread-Puffer nicht die angeforderte Menge an Daten hat, wird der aktuelle Lua-Thread ausgesetzt, bis mehr Daten verfügbar sind, preread_buffer_size überschritten wurde oder preread_timeout verstrichen ist. Erfolgreiche Aufrufe geben immer die angeforderte Menge an Daten zurück, d.h. es werden keine Teilmengen von Daten zurückgegeben.

Wenn preread_buffer_size überschritten wurde, wird die aktuelle Stream-Sitzung sofort mit dem Session-Statuscode 400 vom Stream-Kernmodul beendet, mit der Fehlermeldung "preread buffer full", die im Fehlerprotokoll ausgegeben wird.

Wenn preread_timeout überschritten wurde, wird die aktuelle Stream-Sitzung sofort mit dem Session-Statuscode 200 vom Stream-Kernmodul beendet.

In beiden Fällen ist keine weitere Verarbeitung der Sitzung möglich (außer log_by_lua*). Die Verbindung wird automatisch vom Stream-Kernmodul geschlossen.

Beachten Sie, dass diese API nicht verwendet werden kann, wenn der Verbrauch von Client-Daten erfolgt ist. Zum Beispiel, nachdem reqsock:receive aufgerufen wurde. Wenn ein solcher Versuch unternommen wurde, wird der Lua-Fehler "attempt to peek on a consumed socket" ausgelöst. Das Verbrauchen von Client-Daten nach dem Aufruf dieser API ist erlaubt und sicher.

Hier ist ein Beispiel für die Verwendung dieser API:

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

local data = assert(sock:peek(1)) -- schaue mir die ersten 1 Byte an, die die Länge enthalten
data = string.byte(data)

data = assert(sock:peek(data + 1)) -- schaue mir die Länge + das Größenbyte an

local payload = data:sub(2) -- trimme das Längenbyte, um die tatsächliche Nutzlast zu erhalten

ngx.log(ngx.INFO, "Nutzlast ist: ", payload)

Diese API wurde erstmals in der v0.0.6 Veröffentlichung eingeführt.

Zurück zum Inhaltsverzeichnis

Nginx-Kompatibilität

Die neueste Version dieses Moduls ist kompatibel mit den folgenden Versionen von Nginx:

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

Nginx-Kerne älter als 1.13.6 (exklusiv) sind nicht getestet und funktionieren möglicherweise nicht. Benutzen Sie auf eigenes Risiko!

Teilen Sie Nginx's Build-System mit, wo LuaJIT 2.1 zu finden ist:

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

Hier gehen wir davon aus, dass Nginx unter /opt/nginx/ installiert werden soll.

./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

Code-Repository

Das Code-Repository dieses Projekts wird auf GitHub unter openresty/stream-lua-nginx-module gehostet.

Siehe auch

GitHub

Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub Repository für nginx-module-stream-lua.