listen

The listen block configures how a RADIUS server receives incoming requests. There are two modes:

  • Network listen - Bind to a local IP address and port to accept requests directly over UDP, TCP, or TLS.
  • Reverse listen - Receive requests over an outbound backend connection using the backend statement, instead of binding to a local port.

Network listen

Use protocol, port, and ip to bind the server to a local network interface.

Example configuration of a network listen clause:

listen {
    # Transport protocol
    protocol udp;

    # Transport protocol port to listen to
    port 1813;

    # IPv4 address to listen to
    ip 127.0.0.1;

    # Default idle timeout for TCP/TLS connections (optional)
    # Used when client has no timeout configured
    timeout 30s;

    # TCP keepalive settings (optional, TCP/TLS only)
    keepalive {
        idle 60s;      # Time before first probe
        interval 10s;  # Time between probes
        count 3;       # Max probes before connection is dead
    }
}

Backend listen

The backend statement configures the server to receive RADIUS requests in reverse over an outbound backend connection. Instead of opening a local port, the server listens for requests arriving on the connections established by the named RADIUS backend.

This is useful when a device needs to receive RADIUS requests (such as CoA or Disconnect-Request) over an already established outbound connection. Typical use cases include:

  • NAS or AP simulation - A Network Access Server (NAS) or Access Point (AP) simulator that connects outbound to a RADIUS server and receives reverse CoA or Disconnect-Request messages over that connection.
  • Reverse connection proxying - A proxy that establishes an outbound connection to an upstream RADIUS server and forwards reverse requests received on that connection.

The value is the name of a RADIUS backend defined in the backends block. When backend is used, no other listen parameters (protocol, port, ip, timeout, keepalive) are allowed inside the listen block.

Example configuration:

backends {
    radius "RADSEC_BACKEND" {
        server "UPSTREAM" {
            secret "mysecret";
            timeout 60s;
            retries 2;
            status true;

            connect {
                protocol tls;
                host "192.168.1.1";
                port 2083;
                tls {
                    certificate "CLIENT_CERT";
                    certificate_key "CLIENT_KEY";
                    server_ca_certificate "SERVER_CA";
                }
            }
        }
    }
}

servers {
    radius "REVERSE_SERVER" {
        listen {
            backend "RADSEC_BACKEND";
        }
        clients "CLIENTS_RADIUS_ALL";
    }
}

aaa {
    policy "REVERSE_POLICY" {
        conditions all {
            radius.server == "REVERSE_SERVER";
        }

        handler "HANDLE_REVERSE" {
            @execute {
                # Process the reverse RADIUS request like a normal RADIUS
                # request. Apply local policy, update session state, proxy
                # onward, etc.
                accept;
            }
        }
    }
}

In this example, REVERSE_SERVER does not bind to any local port. Instead, it receives RADIUS requests that arrive on the outbound TLS connections managed by the RADSEC_BACKEND backend. Incoming reverse requests are matched against the configured clients list using the remote peer address of the backend connection.

For more information, see the Reverse CoA Messaging article.

timeout

The timeout option sets the default idle timeout for TCP and TLS connections on this listener. If no data is received within this period, the connection is closed.

Timeout priority:

  • If the client has a timeout configured, the client's value is used (including 0 to explicitly disable)
  • If the client has no timeout configured, the listener's timeout is used
  • If neither has a timeout, defaults to 10 seconds

keepalive

The keepalive block configures TCP keepalive probes for connections on this listener. Keepalive probes detect stale or dead connections at the TCP layer, even when no application data is being exchanged.

When to use keepalive: If you set a large timeout value (or disable it entirely), consider enabling keepalive to detect and close stale connections that may have been disconnected without proper termination (e.g., due to network failures, NAT timeouts, or client crashes).

Options:

  • idle: Time a connection must be idle before the first keepalive probe is sent.
  • interval: Time between subsequent keepalive probes.
  • count: Number of unanswered probes before the connection is considered dead and closed.

Example: RadSec with long timeout and keepalive

For RadSec (RADIUS over TLS) connections that should remain open for extended periods, use a long timeout combined with keepalive to detect stale connections:

listen {
    protocol tls;
    port 2083;
    ip 0.0.0.0;
    ip ::;

    # Allow connections to remain idle for up to 1 hour
    timeout 1h;

    # But probe every minute to detect dead connections
    keepalive {
        idle 1m;       # Start probing after 1 minute of idle
        interval 10s;  # Send probes every 10 seconds
        count 3;       # Close after 3 failed probes (30s max)
    }

    tls {
      ...
    }
}

This configuration keeps connections open for long-lived RadSec sessions while ensuring dead connections are detected within ~90 seconds (1 minute idle + 3 x 10 second probes).

TLS Connection Logging

When a TLS connection is accepted, a log message at log level debug is generated with details about the connection. The log message includes the following fields:

  • client_name: Name of the matched client configuration
  • peer_addr: Client IP address and port
  • tls_version: Negotiated TLS version (e.g., TLSv1_3)
  • cipher_suite: Negotiated cipher suite (e.g., TLS13_AES_256_GCM_SHA384)
  • key_exchange_group: Negotiated key exchange group if available (e.g., X25519)
  • alpn: ALPN protocol if negotiated (e.g., radius/1.0)
  • cert_subject: Subject of the client certificate
  • cert_issuer: Issuer of the client certificate

Example log output:

{
  "message": "Accepting Radius TLS client connection",
  "fields": {
    "client_name": "RADSEC_CLIENT",
    "peer_addr": "192.168.1.100:54321",
    "tls_version": "TLSv1_3",
    "cipher_suite": "TLS13_AES_256_GCM_SHA384",
    "alpn": "radius/1.0",
    "cert_subject": "cn=client.example.com",
    "cert_issuer": "cn=Example CA"
  }
}