]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
regenerate from module configuration
authorAlan T. DeKok <aland@freeradius.org>
Thu, 26 Dec 2024 22:32:33 +0000 (17:32 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 26 Dec 2024 22:32:33 +0000 (17:32 -0500)
doc/antora/modules/raddb/pages/mods-available/radius.adoc

index b886e41f6bff3dd9f067bc20498f8a9e84b3a6a6..6905824d22811525f8211a6417839aa02a883a23 100644 (file)
@@ -4,23 +4,87 @@
 
 = 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`.
+The `radius` module in v4 implements RADIUS proxying and
+replication.  In v3, RADIUS proxying is a special kind of
+configuration, with it's own load-balancing, fail-over etc.  That
+configuration is now simpler in v4.  The outbound RADIUS proxying
+is done by just another module: the `radius` module.
+Load-balancing and redundant fail-over are handled by the
+`load-balance` and `redundant` keywords.
+
+In v4, the `radius` module most clearly maps to a `home_server` in
+v4.  The `radius` module typically makes a connection from one
+source IP address to a server at one destination IP/port.  It may
+open multiple source ports, depending on how many packets are being
+proxied.
+
+## Recommendations
+
+In most cases, the v3 configuration be moved to v4 without too many
+problems.  For each `home_server foo { ... }` in v3, create a v4
+module `radius foo { ... } `.  Copy over the IP address, port, and
+secret configuration items.  When this step is finished, the bulk
+of the basic work is done.
+
+Converting a `home_server_pool foo { ... }` can be done by
+creating a module in `mods-enabled`, either `load-balance foo {
+... }`, or `redundant foo { ... }`.  i.e. the v3 module
+configuration does not have any `instantiate` section.  You can
+just list "virtual" modules directly in the `modules` directory!
+
+The contents of the `load-balance` or `redundant` section will be
+the list of home servers which will part of that `load-balance` or
+`redundant` pool.
+
+Then, anywhere you want to use a home server, just list it's name
+in an `unlang` processing section.  Anywhere you want to list a
+home server pool, just list it's name in an `unlang` processing
+section.
+
+Unlike v3, there is no `Proxy-To-Realm` attribute, or
+`Home-Server-Pool`, or `Home-Server-Name`.  Instead, you just
+configure a module (`radius`, or `load-balance`), and then use the
+module anywhere you want to proxy packets.
+
+In most cases, you can just set something like `Auth-Type :=
+example.com`, and then have a section `authenticate example.com {
+... }`, which contains the `radius` modules which do proxying.  See
+link:../../../../../../sites-available/default.adoc[sites-available/default] for sample configuration which uses this
+pattern.
+
+## Behavior
 
-## Configuration Settings
+The module adds a Proxy-State attribute to all proxied packets.
+This `link:https://freeradius.org/rfc/rfc2865.html#Proxy-State[Proxy-State]` contains a 32-bit random number, which is unique
+to this module.  This unique number helps to detect proxy loops.
+
+The reply from home server is appended to the reply list for the
+current packet.
+
+WARNING: For security reasons, the module ensures that all proxied
+`link:https://freeradius.org/rfc/rfc2865.html#Access-Request[Access-Request]` packets contain a `link:https://freeradius.org/rfc/rfc2869.html#Message-Authenticator[Message-Authenticator]`
+attribute.  This behavior is *NOT* configurable, and *CANNOT* be
+changed.  This behavior is part of the BlastRADIUS mitigations.
 
 Any proxied packet (including `link:https://freeradius.org/rfc/rfc2866.html#Accounting-Request[Accounting-Request]`) can
 receive a `Protocol-Error` response packet.  This packet
 is an explicit `NAK` that something went wrong processing
 the request.
 
-WARNING: For security reasons, the module ensures that all proxied
-`link:https://freeradius.org/rfc/rfc2865.html#Access-Request[Access-Request]` packets contain a `link:https://freeradius.org/rfc/rfc2869.html#Message-Authenticator[Message-Authenticator]` attribute.
-This behavior is *NOT* configurable, and *CANNOT* be changed.
+Unlike v3, the server does not support any "pre-proxy" or
+"post-proxy" processing sections.  Similarly, this module does not
+support any "proxy" or "proxy-reply" list.  Instead, the current
+request is proxied as-is, and the proxied reply is added to the
+current reply list.  If you want to modify the proxied request
+and/or proxied reply, then you should use a `subrequest` block to
+create a child request.  That child request can then be modified
+independently of the parent.  Any reply attributes will have to be
+copied back manually to the parent request.
 
-The module adds a Proxy-State attribute to all proxied packets.
-This `link:https://freeradius.org/rfc/rfc2865.html#Proxy-State[Proxy-State]` contains a 32-bit random number, which is unique
-to this module.  This unique number helps to detect proxy loops.
+## Configuration Settings
+
+The configuration settings of this module are similar to the
+`home_server` settings in v3.
 
 The module has the following return codes:
 
@@ -40,7 +104,59 @@ The module has the following return codes:
 |===
 
 
-transport:: Only UDP transport is allowed.
+mode:: What kind of client behavior is being used.
+
+proxy - forward packets which are received from a NAS
+- each packet has a Proxy-State attribute added.
+- it looks for, and stops proxy loops
+       - retransmissions are sent only when the NAS retransmits
+- the module fails if it does not receive a reply
+
+client - originate packet, and do retransmissions ourselves
+- no Proxy-State is added.
+- the module retransmits as needed
+- the module fails if it does not receive a reply
+
+replicate - send packets without waiting for a reply.
+- no Proxy-State is added
+- the module does not expect any reply
+- all replies are discarded
+- the module continues with "ok" immediately after
+ sending the packet.
+
+unconnected-replicate - replicate packets to dynamic destinations
+- For unconnected UDP sockets only.
+     - It MUST have `transport = udp`
+- It MUST have `src_ipaddr = *` and no `src_port`
+- You CANNOT use the module "in place" as with normal proxying.
+- It is only supported via the function %replicate.sendto.ipaddr(ipaddr, port, secret)
+
+dynamic-proxy - proxy packets to dynamic destinations
+- https://tools.ietf.org/html/rfc7585[RFC 7585] dynamic DNS lookups are not supported
+- It MUST have `src_ipaddr = *` and no `src_port`
+- You CANNOT use the module "in place" as with normal proxying.
+- Proxying is only supported via the function %proxy.sendto.ipaddr(ipaddr, port, secret)
+
+The server can still be used to create (i.e. originate)
+packets via this module when `mode = proxy` is set.  The
+module can automatically detect the difference between
+proxied packets and client packets it originates.
+Originated packets are taken from the detail file, or
+result when changing packet type (e.g. Accounting-Request
+to Disconnect-Request), or when the current request is a
+subrequest, and the parent request is from a different
+protocol.
+
+Note that there is no `mode = unconnected`, where the
+module then both proxies packets, and replicates them.  The
+need to track replies when proxying means that it's
+difficult to both proxy and replicate at the same time.  As
+a result, there are two "unconnected" modes, one for each
+of "proxy" and "replicate".
+
+
+
+transport:: Transport protocol.  Can be `udp` or `tcp`.
 
 
 
@@ -52,71 +168,130 @@ 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.
+The module will only send packets types which are listed
+here.  Other types of packets will be ignored.  The main
+purpose of the `type` configuration is to ensure that the
+correct packets are being sent to the home server.  This
+entry serves as a double-check against misconfigurations.
+
+In v3, the `home_server` configuration of `auth`, `acct`,
+or `auth+acct` is used to _find_ a home server.  That is,
+when FreeRADIUS has an `link:https://freeradius.org/rfc/rfc2865.html#Access-Request[Access-Request]` packet in v3, it
+proxies it by looking up a matching `home_server`.
 
-NOTE: `Status-Server` is reserved for `inter-server` signaling,
+In v4, proxying is done by listing the `radius` module in a
+processing section, such as `authenticate radius { ... }`,
+or `recv Accounting-Request { ... }`.  So unlike v3, the
+module doesn't have to _find_ a proxy destination for a
+particular kind of packet.  Instead, the administrator
+_configures_ the module to send packets to a destination.
+
+As a result, the module doesn't really care about what kind
+of packets it sends.  It has a packet, a destination where
+that packet should be sent, and it sends the packet.
+
+In order to change packet types, see the `subrequest` keyword.
+
+NOTE: `Status-Server` is reserved for connection signaling,
 and cannot be proxied.
 
+Unlike v3, all packet types are allocated from the same
+8-bit ID space.  This change does not affect the majority
+of RADIUS proxying, which only sends one type of packet.
+This change does not affect the home server which receives
+these packets, as the home server does not track IDs except
+to correlate requests to replies.
 
+The only visible difference, then, between v3 and v4 is
+that in some cases, the new `radius` module will use more
+source ports when proxying.
 
-replicate:: Whether or not we are replicating packets.
+This change simplifies the implementation of the RADIUS
+client.
 
-Replication is "send proxied request, and continue,
-without waiting for a response".  Any response received
-is discarded, and does not affect packet processing.
 
 
+require_message_authenticator::Require Message-Authenticator
+in responses.
 
-synchronous::
+A server should include Message-Authenticator attribute as
+the first attribute in responses to Access-Request packets.
+This behavior mitigates against the BlastRADIUS attack.
 
-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, not all servers follow this security practice.  As
+a result, this module can be configured to either not
+require, or require, Message-Authenticator.
 
-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`
+If value is `auto`, then the module will automatically
+detect the existence of Message-Authenticator in response
+packets.  Once the module sees a Message-Authenticator, it
+will automatically change the configuration internally to
+`yes`.  This change prevents security "down-bidding"
+attacks.
 
-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.
+Allowed values: yes, no, auto
 
-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 default is `auto`.
 
-NOTE: The behavior in v3 is the same as `synchronous = yes`
 
 
+response_window: If we do not receive any replies within
+this time period, then start `zombie_period`
 
-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.
+zombie_period:: If the home server does not reply to
+packets within `response_window`, then `zombie_period`
+starts.
 
+When `zombie_period` starts, a connection is marked
+`zombie`, and then is not used to send new packets.  If
+there are no responses on this connection within
+`zombie_period`, the module either closes the connection
+(no `status_check` subsection), or starts pinging the home
+server (`status_check.type = Status-Server`).
 
-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.
+revive_interval:: If there are no status checks, mark the
+home server alive after `revive_interval` timeout.
 
-Allowed values: yes, no, auto
+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
 
-The default is "no".
 
 
+### Check the status of a connection
 
 status_check { ... }:: For "are you alive?" queries.
 
@@ -128,12 +303,13 @@ 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
+Status-Server is recommended as other packet types
+may be interpreted incorrectly, or may ve proxied
+to a remote server, which defeats the purpose of
+the status checks.
 
 If you specify another type of packet, it MUST be listed
-as an allowed `type`, above.
+as an allowed `type` above.
 
 
 
@@ -141,8 +317,9 @@ as an allowed `type`, above.
 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.
+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
@@ -163,56 +340,54 @@ changeable after that.
 
 
 
-response_window: If we do not receive a reply within this time period, then
-start `zombie_period`
+## Transport Protocols
 
+The module supports multiple transport protocols.
 
 
-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`).
+### File Output
 
+Write raw RADIUS packets (no IP or UDP header) to a file.
+This transport can only be used for `mode = replicate`
 
 
-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.
+### UDP Transport
 
-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.
+Much like the v3 `home_server` configuration.
 
-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.
+src_ipaddr:: IP we open our socket on.
 
-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
+Destination IP address, port, and secret.
+
+Use `ipv4addr = ...` to force IPv4 addresses.
+Use `ipv6addr = ...` to force IPv6 addresses.
+
+
+
+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.
+
+
+
+### TCP
+
+The TCP configuration is identical to the `udp` configuration.
 
 
 
@@ -345,45 +520,12 @@ the connection.
 
 
 
-## Protocols
-
-For now, only UDP is supported.
-
-udp { ... }:: UDP is configured here.
-
-
-
-NOTE: 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
+## Retransmission timers.
 
 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).
+are the same for all packet types.
 
 
 
@@ -451,18 +593,241 @@ server is alive and responding to requests.
 WARNING: The `Status-Server` packets CANNOT be proxied.
 
 
+
+## Replication of Packets
+
+The module supports replication of packets to new destinations at
+run time.  In this context, replication means "send the packet, and
+do not wait for the response".  This functionality is most useful
+when copying large amounts of accounting data to multiple
+destinations.
+
+The module can then only be used as a dynamic expansion.  That is,
+you cannot specify the `replicate` module directly in a processing
+section.
+
+### Usage
+
+This module can only be used as a dynamic expansion.  Since the
+module does not wait for any response, the expansion does not
+return any value.
+
+The module can be called from any processing section as follows:
+
+
+The function takes three arguments:
+
+
+This function allows the module to send packets to _any_
+destination, where the destination is chosen dynamically at run
+time.  The arguments to the function can be take from other
+attributes, database queries, etc.
+
+
+Generally you only want to replicate accounting packets.
+
+
+
+We are not opening a socket from our server to their
+server.  We are replicating packets.
+
+
+
+For replicated packets, only UDP is supported.
+
+
+
+### UDP Transport
+
+For unconnected modes, only UDP is supported.
+
+
+src_ipaddr:: The source IP address used by the module.
+
+
+
+`src_port` cannot be used.  If it is used here, the
+module will refuse to start.  Instead, the module
+will open a unique source port per thread.
+
+`secret` cannot be used.  If it is used, the value
+will be ignored.
+
+
+
+### Other Configuration
+
+No other configuration items are supported when using
+`mode = unconnected-replicate`.
+
+The `pool` configuration is ignored, as is `status-check`,
+along with all per-packet timeouts.
+
+
+
+A dynamic proxy module
+
+
+
+We are not opening a socket from our server to their
+server.  We are replicating packets.
+
+
+
+Both UDP and TCP are supported.
+
+
+
+### UDP Transport
+
+
+src_ipaddr:: The source IP address used by the module.
+
+
+
+`src_port` cannot be used.  If it is used here, the
+module will refuse to start.  Instead, the module
+will open a unique source port per thread.
+
+`secret` cannot be used.  If it is used, the value
+will be ignored.
+
+
+
+## Connection trunking
+
+See above for documentation on connection trunking.
+
+
+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.
+
+
+
 == Default Configuration
 
 ```
 radius {
+       mode = proxy
        transport = udp
 #      max_attributes = 255
        type = Access-Request
        type = Accounting-Request
-#      replicate = no
-#      synchronous = no
-#      originate = no
        require_message_authenticator = auto
+       response_window = 15
+       zombie_period = 10
+       revive_interval = 3600
        status_check {
                type = Status-Server
 #              update request {
@@ -472,9 +837,22 @@ radius {
 #                      &Event-Timestamp = 0
 #              }
        }
-       response_window = 15
-       zombie_period = 10
-       revive_interval = 3600
+       file {
+            filename = ${logdir}/packets.bin
+       }
+       udp {
+#              src_ipaddr = *
+               ipaddr = 127.0.0.1
+               port = 1812
+               secret = testing123
+#              interface = eth0
+#              max_packet_size = 4096
+#              recv_buff = 1048576
+#              send_buff = 1048576
+       }
+#      tcp {
+#              ...
+#      }
        pool {
                start = 0
                min = 1
@@ -495,16 +873,6 @@ radius {
                        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
@@ -536,4 +904,45 @@ radius {
                max_rtx_duration = 30
        }
 }
+#      %replicate.sendto.ipaddr(127.0.0.1, 1813, 'testing123')
+#      * IP address where the packet is sent.  It MUST be the same
+#        address family as `src_ipaddr` below.
+#      * port where the packet is sent.
+#      * secret for this packet.
+radius replicate {
+       type = Accounting-Request
+       mode = unconnected-replicate
+       transport = udp
+       udp {
+               src_ipaddr = *
+       }
+}
+radius proxy {
+       type = Access-Request
+       mode = dynamic-proxy
+       transport = udp
+       udp {
+               src_ipaddr = *
+       }
+       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
+               }
+       }
+}
 ```