tls
The tls clause configures Transport Layer Security (TLS) for server listeners. This configuration applies to all server types that support TLS:
- HTTP servers - Enables HTTPS with HTTP/1.1 and HTTP/2 support
- RADIUS servers - Enables RadSec (RADIUS over TLS, RFC 6614) on port 2083
- TACACS+ servers - Enables TACACS+ over TLS
Parameters
| Parameter | Description | Required |
|---|---|---|
| certificate | Server certificate name (from certificates block) | Yes |
| certificate_key | Server private key name (from certificates block) | Yes |
| server_ca_certificate | Additional certificates to append to the presented server certificate chain, typically intermediates | No |
| require_client_certificate | Whether clients must present a certificate | No |
| client_ca_certificate | CA certificate for validating client certificates | Conditional |
| @verification | Custom certificate verification pipeline | No |
| min_protocol_version | Minimum TLS protocol version (tlsv12 for TLS 1.2, tlsv13 for TLS 1.3) | No |
| max_protocol_version | Maximum TLS protocol version (tlsv12 for TLS 1.2, tlsv13 for TLS 1.3) | No |
| tls13_session_tickets | Number of TLS 1.3 session tickets to send (0 to disable) | No |
| tls13_session_ticket_lifetime | Advertised TLS 1.3 ticket lifetime as a duration (e.g. 24h, 30m, 0s); 0 disables resumption tickets entirely | No |
| keylog_filename | File path for TLS key logging (for debugging with Wireshark) | No |
require_client_certificate defaults to true when omitted. Set
require_client_certificate false; for one-way TLS listeners such as a normal
HTTPS endpoint.
The client_ca_certificate parameter is required when
require_client_certificate is set to true.
server_ca_certificate is optional. Use it when the certificate configured in
certificate does not already contain the full chain that clients should
receive from the server.
tls13_session_tickets controls TLS 1.3 session tickets only. TLS 1.3 early data (0-RTT) is always disabled irrespective of this setting.
tls13_session_ticket_lifetime sets the advertised ticket_lifetime value
carried in each TLS 1.3 NewSessionTicket message. The value accepts
standard duration units (for example 24h, 30m, 90s); a bare number is
interpreted as milliseconds for consistency with other Radiator duration
parameters. The TLS 1.3 ticket_lifetime field is expressed in whole
seconds, so sub-second positive values (such as 100ms) are rejected at
configuration load to avoid silently disabling resumption. Setting it to
0 (or 0s) disables resumption ticket issuance entirely, equivalent to
tls13_session_tickets 0;. When the parameter is omitted, a stateful
resumption store is used with a 24-hour advertised lifetime.
Example: HTTPS Server
certificates {
x509 "SERVER_CERT" {
filename "/var/lib/radiator/certs/server.pem";
}
key "SERVER_KEY" {
filename "/var/lib/radiator/certs/server-key.pem";
}
}
servers {
http "HTTPS_SERVER" {
listen {
protocol tls;
port 8443;
ip 0.0.0.0;
tls {
certificate "SERVER_CERT";
certificate_key "SERVER_KEY";
require_client_certificate false;
}
}
}
}
Example: RadSec Server (RADIUS over TLS)
RadSec typically requires mutual TLS (mTLS) where both server and client authenticate with certificates:
certificates {
x509 "RADSEC_CERT" {
filename "/var/lib/radiator/certs/radsec-server.pem";
}
key "RADSEC_KEY" {
filename "/var/lib/radiator/certs/radsec-server-key.pem";
}
x509 "RADSEC_SERVER_CA" {
filename "/var/lib/radiator/certs/radsec-ca.pem";
}
x509 "RADSEC_CLIENT_CA" {
filename "/var/lib/radiator/certs/radsec-client-ca.pem";
}
}
servers {
radius "RADSEC" {
listen {
protocol tls;
port 2083;
ip 0.0.0.0;
tls {
certificate "RADSEC_CERT";
certificate_key "RADSEC_KEY";
server_ca_certificate "RADSEC_SERVER_CA";
# RadSec requires client certificates
require_client_certificate true;
client_ca_certificate "RADSEC_CLIENT_CA";
@verification {
if any {
cert.valid != true;
# Require certificate issued under network device policy
cert.policy != "1.3.6.1.4.1.99999.1.2.3";
# Require certificate from partner organization
cert.subject.o != "Partner Network Inc";
} then {
reject;
} else {
accept;
}
}
}
}
clients "RADSEC_CLIENTS";
}
}
Example: TACACS+ over TLS
Add a tls { ... } block to a TACACS+ server listen { protocol tls; ... }
section. The TLS listener honors ip-accept, listener timeout,
keepalive, and per-client timeout exactly like the plain TCP listener.
servers {
tacacs-plus "TACACS_TLS" {
listen {
protocol tls;
port 300;
ip 0.0.0.0;
ip-accept "TACACS_TLS_ACCESS";
timeout 30s;
tls {
certificate "TACACS_SERVER_CERT";
certificate_key "TACACS_SERVER_KEY";
require_client_certificate true;
client_ca_certificate "TACACS_CLIENT_CA";
}
}
clients "TACACS_TLS_CLIENTS";
policy "POLICY_TACACS_PLUS";
}
}
Notes:
- TACACS+ TLS and RadSec listeners support
proxy-protocol v2;. The proxy sends the PROXY header before the TLS handshake. Radiator reads the header first, then uses the real client address from it for client matching. - Prefer running TACACS+ TLS and TACACS+ TCP on separate ports (and ideally
separate
tacacs-plusserver blocks). Distinct ports keep the configuration easier to reason about, simplify firewall rules, and avoid surprises when the same client address appears under both transports. If you must share the address space, TACACS+ clients can declareprotocol tls;in theirsourceblock to disambiguate; see clients.tacacs-plus for the matching rules. - For TACACS+ over TLS deployment details, including listener, client, and obfuscation settings, see TACACS+ Authentication, Authorization, and Accounting.
For policy, multistage authentication, and operational guidance, see TACACS+ Authentication, Authorization, and Accounting.
Example: Mutual TLS (mTLS)
When client certificate verification is required:
certificates {
x509 "SERVER_CERT" {
filename "/var/lib/radiator/certs/server.pem";
}
key "SERVER_KEY" {
filename "/var/lib/radiator/certs/server-key.pem";
}
x509 "SERVER_CA" {
filename "/var/lib/radiator/certs/ca.pem";
}
x509 "CLIENT_CA" {
filename "/var/lib/radiator/certs/client-ca.pem";
}
}
servers {
http "MTLS_SERVER" {
listen {
protocol tls;
port 8443;
ip 0.0.0.0;
tls {
certificate "SERVER_CERT";
certificate_key "SERVER_KEY";
server_ca_certificate "SERVER_CA";
# Require and validate client certificates
require_client_certificate true;
client_ca_certificate "CLIENT_CA";
}
}
}
}
EAP-TLS handshake logging
EAP-TLS and the EAP methods that tunnel TLS inside it (EAP-TTLS, EAP-PEAP,
EAP-TEAP) emit a structured logging scope around the inner TLS handshake.
The records below show example log entries. Fragment records do not include
payload bytes; use a packet capture and
keylog_filename for byte-level analysis in Wireshark.
Example JSON log records
A successful EAP-TLS handshake over TLS 1.3 (with --json-log-format):
{
"timestamp": "2026-05-21T10:14:07.482914Z",
"level": "DEBUG",
"namespace": ["server", "radius", "AUTH_RADIUS_UDP"],
"message": "TLS handshake complete",
"fields": {
"context_id": "e7c1d2c6-4a3f-4f9c-8f9a-2d4f1b1c9a44",
"eap_type": "tls",
"eap_identifier": 12,
"eaptls.version": 0,
"tls.role": "server",
"tls.timeout_ms": 5000,
"tls.max_fragment_size": 1024,
"tls.version": "TLSv1_3",
"tls.ciphersuite": "TLS13_AES_256_GCM_SHA384",
"tls.key_exchange_group": "X25519",
"tls.session_resumed": false,
"tls.exporter.label": "EXPORTER_EAP_TLS_Key_Material",
"tls.msk.exported": true,
"tls.msk.len": 128,
"tls.eap_tls13_trailer": true,
"tls.peer_cert.subject": "cn=testUser,o=Radiator Software,c=FI",
"tls.peer_cert.issuer": "cn=Radiator Intermediate CA I2,o=Radiator Software,c=FI",
"tls.peer_cert.chain_len": 2,
"tls.peer_cert.serial": "1a:2b:3c",
"tls.peer_cert.not_before": 1716285247,
"tls.peer_cert.not_before_timestamp": "2024-05-21T09:54:07Z",
"tls.peer_cert.not_after": 1747821247,
"tls.peer_cert.not_after_timestamp": "2025-05-21T09:54:07Z",
"tls.peer_cert.fingerprint_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"tls.peer_cert.sans": "dns:testuser.radiatorsoftware.example.com",
"tls.peer_cert.authority_key_identifier": "5c8fb3d99eabd69c6f884fa4aab442b5292f2f6b",
"tls.peer_cert.subject_key_identifier": "9d2892c2c6730bd7ee8b069d115ffe5e77d1dc7f",
"tls.peer_cert.intermediates": [
{
"chain_index": 1,
"subject": "cn=Radiator Intermediate CA I2,o=Radiator Software,c=FI",
"issuer": "cn=Radiator Root CA,o=Radiator Software,c=FI",
"serial": "10:02",
"not_before": 1704067200,
"not_before_timestamp": "2024-01-01T00:00:00Z",
"not_after": 1861833600,
"not_after_timestamp": "2028-12-31T00:00:00Z",
"fingerprint_sha256": "cfec366a0526a404cfe154527822b93fb9a8cdfbabf6fc259c0b24ea0ff8176e",
"authority_key_identifier": "884a0c7f8a3f38d8c2e886c83276f6d0a3b5cc37",
"subject_key_identifier": "5c8fb3d99eabd69c6f884fa4aab442b5292f2f6b"
}
],
"identity": "testUser@radiatorsoftware.example.com",
"calling_station_id": "22-44-66-00-11-22",
"called_station_id": "22-44-66-11-22-33:test.radiator",
"nas_identifier": "ap-lobby-1",
"nas_port": 0,
"nas_ip_address": "192.0.2.10"
}
}
A handshake failure where the Windows supplicant rejected the server
certificate or certificate chain. Depending on the Windows version and
certificate problem, the alert can appear as AccessDenied,
InternalError, or another fatal TLS alert:
{
"timestamp": "2026-05-21T10:15:21.107834Z",
"level": "WARN",
"namespace": ["server", "radius", "AUTH_RADIUS_UDP"],
"message": "TLS handshake failed",
"fields": {
"context_id": "1f8d3b4a-3b9d-49a1-b2a4-8a3f4b6c8d10",
"eap_type": "ttls",
"eap_identifier": 4,
"tls.role": "server",
"tls.timeout_ms": 5000,
"tls.max_fragment_size": 1024,
"identity": "anonymous@radiatorsoftware.example.com",
"calling_station_id": "AA-BB-CC-11-22-33",
"called_station_id": "11-22-33-AA-BB-CC:corp-wifi",
"nas_identifier": "ap-floor3-east",
"handshake.error.source": "tls",
"handshake.error.kind": "alert_received",
"handshake.error.detail": "received fatal alert: AccessDenied"
}
}
An outbound fragment record produced at Trace level when
max-fragment-size forces the server certificate flight to be split
across several EAP-TLS fragments:
{
"timestamp": "2026-05-21T10:14:07.481102Z",
"level": "TRACE",
"namespace": ["server", "radius", "AUTH_RADIUS_UDP"],
"message": "EAP-TLS fragment sent to peer",
"fields": {
"context_id": "e7c1d2c6-4a3f-4f9c-8f9a-2d4f1b1c9a44",
"eap_type": "tls",
"eap_identifier": 3,
"tls.role": "server",
"tls.max_fragment_size": 256,
"tls.bytes_total": 2104,
"frag.index": 1,
"frag.size": 252,
"frag.remaining": 1852,
"frag.more": true,
"frag.length_included": true
}
}
See Also
- certificates - Certificate configuration
- tls.verification - Custom certificate verification rules
- servers.http.listen - HTTP listen configuration
- servers.http - HTTP server configuration
- clients.tacacs-plus - TACACS+ client matching, secrets, and timeouts
- servers.listen.ip-accept - Pre-admission IP filtering
- servers.listen.proxy-protocol - PROXY protocol behavior on TCP and TLS listeners
- servers.radius.listen - RADIUS listen configuration
- servers.radius - RADIUS server configuration