SkillAgentSearch skills...

Eradius

Erlang RADIUS server framework

Install / Use

/learn @travelping/Eradius
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

eradius

[![Hex.pm Version][hexpm version]][hexpm] [![Hex.pm Downloads][hexpm downloads]][hexpm] [![Build Status][gh badge]][gh] [![Erlang Versions][erlang version badge]][gh]

This fork of eradius is a radical deviation from the original Jungerl code. It contains a generic RADIUS client, support for several authentication mechanisms and dynamic configuration (it implements the config_change/3 application callback).

Contents

Erlang Version Support

All minor version of the current major release and the highest minor version of the previous major release will be supported. At the moment this means OTP 21.3, OTP 22.x, OTP 23.x and OTP 24.x are supported. OTP versions before 21.0 do not work due the use of logger. When in doubt check the otp_release section in main.yml for tested versions.

Building eradius

$ rebar3 compile

Using eradius

Eradius requires a certain degree of configuration which is described in the app.src file. Minimal examples of server callbacks can be found in the tests.

Run sample server

$ cd sample
$ rebar3 shell --config example.config --apps eradius_server_sample

Then run a simple benchmark:

1> eradius_server_sample:test().
...
13:40:43.979 [info] 127.0.0.1:59254 [8]: Access-Accept
13:40:43.979 [info] 127.0.0.1:59254 [6]: Access-Accept
13:40:43.980 [info] 127.0.0.1:59254 [3]: Access-Accept
13:40:43.980 [info] 127.0.0.1:59254 [0]: Access-Accept
4333.788381 req/sec.
ok

Metrics

Eradius exposes following metrics via exometer:

  • counter and handle time for requests
  • counter for responses (this includes acks, naks, accepts etc.)

The measurements are available for client, server and also for the specific NAS callbacks. Further they are exposed in a 'total' fashion but also itemized by request/response type (e.g. access request, accounting response etc.).

It is possible to expose measurements compliant with RFC 2619 and RFC 2621 using the build in metrics.

The handle time metrics are generated internally using histograms. These histograms all have a time span of 60s. The precise metrics are defined in include/eradius_metrics.hrl.

See more in METRICS.md.

RADIUS server configuration

:warning: Notes :warning:

  • Square brackets ([]) denote an array that consists of n comma-separated objects.
  • Curly brackets ({}) denote a tuple that consists of a defined number of objects.

Servers in this configuration are endpoints consisting of an IPv4 address and one or more ports.
servers is a list [] of said endpoints:

servers == { servers, [<Server>] }

Each server is tuple ({}):

Server == { <SymbolicName>, { <IP>, [<Ports>] } } | { <SymbolicName>, { <IP>, [<Ports>], <ExtraSocketOptions> } }
ExtraServerOptions == [<ServerOption>]
ExtraSocketOptions == [{socket_opts, [socket_setopt()]}] (see: https://erlang.org/doc/man/inet.html#setopts-2)
ServerOption == {rate_config, <SymbolicNameLimit> | <RateConfigList>}

Rate configuration can be configured per server, in extra configuration, with a symbolic name or directly in server

{SymbolicNameLimit, RateConfigList}
RateConfigList == [<RateOption>]
RateOption == { limit | max_size | max_time, integer() | undefined }

Each server is assigned a list of handlers. This list defines the NASes that are allowed to send RADIUS requests to a server and which handler is to process the request.

Handler assignment: {<SymbolicName>, [<Handlers>]}

SymbolicName == Reference to a previously defined server.
Handler == { <HandlerDefinition>, [<Sources>] }

If only one handler module is used, it can be defined globally as {radius_callback, <HandlerMod>}. If more than one handler modules are used, they have to be given in the HandlerDefinition:

HandlerDefinition == {<HandlerMod>, <NasId>, <HandlerArgs>} | {<NasId>, <HandlerArgs>}
HandlerMod == Handler module to process the received requests.
NasId == String describing the Source.
HandlerArgs == List of arguments givent the handler module.
Source == {<IP>, <Secret>} | {<IP>, <Secret>, [<SourceOption>]}
SourceOption == {group, <GroupName>} | {nas_id, <NasId> }

IP == IPv4 source address.
Secret == Binary. Passphrase, the NAS authenticates with.
GroupName:
RADIUS requests received by a server are forwarded to lists of nodes.
The lists are assigned to handlers, so the RADIUS requests of every handler can be forwarded to different nodes, if necessary.
The lists are referenced by a GroupName. If only one group is defined, the GroupName can be omitted.
In this case, all handlers forward their requests to the same list of nodes.
Session nodes == {session_nodes, ['node@host', ...]} | {session_nodes, [{<GroupName>, ['node@host', ...]}]}

eradius configuration example 1

All requests are forwarded to the same globally defined list of nodes. Only one handler module is used.

[{eradius, [
    {session_nodes, ['node1@host1', 'node2@host2']},
    {radius_callback, tposs_pcrf_radius},
    {servers, [
        {root, {"127.0.0.1", [1812, 1813]}}
    ]},
    {root, [
        {
            {"NAS1", [handler_arg1, handler_arg2]},
            [ {"10.18.14.2", <<"secret1">>} ]
        },
        {
            {"NAS2", [handler_arg1, handler_arg2]},
            [ {"10.18.14.3", <<"secret2">>, [{nas_id, <<"name">>}]} ]
        }
    ]}
]}]

eradius configuration example 2

Requests of different sources are forwarded to different nodes. Different handlers are used for the sources.

[{eradius, [
    {session_nodes, [
        {"NodeGroup1", ['node1@host1', 'node2@host2']},
        {"NodeGroup2", ['node3@host3', 'node4@host4']}
    ]},
    {servers, [
        {root, {"127.0.0.1", [1812, 1813]}}
    ]},
    {root, [
        {
            {tposs_pcrf_handler1, "NAS1", [handler_arg1, handler_arg2]},
            [ {"10.18.14.2", <<"secret1">>, [{group, "NodeGroup1"}]} ]
        },
        {
            {tposs_pcrf_handler2, "NAS2", [handler_arg3, handler_arg4]},
            [ {"10.18.14.3", <<"secret2">>, [{group, "NodeGroup2"}]} ]
        }
    ]}
]}]

eradius configuration example 3

Requests of different sources are forwarded to different nodes. Different handlers are used for the sources.

[{eradius, [
    {session_nodes, [
        {"NodeGroup1", ['node1@host1', 'node2@host2']},
        {"NodeGroup2", ['node3@host3', 'node4@host4']}
    ]},
    {servers, [
        {root, {"127.0.0.1", [1812, 1813], [{socket_opts, [{recbuf, 8192},
                                                           {sndbuf, 131072},
                                                           {netns, "/var/run/netns/myns"}]}]}}
    ]},
    {root, [
        {
            {tposs_pcrf_handler1, "NAS1", [handler_arg1, handler_arg2]},
            [ {"10.18.14.2", <<"secret1">>, [{group, "NodeGroup1"}]} ]
        },
        {
            {tposs_pcrf_handler2, "NAS2", [handler_arg3, handler_arg4]},
            [ {"10.18.14.3", <<"secret2">>, [{group, "NodeGroup2"}]} ]
        }
    ]}
]}]

eradius configuration example 4

Example of full configuration with keys which can use in eradius:

[{eradius, [
    %% The IP address used to send RADIUS requests
    {client_ip, {127, 0, 0, 1}},
    %% The maximum number of open ports that will be used by RADIUS clients
    {client_ports, 256},
    %% how long the binary response is kept before re-sending it
    {resend_timeout, 500},
    %% List of RADIUS dictionaries
    {tables, [dictionary]},
    %% List of nodes where RADIUS requests possibly will be forwarded by a RADIUS server
    {session_nodes, local},
    %% A RADIUS requests handler callback module
    {radius_callback, eradius_server_sample},
    %% NAS specified for `root` RADIUS server
    {root, [
        {{"root", []}, [{"127.0.0.1", "secret"}]}
    ]},
    %% NAS specified for `acct` RADIUS server
    {acct, [
        {{eradius_proxy, "radius_acct", [{default_route, {{127, 0, 0, 2}, 1813, <<"secret">>}, [{pool, pool_name}, {timeout, 5000}, {retries, 3}]]},
        [{"127.0.0.1", "secret"}]}
    ]},
    %% List of RADIUS servers
    {servers, [
        {root, {"127.0.0.1", [1812]}},
        {acct, {"127.0.0.1", [1813]}}
    ]},
    {counter_aggregator, false},
    %% List of histogram buckets for RADIUS servers metrics
    {histogram_buckets, [10, 30, 50, 75, 100, 1000, 2000]},
    %% Simple file-based logging of RADIUS requests and metadata
    {logging, true},
    %% Path to log file
    {logfile, "./radius.log"},
    %% List of upstream RADIUS servers pools
    {servers_pool, [
        {pool_name, [
            {{127, 0, 0, 2}, 1812, <<"secret">>, [{retries, 3}]},
            {{127, 0, 0, 3}, 1812, <<"secret">>}
        ]}
    ]},
    {server_status_metrics_enabled, false},
    {counter_aggregator, false},
    %% Size of RADIUS receive buffer
    {recbuf, 8192},
    %% The minimum size of the send buffer to use for the RADIUS
    {sndbuf, 131072}
]}].

Support of failover for client

Added support for

Related Skills

View on GitHub
GitHub Stars62
CategoryDevelopment
Updated4d ago
Forks45

Languages

Erlang

Security Score

100/100

Audited on Apr 4, 2026

No findings