This manual explains the script API how to write working service scripts.
If you wrote your own script, feel free to open PR in the repository to "examples" directory!
Scripts run in a restricted Lua environment.
Available standard libraries:
_G(base)stringtablemathutf8
Unavailable by default:
ioospackagedebug
This is intentional to keep scripts isolated and predictable.
Scripts interact with the client through the global table deadend.
Signature:
deadend.send(string_data) -> boolean
Sends raw bytes to the connected client.
Returns true on success, false if sending failed.
Example:
local ok = deadend.send("220 Service ready\r\n")
if not ok then
return
endSignature:
deadend.recv(integer_n) -> string | nil
Reads up to n bytes from the client.
Returns nil when the peer disconnects or the read fails.
Constraints:
nmust be in range1..65535.
Example:
local req = deadend.recv(1024)
if not req then
return
endSignature:
deadend.sleep(integer_ms)
Pauses script execution for ms milliseconds.
Example:
deadend.sleep(500)Signature:
deadend.get_ip() -> string
Returns the peer IP address.
Example:
local ip = deadend.get_ip()Signature:
deadend.log(string_message, string_level?)
Writes a runtime log line to stdout from a Lua script.
level is optional and defaults to "info".
Example:
deadend.log("smtp handshake started")
deadend.log("auth failure", "warn")Signature:
deadend.set_tarpit(integer_base_ms, integer_jitter_ms?)
Configures an automatic delay applied after each successful deadend.recv.
base_ms: fixed delay in millisecondsjitter_ms: optional extra random delay in range0..jitter_ms
Constraints:
- each value must be in range
0..60000
Example:
deadend.set_tarpit(80, 40)Signature:
deadend.set_limits(integer_recv_calls_limit, integer_recv_bytes_limit?)
Configures runtime receive limits for the current connection.
When a limit is exceeded, deadend.recv returns nil and the socket is closed.
recv_calls_limit: max number of successfulrecvcalls (0disables this limit)recv_bytes_limit: max cumulative bytes received (0disables this limit)
Example:
deadend.set_limits(200, 262144)Signature:
deadend.close()
Closes the current client socket.
Example:
deadend.close()
return- Always handle
nilfromdeadend.recv. - Keep state machines bounded (for example, max command loops).
- Use
deadend.set_tarpitanddeadend.set_limitsfor connection throttling and abuse control. - Use explicit protocol states for better realism and maintainability.
- Log important events (
connect,auth, protocol errors,disconnect). - Close cleanly when done.
A script file named <port>.lua serves that TCP port.
Examples:
22.luaserves port 2280.luaserves port 8025.luaserves port 255222.luaserves port 5222
Invalid names are ignored:
ssh.lua22.txt00000.lua70000.lua
See the examples directory for working scripts.
examples/25.lua: SMTP mock with command-state handling and script logging.examples/5222.lua: XMPP client-stream mock with feature negotiation and script logging.
- Lua 5.4 recommended.
- API is intentionally small and stable.