Lunar - Tools
Lunar ships two command-line tools that make it easy to test and integrate a RADIUS deployment without a full backend or a live NAS:
radtest is a RADIUS test client for sending real Access-Requests at a server and inspecting the reply.
lunar_backend_sim is a stand-in backend API that serves a fixed test virtual and answers every decision, so you can run lunar end-to-end with nothing else in place.
Both are installed under /opt/lunar/bin/ and both are built on lunar's own code, so what they accept and produce matches the server exactly.
Radtest
radtest (/opt/lunar/bin/radtest) is a minimal RADIUS test client. It builds an Access-Request with lunar's own RADIUS codec (the exact code the server runs), sends it over UDP, validates the reply's Response Authenticator, and prints both the request and the reply attribute-by-attribute. Because it uses the server's codec, a request radtest accepts is a request the server accepts.
It supports PAP (default), CHAP, MS-CHAP and MS-CHAPv2.
Usage
radtest [OPTIONS] radius-server[:port] secret
The two positional arguments are the target server (with an optional :port, default 1812) and the shared secret configured for this client on the virtual. Everything else is an option:
Option |
Description |
|---|---|
--username <name> |
User-Name attribute value. Omitted = not sent. |
--password <pass> |
The password for the -t authentication type. Omitted = no password credential is sent and -t is ignored. This is the basis for methods that need no password, such as MAC authentication by Calling-Station-Id. |
-t <type> |
Authentication type: pap, chap, mschap or mschapv2 (default pap). Requires --password. Ignored when none is given. |
-d <dictionary> |
RADIUS dictionary.yaml file. Default: dictionary.yaml under /opt/lunar/share/lunar/radius/. |
--nas-port <number> |
NAS-Port attribute value. Omitted = not sent. |
--nas-ip-address <ip> |
NAS-IP-Address attribute value. Default: the source address. |
--source-ip <ip> |
Source IPv4 to send from (must be a local address). Default: chosen by the kernel route. |
--framed-protocol <val> |
Framed-Protocol attribute, by name (e.g. PPP, SLIP) or number. Omitted = not sent. |
--calling-station-id <id> |
Calling-Station-Id attribute value. Omitted = not sent. |
--no-message-auth |
Do not send a Message-Authenticator in the request. By default one is always added and signed. BlastRADIUS-hardened servers may drop a request without it. |
--timeout <seconds> |
Seconds to wait for a reply per attempt. Default: 5. |
--retry <count> |
Number of send attempts before giving up. Default: 3. |
Run radtest with no arguments to print this option list.
radtest exits 0 on an Access-Accept and 1 on anything else (reject, timeout or error), so it drops straight into a script or a health check.
Example
$ /opt/lunar/bin/radtest --username test@example.com --password testing123 172.16.0.1 testing123
Sent Access-Request Id 23 from 172.16.0.1:40297 to 172.16.0.1:1812 length 90
User-Name = "test@example.com"
User-Password = "testing123"
NAS-IP-Address = 172.16.0.1
Message-Authenticator = 0x00000000000000000000000000000000
Received Access-Accept Id 23 from 172.16.0.1:1812 to 172.16.0.1:40297 length 93
Message-Authenticator = 0x93d72b55740823997bbd197e740bc898
Class = 0x6e733a3a3861...
radtest: Success
A successful run ends in radtest: Success after an Access-Accept. The printed attribute names use their conventional dictionary spelling for readability. This is the console view, not the JSON the API emits.
Passwordless requests
Because --username and --password are both optional, the smallest possible test is just a server and a secret:
$ /opt/lunar/bin/radtest 172.16.0.1 testing123
This sends a valid Access-Request carrying only a NAS-IP-Address and a signed Message-Authenticator, with no User-Name and no password credential. It is a quick way to confirm connectivity, the shared secret and that the server answers, and it is the shape future passwordless methods (such as MAC authentication) will build on.
lunar_backend_sim
lunar_backend_sim (/opt/lunar/bin/lunar_backend_sim) is a self-contained stand-in for your backend API. It serves one fixed test virtual and answers every decision automatically, so you can bring lunar up and watch a full request flow without writing any backend code or configuring a real NAS.
What it serves
The simulator exposes the same backend routes lunar calls, and always returns the same built-in test virtual:
virtual id TEST listening on 127.0.0.1, auth port 1812, acct port 1813, CoA port 3799.
one client 127.0.0.1 / client-test with shared secret testing123.
Its decision logic is deliberately trivial so the result is never in doubt:
auth always returns access-accept.
acct always returns accounting-response.
coa returns disconnect-ack for a disconnect-request, otherwise coa-ack.
Because auth is answered access-accept unconditionally, the simulator does not validate credentials. Only PAP gives a meaningful radtest result against it; CHAP, MS-CHAP, MS-CHAPv2 and EAP need a real backend that runs the challenge/response, so they will not authenticate here.
For every reply it mirrors the request attributes straight back onto the response. That makes it easy to see, with radtest or the .../test route, exactly what lunar decoded and sent. It speaks both JSON and MessagePack, choosing the reply encoding from the request's Accept / Content-Type headers.
Routes it answers
GET /v1/lunar/<server>/virtuals returns the test virtual as a one-element list.
GET /v1/lunar/<server>/virtual/<id> returns the test virtual.
POST /v1/lunar/<server>/<type>/<id> accepts an inbound auth / acct / coa packet and returns the reply packet.
POST /v1/lunar/<server>/log accepts and discards remote log lines (201).
GET /v1/lunar/ping is a health probe (200), what lunar's /v1/status hits to decide the backend is reachable.
Usage
lunar_backend_sim [-h listen_ip] [-p listen_port] [-s auth_sleep_ms]
[-w worker_threads] [-V] [--enable-client-blast-ma]
Option |
Description |
|---|---|
-h <ip> |
Listen address. Default 127.0.0.1. |
-p <port> |
Listen port. Default 5555. |
-s <ms> |
Artificial auth latency in milliseconds. Only the auth path sleeps. Use it to simulate a slow backend. Default 0. |
-w <count> |
Worker threads. Default 512. |
-V |
Verbose: pretty-print (syntax-colored) every HTTP request and response. This is the mode to run while learning or debugging. You see each decoded packet lunar posts and each reply the simulator returns. |
--enable-client-blast-ma |
Mark the test client as requiring Message-Authenticator on inbound requests (BlastRADIUS mitigation), so lunar validates it for this client. By default the test client does not require it, which keeps simple manual tests easy. |
Running it in -V verbose mode alongside lunar is the fastest way to understand the request/response flow. See the Quickstart for a full walk-through.