OUR SITES NetworkRADIUS FreeRADIUS

Radius Module

The radius module in v4, can be used to implement proxying and request fan-out, as well as synchronous and asynchronous CoA and DM.

Configuration Settings

Any proxied packet (including Accounting-Request) can receive a Protocol-Error response packet. This packet is an explicit NAK that something went wrong processing the request.

For security reasons, the module ensures that all proxied Access-Request packets contain a Message-Authenticator attribute. This behavior is NOT configurable, and CANNOT be changed.

The module adds a Proxy-State attribute to all proxied packets. This Proxy-State contains a 32-bit random number, which is unique to this module. This unique number helps to detect proxy loops.

The module has the following return codes:

Code Description

invalid

Something went wrong sending the request, or the reply packet is invalid.

ok

the module received an ack (Access-Accept, Accounting-Response, CoA-ACK, etc.)

handled

the module received an Access-Challenge

fail

there was no response to the proxied request

reject

the module received a nak (Access-Reject, CoA-NAK, etc.)

noop

the module saw its own Proxy-State attribute, and is will not proxy the request. This behavior prevents proxy loops.

transport

Only UDP transport is allowed.

max_attributes

Maximum number of attributes to decode in response.

Default is 255.

type

List of allowed packet types.

There is currently no way to change the packet type in the request. See unlang fork for that functionality.

Status-Server is reserved for inter-server signaling, and cannot be proxied.
replicate

Whether or not we are replicating packets.

Replication is "send proxied request, and continue, without waiting for a response". Any response received is discarded, and does not affect packet processing.

synchronous

In many cases, the module should do retransmissions of proxied request on its own. See the various configurations for initial_rtx_time, etc. below. This means setting synchronous = no.

However, in some cases, it is useful to retransmit only when the server receives a retransmission from the NAS. This is done by setting synchronous = yes

In general, if the server is receiving packets directly from a NAS, you should set synchronous = no. This is because the NAS retransmission behavior is horrible, inconsistent, and hard to configure.

If the server is receiving packets from another proxy server, you should set synchronous = yes. This allows the other proxy server to do retransmissions correctly.

The behavior in v3 is the same as synchronous = yes
originate

Whether or not we are creating the packet.

Sometimes we are creating a request that is not for the purpose of proxying another request, in which case we do not want to add a Proxy-State attribute.

In some cases, such as originating a CoA or Disconnect request, including Proxy-State may confuse the receiving NAS.

require_message_authenticator::Require Message-Authenticator in responses.

Including a Message-Authenticator attribute first in response packet, mitigates against the blastradius prefix attack.

If value is auto, then if any packet received from the client contains a valid Message-Authenticator attribute, then the server will require it from all future packets from that client.

Allowed values: yes, no, auto

The default is "no".

status_check { …​ }

For "are you alive?" queries.

If the home server does not respond to proxied packets, the module starts pinging the home server with these packets.

type

You can specify any type of request packet here, e.g. 'Access-Request', 'Accounting-Request' or 'Status-Server'.

Status-Server is recommended as other packet types may be interpreted incorrectly, or proxied to a remote server defeting the purpose of the status check

If you specify another type of packet, it MUST be listed as an allowed type, above.

Status-Server packet contents are fixed and cannot be edited.

For other packet types, you can set the contents here. The section MUST be set over "&request.<attribute> = value", and anything else will cause a parse error.

We RECOMMEND that you use packet contents which lets the other end easily tell that they are not "real" packets from a NAS.

The example here is for Access-Request. The contents will vary by other packet types.

The module will automatically update the contents of the Event-Timestamp attribute to be the time when the packet is sent. The module will also automatically add a Proxy-State attribute.

Do NOT do SQL queries, LDAP queries, dynamic expansions, etc. in this section. The contents are created when a connection is opened, and are not changeable after that.

response_window: If we do not receive a reply within this time period, then start zombie_period

zombie_period

If the home server does not reply to a packet, the zombie_period starts.

The connection is marked zombie, and isn’t used to send new packets. If there are no responses within zombie_period, the server either closes the connection (no status_check subsection), or starts pinging the home server (status_check.type = Status-Server).

revive_interval

If there are no status checks, mark the home server alive after revive_interval timeout.

Some home servers do not support status checks via the Status-Server packet. Others may not have a "test" user configured that can be used to query the server, to see if it is alive. For those servers, we have NO WAY of knowing when it becomes alive again. Therefore, after the server has been marked dead, we wait a period of time, and mark it alive again, in the hope that it has come back to life.

If it has NOT come back to life, then the module will wait for zombie_period before marking it dead again. During the zombie_period, ALL AUTHENTICATIONS WILL FAIL, because the home server is still dead. There is NOTHING that can be done about this, other than to enable the status checks, as documented above.

e.g. if zombie_period is 40 seconds, and revive_interval is 300 seconds, the for 40 seconds out of every 340, or about 10% of the time, all authentications will fail.

If the zombie_period and revive_interval configurations are set smaller, than it is possible for up to 50% of authentications to fail.

As a result, we recommend enabling status checks, and we do NOT recommend using revive_interval.

The revive_interval configuration is used ONLY if the status_check subsection is not used. Otherwise, revive_interval is not necessary, and should be deleted.

Useful range of values: 10 to 3600

Connection trunking

Each worker thread (see radiusd.conf, num_workers), has it’s own set of connections. These connections are grouped together into a "pool".

Much of the configuration here is similar to the old connection "pool" configuration in v3. However, there are more configuration parameters, and therefore more control over the behavior.

start

Connections to create during module instantiation.

If the server cannot create specified number of connections during instantiation it will exit.

Set to 0 to allow the server to start without the database being available.

min

Minimum number of connections to keep open.

max

Maximum number of connections.

If these connections are all in use and a new one is requested, the request will NOT get a connection.

connecting

Maximum number of sockets to have in the "connecting" state.

If a home server goes down, the module will close old / broken connections, and try to open new ones. In order to avoid flooding the home server with connection attempts, set the connecting value to a small number.

uses

number of packets which will use the connection.

After uses packets have been sent the connection will be closed, and a new one opened. For no limits, set uses = 0.

lifetime

lifetime of a connection, in seconds.

After lifetime seconds have passed, no new packets will be sent on the connection. When all replies have been received, the connection will be closed.

For no limits, set lifetime = 0.

It is possible to use precise times, such as lifetime = 1.023, or even qualifiers such as lifetime = 400ms.

open_delay

How long (in seconds) a connection must be above per_connection_target before a new connection is opened.

Parsing of this field is the same as for lifetime.

close_delay

How long (in seconds) a connection must be below per_connection_target before a connection is closed.

manage_interval

How often (in seconds) the connections are checked for limits, in order to open / close connections.

connection { …​ }

Per-connection configuration.

connection_timeout

How long to wait before giving up on a connection which is being opened.

reconnect_delay

If opening a connection fails, or an open connection fails, we wait reconnect_delay seconds before attempting to open another connection.

request { …​ }

Per-request configuration.

per_connection_max

The maximum number of requests which are "live" on a particular connection.

per_connection_target

The target number of requests which are "live" on a particular connection.

There can be a balance between overloading a connection, and under-utilizing it. The default is to fill each connection before opening a new one.

free_delay

How long to wait before freeing internal resources associated with the connection.

Protocols

For now, only UDP is supported.

udp { …​ }

UDP is configured here.

Don’t change anything if you are not sure.
interface

Interface to bind to.

max_packet_size

Our max packet size. may be different from the parent.

recv_buff

How big the kernel’s receive buffer should be.

send_buff

How big the kernel’s send buffer should be.

src_ipaddr

IP we open our socket on.

Packets

Each packet can have its own retransmission timers.

The sections are named for each packet type. The contents are the same for all packet types. Only the relevant ones are parsed (see type above).

Access requests packets

initial_rtx_time

If there is no response within this time, the module will retransmit the packet.

Value should be 1..5.

max_rtx_time

The maximum time between retransmissions.

Value should be 5..30

  • The following are maximums that all apply.

i.e. if any one of the limits is hit, the retransmission stops.

max_rtx_count

How many times the module will send the packet before giving up.

Value should be 1..20 (0 == retransmit forever)

max_rtx_duration

The total length of time the module will try to retransmit the packet.

Value should be 5..60

Accounting Packets

i.e. If you want retransmit forever, you should set:

max_rtx_time = 0
max_rtx_count = 0

CoA Packets

Disconnect packets

Status-Server packets

The configuration here helps the module determine if a home server is alive and responding to requests.

The Status-Server packets CANNOT be proxied.

Default Configuration

radius {
	transport = udp
#	max_attributes = 255
	type = Access-Request
	type = Accounting-Request
#	replicate = no
#	synchronous = no
#	originate = no
	require_message_authenticator = auto
	status_check {
		type = Status-Server
#		update request {
#			&User-Name := "test-user"
#			&User-Password := "this-is-not-a-real-password"
#			&NAS-Identifier := "Status check.  Are you alive?"
#			&Event-Timestamp = 0
#		}
	}
	response_window = 15
	zombie_period = 10
	revive_interval = 3600
	pool {
		start = 0
		min = 1
		max = 8
		connecting = 1
		uses = 0
		lifetime = 0
		open_delay = 0.2
		close_delay = 1.0
		manage_interval = 0.2
		connection {
			connection_timeout = 3.0
			reconnect_delay = 5
		}
		request {
			per_connection_max = 255
			per_connection_target = 255
			free_delay = 10
		}
	}
	udp {
		ipaddr = 127.0.0.1
		port = 1812
		secret = testing123
#		interface = eth0
#		max_packet_size = 4096
#		recv_buff = 1048576
#		send_buff = 1048576
#		src_ipaddr = ""
	}
	Access-Request {
		initial_rtx_time = 2
		max_rtx_time = 16
		max_rtx_count = 2
		max_rtx_duration = 30
	}
	Accounting-Request {
		initial_rtx_time = 2
		max_rtx_time = 16
		max_rtx_count = 5
		max_rtx_duration = 30
	}
	CoA-Request {
		initial_rtx_time = 2
		max_rtx_time = 16
		max_rtx_count = 5
		max_rtx_duration = 30
	}
	Disconnect-Request {
		initial_rtx_time = 2
		max_rtx_time = 16
		max_rtx_count = 5
		max_rtx_duration = 30
	}
	Status-Server {
		initial_rtx_time = 2
		max_rtx_time = 5
		max_rtx_count = 5
		max_rtx_duration = 30
	}
}