What type of defect/bug is this?
Unexpected behaviour (obvious or verified by project member)
How can the issue be reproduced?
Environment
- FreeRADIUS 3.2.10
- radsecproxy 1.11.2
- FreeRADIUS running in a Linux container
- Incoming RadSec over TCP/2083
- Mutual TLS
- TLS 1.3 observed on the connection
I observed a deterministic 30-second server-side disconnect when an incoming RadSec listener is configured with both lifetime = 0 and idle_timeout = 0. The issue is reproducible independently of RADIUS authentication traffic.
The incoming TLS listener is configured as:
listen {
ipaddr = *
port = 2083
type = auth+acct
proto = tcp
virtual_server = default
clients = radsec
limit {
max_connections = 128
lifetime = 0
idle_timeout = 0
}
tls {
# certificates omitted
require_client_cert = yes
}
}
clients radsec {
client radsec-peer {
ipaddr = 10.x.x.x
proto = tls
secret = <redacted>
limit {
max_connections = 128
lifetime = 0
idle_timeout = 0
}
}
}
We verified that the configuration file actually consumed by the running container contains these values. The enabled TLS site is a symlink to the expected sites-available/tls; there is no alternate/stale configuration tree involved.
freeradius -XC reports the listener as:
listen {
type = "auth+acct"
virtual_server = "default"
ipaddr = *
port = 2083
proto = "tcp"
...
limit {
max_connections = 128
lifetime = 0
idle_timeout = 0
}
}
Configuration appears to be ok
### Reproduction
1. Configure the incoming RadSec/TCP listener and matching TLS client as
shown above.
2. Start FreeRADIUS 3.2.10.
3. Connect using radsecproxy 1.11.2.
4. Disable or minimise radsecproxy Status-Server polling so that the TLS
connection becomes genuinely idle.
5. Allow the connection to sit idle.
6. After approximately 30 seconds, FreeRADIUS closes the TCP connection.
7. radsecproxy immediately reconnects.
8. The sequence repeats every ~30 seconds.
The client reports:
```text
tlsconnect: TLS connection to internal-radsec (... port 2083), TLSv1.3 ... up
sslreadtimeout: SSL: error:0A000126:SSL routines::unexpected eof while reading
closeh: connection to server internal-radsec lost
tlsconnect: TLS connection to internal-radsec (... port 2083), TLSv1.3 ... up
Packet-level verification
I captured the traffic on the FreeRADIUS host to determine which endpoint was actually terminating the session. For one representative connection:
22:24:02.52 TLS handshake / final connection setup traffic
22:24:32.50 <freeradius-container>:2083 > <radsec-peer>:41503 Flags [F.]
The first FIN originates from the FreeRADIUS container. The same sequence was observed repeatedly on separate TCP connections:
~22:23:02 FreeRADIUS FIN
~22:23:32 FreeRADIUS FIN
~22:24:02 FreeRADIUS FIN
~22:24:32 FreeRADIUS FIN
~22:25:02 FreeRADIUS FIN
~22:25:32 FreeRADIUS FIN
~22:26:02 FreeRADIUS FIN
~22:26:32 FreeRADIUS FIN
~22:27:02 FreeRADIUS FIN
~22:27:32 FreeRADIUS FIN
This ruled out radsecproxy initiating the disconnect, and also ruled out a firewall/NAT silently expiring the connectioon since FreeRADIUS itself sends the initial TCP FIN.
A/B test
We then changed only the two relevant values from:
to:
for both the listener and matching RadSec client, and restarted FreeRADIUS.
With that change, the same radsecproxy peer remained connected for more than 17 minutes without the previous EOF / close / reconnect cycle.
Changing the explicit timeout therefore changes the behaviour from:
idle_timeout = 0
-> server closes connection after ~30 seconds
to:
idle_timeout = 900
-> connection remains established beyond the previous 30-second limit
Relevant FreeRADIUS 3.2.10 source
While investigating the behaviour, I found the following logic in src/main/listen.c on the release_3_2_10 branch:
if (sock->limit.lifetime) {
...
} else if (!sock->limit.idle_timeout) {
sock->limit.idle_timeout = 30;
}
This appears to explain the observed behaviour exactly: when both values are zero, the parsed listener state is subsequently normalised to an effective 30-second idle timeout.
However, freeradius -XC continues to display:
lifetime = 0
idle_timeout = 0
so the effective runtime behaviour is not apparent from the configuration check output.
Expected behaviour / question
If idle_timeout = 0 is intended to represent a disabled/unlimited idle timeout, we would expect the RadSec connection to remain open.
If zero is intentionally interpreted as "use the default 30-second timeout", it would be useful for the effective configuration/debug output and the relevant sample configuration/documentation to make that behaviour explicit.
The current combination is particularly confusing because:
- the configured value is
idle_timeout = 0;
freeradius -XC reports idle_timeout = 0;
- the server actually enforces approximately 30 seconds;
- setting an explicit non-zero timeout immediately changes the runtime behaviour.
Impact
The practical impact for long-lived RadSec connections is:
- TLS connections are unnecessarily torn down and re-established every
30 seconds when idle;
- repeated TLS handshake overhead;
- repeated disconnect/reconnect logging on the RadSec peer;
- transport appears unstable despite otherwise healthy connectivity;
- the churn can obscure genuine authentication/RADIUS transport failures.
An explicit non-zero idle_timeout is an effective workaround.
Log output from the FreeRADIUS daemon
Info: Ready to process requests
... adding new socket auth+acct from client (10.208.104.66, 34485) -> (*, 2083, virtual-server=default)
... shutting down socket auth+acct from client (10.208.104.66, 34485) -> (*, 2083, virtual-server=default)
... adding new socket auth+acct from client (10.208.104.66, 42651) -> (*, 2083, virtual-server=default)
... shutting down socket auth+acct from client (10.208.104.66, 42651) -> (*, 2083, virtual-server=default)
# The add/shutdown sequence repeats as the RadSec peer reconnects.
Relevant log output from client utilities
radsecproxy 1.11.2 starting
createlistener: listening for udp on 127.0.0.1:1812
tlsconnect: TLS connection to internal-radsec (... port 2083), TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 up
# approximately 30 seconds later:
sslreadtimeout: SSL: error:0A000126:SSL routines::unexpected eof while reading
closeh: connection to server internal-radsec lost
tlsconnect: TLS connection to internal-radsec (... port 2083), TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 up
# repeats approximately every 30 seconds while idle
The full capture confirms that the first FIN comes from FreeRADIUS, not radsecproxy.
Backtrace from LLDB or GDB
Not applicable; no crash occurs.
What type of defect/bug is this?
Unexpected behaviour (obvious or verified by project member)
How can the issue be reproduced?
Environment
I observed a deterministic 30-second server-side disconnect when an incoming RadSec listener is configured with both
lifetime = 0andidle_timeout = 0. The issue is reproducible independently of RADIUS authentication traffic.The incoming TLS listener is configured as:
We verified that the configuration file actually consumed by the running container contains these values. The enabled TLS site is a symlink to the expected
sites-available/tls; there is no alternate/stale configuration tree involved.freeradius -XCreports the listener as:Packet-level verification
I captured the traffic on the FreeRADIUS host to determine which endpoint was actually terminating the session. For one representative connection:
The first FIN originates from the FreeRADIUS container. The same sequence was observed repeatedly on separate TCP connections:
This ruled out radsecproxy initiating the disconnect, and also ruled out a firewall/NAT silently expiring the connectioon since FreeRADIUS itself sends the initial TCP FIN.
A/B test
We then changed only the two relevant values from:
to:
for both the listener and matching RadSec client, and restarted FreeRADIUS.
With that change, the same radsecproxy peer remained connected for more than 17 minutes without the previous EOF / close / reconnect cycle.
Changing the explicit timeout therefore changes the behaviour from:
to:
Relevant FreeRADIUS 3.2.10 source
While investigating the behaviour, I found the following logic in
src/main/listen.con therelease_3_2_10branch:This appears to explain the observed behaviour exactly: when both values are zero, the parsed listener state is subsequently normalised to an effective 30-second idle timeout.
However,
freeradius -XCcontinues to display:so the effective runtime behaviour is not apparent from the configuration check output.
Expected behaviour / question
If
idle_timeout = 0is intended to represent a disabled/unlimited idle timeout, we would expect the RadSec connection to remain open.If zero is intentionally interpreted as "use the default 30-second timeout", it would be useful for the effective configuration/debug output and the relevant sample configuration/documentation to make that behaviour explicit.
The current combination is particularly confusing because:
idle_timeout = 0;freeradius -XCreportsidle_timeout = 0;Impact
The practical impact for long-lived RadSec connections is:
30 seconds when idle;
An explicit non-zero
idle_timeoutis an effective workaround.Log output from the FreeRADIUS daemon
Relevant log output from client utilities
The full capture confirms that the first FIN comes from FreeRADIUS, not radsecproxy.
Backtrace from LLDB or GDB
Not applicable; no crash occurs.