- tls
- Parameters
- Application-Layer Protocol Negotiation (ALPN)
- TLS protocol negotiation constraints
- Session resumption
- RADIUS/1.1 (RFC 9765)
- Version selection and compatibility
- TLS requirements
- Session resumption
- Packet handling
- Example: HTTPS Server
- Example: RadSec Server (RADIUS over TLS)
- Example: TACACS+ over TLS
- Example: Mutual TLS (mTLS)
- EAP-TLS handshake logging
- Example JSON log records
- See Also
- Session resumption and CRL enforcement
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 |
| alpn_protocol | ALPN protocol identifier to offer or accept; repeat to configure multiple identifiers | No |
| 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 |
| radius_versions | RADIUS/TLS packet profiles: none, 1.0, 1.1, or 1.0, 1.1 | No |
| negotiation | Cipher suite, key exchange group, signature scheme, and TLS 1.2 Extended Master Secret constraints | No |
| tls12_session_id_resumption | Enables TLS 1.2 SessionID resumption (true or false) | No |
| session_cache_size | Maximum number of stateful TLS resumption cache entries shared by TLS 1.2 SessionID and TLS 1.3 stateful ticket resumption | No |
| tls12_session_id_resumption_lifetime | Maximum lifetime for TLS 1.2 SessionID cache entries as a duration (for example 24h, 30m, or 0s) | 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 (for example 24h, 30m, or 0s); 0 disables resumption tickets | 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.
Application-Layer Protocol Negotiation (ALPN)
Use alpn_protocol to override the Application-Layer Protocol Negotiation
(ALPN) identifiers for the TLS endpoint. Repeat the parameter to configure
multiple identifiers in preference order. Each value must contain between 1
and 255 bytes. This generic override is available to RADIUS, HTTP, TACACS+, and
other TLS applications that use custom ALPN identifiers. When omitted,
Radiator uses the application defaults. For example, an HTTP server uses h2
and http/1.1 by default, and can override that list with alpn_protocol.
RADIUS TLS endpoints apply additional compatibility behavior: non-standard
ALPN names use the RADIUS/1.0 packet profile. A RADIUS peer that omits ALPN is
also accepted as RADIUS/1.0 when alpn_protocol is configured. Use
radius_versions when the peer must negotiate a registered RADIUS ALPN
profile. Do not configure radius_versions and alpn_protocol in the same TLS
block.
TLS protocol negotiation constraints
Use the optional negotiation block to constrain TLS cipher suites, key
exchange groups, handshake signature schemes, and the TLS 1.2 Extended Master
Secret extension. Each repeated parameter forms an ordered allowlist. Omitted
categories retain their default values and ordering.
See TLS protocol negotiation constraints for the configuration syntax, allowed names, and defaults.
Session resumption
tls12_session_id_resumption controls TLS 1.2 SessionID based resumption.
When omitted, it defaults to false for all TLS listeners. TLS 1.2 ticket
resumption is always disabled.
session_cache_size sets the maximum number of stateful TLS resumption cache
entries for the listener. The cache is shared by TLS 1.2 SessionID resumption
and TLS 1.3 stateful ticket resumption. When omitted, Radiator stores up to
256 entries. Increase this value for high-volume TLS listeners when clients
need a longer window to resume sessions. The value must be at least 1.
Each cached session stores TLS resumption state, negotiated protocol details,
optional client certificate data, and optional application data. A typical entry
without a client certificate uses a few hundred bytes plus cache overhead.
Entries that include client certificate chains are larger. Set
session_cache_size so that the maximum cache memory fits the listener's
memory budget.
tls12_session_id_resumption_lifetime sets the maximum lifetime for TLS 1.2
SessionID cache entries. The value accepts standard duration units (for
example 24h, 30m, 90s, or 0s). A bare number is interpreted as
milliseconds. Positive sub-second values are rejected because TLS session
lifetimes are stored in whole seconds. When omitted, TLS 1.2 SessionID entries
use a 24-hour lifetime.
tls13_session_tickets controls TLS 1.3 session tickets only. When omitted,
it defaults to 0, so TLS 1.3 session resumption is disabled unless the
listener explicitly enables ticket issuance. 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. The maximum value
is 7d (604800 seconds), as required by TLS 1.3. Setting it to 0 (or 0s)
disables resumption ticket issuance entirely, equivalent to
tls13_session_tickets 0;. When the parameter is omitted, ticket issuance is
disabled. A positive lifetime only has an effect when tls13_session_tickets
is also set to a value greater than 0.
When a listener allows both TLS 1.2 and TLS 1.3, Radiator uses a conservative shared-cache policy. If either protocol has resumption disabled, Radiator disables the shared server-side resumption cache for the listener. This avoids advertising TLS 1.2 SessionIDs that the server will not resume. Use separate TLS 1.2-only and TLS 1.3-only listeners if you need independent resumption settings for each protocol version.
RADIUS/1.1 (RFC 9765)
The following settings and requirements apply only to RADIUS TLS listeners.
Version selection and compatibility
radius_versions applies only to RADIUS TLS listeners. When omitted,
Radiator enables only the radius/1.0 ALPN profile for compatibility
with existing configurations. Configure radius_versions 1.0, 1.1; to enable
both profiles and prefer RADIUS/1.1. RFC 9765 specifies 1.0, 1.1 as the
default for implementations that support both profiles. Radiator intentionally
uses RADIUS/1.0 as a backward compatibility exception. This prevents an
upgrade from changing packet encoding and validation for existing listeners.
Set radius_versions 1.0; to run a RADIUS/1.0-only listener. Set
radius_versions none; to accept RADIUS/1.0 clients that omit ALPN.
TLS requirements
RFC 9765 requires TLS 1.3 whenever RADIUS/1.1 is enabled, so Radiator restricts
such listeners to TLS 1.3 and rejects a configuration whose maximum version is
TLS 1.2. RADIUS/1.1 also requires mutual TLS. Set
require_client_certificate true; and configure client_ca_certificate so
Radiator can authenticate every client. Radiator rejects an enabled
RADIUS/1.1 policy when require_client_certificate is false.
Radiator supports RFC 9765 over TLS only. RADIUS/1.1 over DTLS is not supported.
Session resumption
When both versions are enabled, Radiator does not resume RADIUS/1.1 sessions. This prevents a resumed session from changing its negotiated RADIUS version. RADIUS/1.1-only listeners can resume TLS sessions according to the configured TLS 1.3 ticket settings.
Packet handling
On a negotiated RADIUS/1.1 connection, Radiator rejects CHAP-Password without
CHAP-Challenge and uses Protocol-Error replies defined by RFC 9765. These rules
do not affect RADIUS/1.0 or TLS blocks that omit radius_versions.
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 {
# Enable RADIUS/1.1 and RADIUS/1.0
radius_versions 1.0, 1.1;
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.full_authentication_at": "2025-05-21T09:54:07Z",
"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
Session resumption and CRL enforcement
Resumed TLS sessions skip the certificate verification callback, so a peer
whose certificate has been revoked since the original handshake can continue
using a resumption ticket or session ID until that ticket expires. When prompt
revocation enforcement is required (for example mTLS deployments that rely on
crl or crl-directory),
disable TLS 1.3 session tickets so every connection performs a full handshake:
tls {
certificate "SERVER_CERT";
certificate_key "SERVER_KEY";
server_ca_certificate "CA_CERT";
# Force a full handshake on every connection so the current CRL
# snapshot is consulted for every peer.
tls12_session_id_resumption false;
tls13_session_tickets 0;
}
TLS 1.2 SessionID resumption and TLS 1.3 session tickets are disabled by
default for all TLS listeners. Set tls12_session_id_resumption true; or
tls13_session_tickets N; only on listeners that should allow resumption.
- tls
- Parameters
- Application-Layer Protocol Negotiation (ALPN)
- TLS protocol negotiation constraints
- Session resumption
- RADIUS/1.1 (RFC 9765)
- Version selection and compatibility
- TLS requirements
- Session resumption
- Packet handling
- Example: HTTPS Server
- Example: RadSec Server (RADIUS over TLS)
- Example: TACACS+ over TLS
- Example: Mutual TLS (mTLS)
- EAP-TLS handshake logging
- Example JSON log records
- See Also
- Session resumption and CRL enforcement