From 35e0f2f419502934ac7d88ade9cdf78da0df123e Mon Sep 17 00:00:00 2001 From: "noussair.hamrit" Date: Tue, 3 Feb 2026 11:56:24 +0100 Subject: [PATCH] feat(freeradius): add radius.conf and queries.conf ConfigMaps and bump chart version - Move FreeRADIUS SQL and radius.conf into ConfigMaps - Add /etc/freeradius/mods-config/sql/main/mysql/queries.conf and /etc/freeradius/radius.conf templates for Helm deployment - Update SQL post-auth query formatting - Enable suppress_secrets in radius.conf - Bump Helm chart version to 1.0.10 - Adjust GitLab CI and Deployment to use new config structure --- .gitignore | 1 + .gitlab-ci.yml | 2 +- Chart.lock | 7 +- Chart.yaml | 6 +- files/mods-config/queries.conf | 693 ++++++++++++++++ files/radius.conf | 1143 ++++++++++++++++++++++++++ templates/ConfigMap/mods-config.yaml | 19 + templates/ConfigMap/radius-conf.yaml | 19 + templates/Deployment.yaml | 12 + 9 files changed, 1891 insertions(+), 11 deletions(-) create mode 100644 .gitignore create mode 100644 files/mods-config/queries.conf create mode 100644 files/radius.conf create mode 100644 templates/ConfigMap/mods-config.yaml create mode 100644 templates/ConfigMap/radius-conf.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..711a39c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +charts/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7cd6c21..e545c41 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,7 +8,7 @@ stages: variables: CHART_NAME: "freeradius" - CHART_VERSION: "1.0.9" + CHART_VERSION: "1.0.10" PACKAGE_PATH: "packages" ST_COMMON_PROJECT_ID: "270" COMMON_PROJECT_URL: "${CI_API_V4_URL}/projects/${ST_COMMON_PROJECT_ID}/packages/helm/stable" diff --git a/Chart.lock b/Chart.lock index 6650a49..49924ab 100644 --- a/Chart.lock +++ b/Chart.lock @@ -2,8 +2,5 @@ dependencies: - name: st-common repository: https://gitlab/api/v4/projects/270/packages/helm/stable version: 0.1.12 -- name: mariadb - repository: oci://registry-1.docker.io/bitnamicharts - version: 20.5.9 -digest: sha256:55c375d2786b3554c8e0d35dfe1e2fb4c6d67d2ba7ee5cbcdc7c3e0a9c564d01 -generated: "2025-11-25T11:46:23.835203402+01:00" +digest: sha256:effc27041fec14dd47ce67b96daae936455482afe0a2d3d6069ebffd7e33ba2c +generated: "2026-02-03T12:45:51.347388527+01:00" diff --git a/Chart.yaml b/Chart.yaml index f06dcde..e2e2b55 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -6,10 +6,6 @@ dependencies: - name: st-common repository: https://gitlab/api/v4/projects/270/packages/helm/stable version: 0.1.12 -- condition: mariadb.enabled - name: mariadb - repository: oci://registry-1.docker.io/bitnamicharts - version: 20.x.x description: FreeRADIUS is a modular, high performance free RADIUS suite developed and distributed under the GNU General Public License, version 2, and is free for download and use. @@ -31,4 +27,4 @@ sources: - https://freeradius.org/ - https://github.com/FreeRADIUS/freeradius-server type: application -version: 1.0.9 +version: 1.0.10 diff --git a/files/mods-config/queries.conf b/files/mods-config/queries.conf new file mode 100644 index 0000000..7100bbf --- /dev/null +++ b/files/mods-config/queries.conf @@ -0,0 +1,693 @@ +# -*- text -*- +# +# main/mysql/queries.conf-- MySQL configuration for default schema (schema.sql) +# +# $Id: b31ae9c3a1bf41f030a2112d31bf3a678e76f23c $ + +# Use the driver specific SQL escape method. +# +# If you enable this configuration item, the "safe_characters" +# configuration is ignored. FreeRADIUS then uses the MySQL escape +# functions to escape input strings. The only downside to making this +# change is that the MySQL escaping method is not the same the one +# used by FreeRADIUS. So characters which are NOT in the +# "safe_characters" list will now be stored differently in the database. +# +#auto_escape = yes + +# Safe characters list for sql queries. Everything else is replaced +# with their mime-encoded equivalents. +# The default list should be ok +# Using 'auto_escape' is preferred +safe_characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /" + +####################################################################### +# Connection config +####################################################################### +# The character set is not configurable. The default character set of +# the mysql client library is used. To control the character set, +# create/edit my.cnf (typically in /etc/mysql/my.cnf or /etc/my.cnf) +# and enter +# [freeradius] +# default-character-set = utf8 +# + +####################################################################### +# Query config: Username +####################################################################### +# This is the username that will get substituted, escaped, and added +# as attribute 'SQL-User-Name'. '%{SQL-User-Name}' should be used below +# everywhere a username substitution is needed so you you can be sure +# the username passed from the client is escaped properly. +# +# Uncomment the next line, if you want the sql_user_name to mean: +# +# Use Stripped-User-Name, if it's there. +# Else use User-Name, if it's there, +# Else use hard-coded string "DEFAULT" as the user name. +#sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}" +# +sql_user_name = "%{User-Name}" + +####################################################################### +# Query config: Event-Timestamp +####################################################################### +# event_timestamp_epoch is the basis for the time inserted into +# accounting records. Typically this will be the Event-Timestamp of the +# accounting request, which is usually provided by a NAS. +# +# Uncomment the next line, if you want the timestamp to be based on the +# request reception time recorded by this server, for example if you +# distrust the provided Event-Timestamp. +#event_timestamp_epoch = "%l" + +event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}" + +# event_timestamp is the SQL snippet for converting an epoch timestamp +# to an SQL date. + +event_timestamp = "FROM_UNIXTIME(${event_timestamp_epoch})" + +####################################################################### +# Query config: Class attribute +####################################################################### +# +# 3.0.22 and later have a "class" column in the accounting table. +# +# However, we do NOT want to break existing configurations by adding +# the Class attribute to the default queries. If we did that, then +# systems using newer versions of the server would fail, because +# there is no "class" column in their accounting tables. +# +# The solution to that is the following "class" subsection. If your +# database has a "class" column for the various tables, then you can +# uncomment the configuration items here. The queries below will +# then automatically insert the Class attribute into radacct, +# radpostauth, etc. +# +class { + # + # Delete the '#' character from each of the configuration + # items in this section. This change puts the Class + # attribute into the various tables. Leave the double-quoted + # string there, as the value for the configuration item. + # + # See also policy.d/accounting, and the "insert_acct_class" + # policy. You will need to list (or uncomment) + # "insert_acct_class" in the "post-auth" section in order to + # create a Class attribute. + # + column_name = # ", class" + packet_xlat = # ", '%{Class}'" + reply_xlat = # ", '%{reply:Class}'" +} + +####################################################################### +# Default profile +####################################################################### +# This is the default profile. It is found in SQL by group membership. +# That means that this profile must be a member of at least one group +# which will contain the corresponding check and reply items. +# This profile will be queried in the authorize section for every user. +# The point is to assign all users a default profile without having to +# manually add each one to a group that will contain the profile. +# The SQL module will also honor the User-Profile attribute. This +# attribute can be set anywhere in the authorize section (ie the users +# file). It is found exactly as the default profile is found. +# If it is set then it will *overwrite* the default profile setting. +# The idea is to select profiles based on checks on the incoming packets, +# not on user group membership. For example: +# -- users file -- +# DEFAULT Service-Type == Outbound-User, User-Profile := "outbound" +# DEFAULT Service-Type == Framed-User, User-Profile := "framed" +# +# By default the default_user_profile is not set +# +#default_user_profile = "DEFAULT" + +####################################################################### +# NAS Query +####################################################################### +# This query retrieves the radius clients +# +# 0. Row ID (currently unused) +# 1. Name (or IP address) +# 2. Shortname +# 3. Type +# 4. Secret +# 5. Server +####################################################################### + +client_query = "\ + SELECT id, nasname, shortname, type, secret, server \ + FROM ${client_table}" + +####################################################################### +# Authorization Queries +####################################################################### +# These queries compare the check items for the user +# in ${authcheck_table} and setup the reply items in +# ${authreply_table}. You can use any query/tables +# you want, but the return data for each row MUST +# be in the following order: +# +# 0. Row ID (currently unused) +# 1. UserName/GroupName +# 2. Item Attr Name +# 3. Item Attr Value +# 4. Item Attr Operation +####################################################################### +# Use these for case sensitive usernames. + +#authorize_check_query = "\ +# SELECT id, username, attribute, value, op \ +# FROM ${authcheck_table} \ +# WHERE username = BINARY '%{SQL-User-Name}' \ +# ORDER BY id" + +#authorize_reply_query = "\ +# SELECT id, username, attribute, value, op \ +# FROM ${authreply_table} \ +# WHERE username = BINARY '%{SQL-User-Name}' \ +# ORDER BY id" + +# +# The default queries are case insensitive. (for compatibility with +# older versions of FreeRADIUS) +# +authorize_check_query = "\ + SELECT id, username, attribute, value, op \ + FROM ${authcheck_table} \ + WHERE username = '%{SQL-User-Name}' \ + ORDER BY id" + +authorize_reply_query = "\ + SELECT id, username, attribute, value, op \ + FROM ${authreply_table} \ + WHERE username = '%{SQL-User-Name}' \ + ORDER BY id" + +# +# Use these for case sensitive usernames. +# +#group_membership_query = "\ +# SELECT groupname \ +# FROM ${usergroup_table} \ +# WHERE username = BINARY '%{SQL-User-Name}' \ +# ORDER BY priority" + +group_membership_query = "\ + SELECT groupname \ + FROM ${usergroup_table} \ + WHERE username = '%{SQL-User-Name}' \ + ORDER BY priority" + +authorize_group_check_query = "\ + SELECT id, groupname, attribute, \ + Value, op \ + FROM ${groupcheck_table} \ + WHERE groupname = '%{${group_attribute}}' \ + ORDER BY id" + +authorize_group_reply_query = "\ + SELECT id, groupname, attribute, \ + value, op \ + FROM ${groupreply_table} \ + WHERE groupname = '%{${group_attribute}}' \ + ORDER BY id" + +####################################################################### +# Simultaneous Use Checking Queries +####################################################################### +# simul_count_query - query for the number of current connections +# - If this is not defined, no simultaneous use checking +# - will be performed by this module instance +# simul_verify_query - query to return details of current connections +# for verification +# - Leave blank or commented out to disable verification step +# - Note that the returned field order should not be changed. +# +# Note: Sessions that started prior to the most recent reload of their NAS will +# be correctly considered inactive, even if the radacct entry itself is not +# marked as stopped. +# +####################################################################### + +simul_count_query = "\ + SELECT COUNT(*) \ + FROM ${acct_table1} a \ + LEFT OUTER JOIN nasreload n USING (nasipaddress) \ + WHERE username = '%{SQL-User-Name}' \ + AND acctstoptime IS NULL \ + AND (a.acctstarttime > n.reloadtime OR n.reloadtime IS NULL)" + +simul_verify_query = "\ + SELECT \ + radacctid, acctsessionid, username, nasipaddress, nasportid, framedipaddress, \ + callingstationid, framedprotocol \ + FROM ${acct_table1} a \ + LEFT OUTER JOIN nasreload n USING (nasipaddress) \ + WHERE username = '%{SQL-User-Name}' \ + AND acctstoptime IS NULL \ + AND (a.acctstarttime > n.reloadtime OR n.reloadtime IS NULL)" + +####################################################################### +# Accounting and Post-Auth Queries +####################################################################### +# These queries insert/update accounting and authentication records. +# The query to use is determined by the value of 'reference'. +# This value is used as a configuration path and should resolve to one +# or more 'query's. If reference points to multiple queries, and a query +# fails, the next query is executed. +# +# Behaviour is identical to the old 1.x/2.x module, except we can now +# fail between N queries, and query selection can be based on any +# combination of attributes, or custom 'Acct-Status-Type' values. +####################################################################### +accounting { + reference = "%{tolower:type.%{%{Acct-Status-Type}:-%{Request-Processing-Stage}}.query}" + + # Write SQL queries to a logfile. This is potentially useful for bulk inserts + # when used with the rlm_sql_null driver. +# logfile = ${logdir}/accounting.sql + + column_list = "\ + acctsessionid, acctuniqueid, username, \ + realm, nasipaddress, nasportid, \ + nasporttype, acctstarttime, acctupdatetime, \ + acctstoptime, acctsessiontime, acctauthentic, \ + connectinfo_start, connectinfo_stop, acctinputoctets, \ + acctoutputoctets, calledstationid, callingstationid, \ + acctterminatecause, servicetype, framedprotocol, \ + framedipaddress, framedipv6address, framedipv6prefix, \ + framedinterfaceid, delegatedipv6prefix ${..class.column_name}" + + type { + accounting-on { + + # + # "Bulk update" Accounting-On/Off strategy. + # + # Immediately terminate all sessions associated with a + # given NAS. + # + # Note: If a large number of sessions require closing + # then the bulk update may be take a long time to run + # and lock an excessive number of rows. See the + # strategy below for an alternative approach that does + # not touch the radacct session data. + # + query = "\ + UPDATE ${....acct_table1} \ + SET \ + acctstoptime = ${....event_timestamp}, \ + acctsessiontime = '${....event_timestamp_epoch}' \ + - UNIX_TIMESTAMP(acctstarttime), \ + acctterminatecause = '%{%{Acct-Terminate-Cause}:-NAS-Reboot}' \ + WHERE acctstoptime IS NULL \ + AND nasipaddress = '%{NAS-IP-Address}' \ + AND acctstarttime <= ${....event_timestamp}" + + # + # "Lightweight" Accounting-On/Off strategy. + # + # Record the reload time of the NAS and let the + # administrator actually close the sessions in radacct + # out-of-band, if desired. + # + # Implementation advice, together with a stored + # procedure for closing sessions and a view showing + # the effective stop time of each session is provided + # in process-radacct.sql. + # + # To enable this strategy, just change the previous + # query to "-query", and this one to "query". The + # previous one will be ignored, and this one will be + # enabled. + # + -query = "\ + INSERT INTO nasreload \ + SET \ + nasipaddress = '%{NAS-IP-Address}', \ + reloadtime = ${....event_timestamp} \ + ON DUPLICATE KEY UPDATE reloadtime = ${....event_timestamp}" + + } + + accounting-off { + query = "${..accounting-on.query}" + } + + # + # Implement the "sql_session_start" policy. + # See raddb/policy.d/accounting for more details. + # + # You also need to fix the other queries as + # documented below. Look for "sql_session_start". + # + post-auth { + query = "\ + INSERT INTO ${....acct_table1} \ + (${...column_list}) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ + NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ + '%{NAS-Port-Type}', \ + ${....event_timestamp}, \ + ${....event_timestamp}, \ + NULL, \ + 0, \ + '', \ + '%{Connect-Info}', \ + NULL, \ + 0, \ + 0, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + NULL, \ + '', \ + '', \ + '', \ + '', \ + '' \ + ${....class.packet_xlat})" + + query = "\ + UPDATE ${....acct_table1} SET \ + AcctStartTime = ${....event_timestamp}, \ + AcctUpdateTime = ${....event_timestamp}, \ + ConnectInfo_start = '%{Connect-Info}', \ + AcctSessionId = '%{Acct-Session-Id}' \ + WHERE UserName = '%{SQL-User-Name}' \ + AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ + AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \ + AND NASPortType = '%{NAS-Port-Type}' \ + AND AcctStopTime IS NULL" + } + + start { + # + # Insert a new record into the sessions table + # + query = "\ + INSERT INTO ${....acct_table1} \ + (${...column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ + '%{NAS-Port-Type}', \ + ${....event_timestamp}, \ + ${....event_timestamp}, \ + NULL, \ + '0', \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '0', \ + '0', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}' \ + ${....class.packet_xlat})" + + # + # When using "sql_session_start", you should comment out + # the previous query, and enable this one. + # + # Just change the previous query to "-query", + # and this one to "query". The previous one + # will be ignored, and this one will be + # enabled. + # + -query = "\ + UPDATE ${....acct_table1} \ + SET \ + AcctSessionId = '%{Acct-Session-Id}', \ + AcctUniqueId = '%{Acct-Unique-Session-Id}', \ + AcctAuthentic = '%{Acct-Authentic}', \ + ConnectInfo_start = '%{Connect-Info}', \ + ServiceType = '%{Service-Type}', \ + FramedProtocol = '%{Framed-Protocol}', \ + framedipaddress = '%{Framed-IP-Address}', \ + framedipv6address = '%{Framed-IPv6-Address}', \ + framedipv6prefix = '%{Framed-IPv6-Prefix}', \ + framedinterfaceid = '%{Framed-Interface-Id}', \ + delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ + AcctStartTime = ${....event_timestamp}, \ + AcctUpdateTime = ${....event_timestamp} \ + WHERE UserName = '%{SQL-User-Name}' \ + AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ + AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \ + AND NASPortType = '%{NAS-Port-Type}' \ + AND AcctStopTime IS NULL" + + # + # Key constraints prevented us from inserting a new session, + # use the alternate query to update an existing session. + # + query = "\ + UPDATE ${....acct_table1} SET \ + acctstarttime = ${....event_timestamp}, \ + acctupdatetime = ${....event_timestamp}, \ + connectinfo_start = '%{Connect-Info}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + + } + + interim-update { + # + # Update an existing session and calculate the interval + # between the last data we received for the session and this + # update. This can be used to find stale sessions. + # + query = "\ + UPDATE ${....acct_table1} \ + SET \ + acctupdatetime = (@acctupdatetime_old:=acctupdatetime), \ + acctupdatetime = ${....event_timestamp}, \ + acctinterval = ${....event_timestamp_epoch} - \ + UNIX_TIMESTAMP(@acctupdatetime_old), \ + framedipaddress = '%{Framed-IP-Address}', \ + framedipv6address = '%{Framed-IPv6-Address}', \ + framedipv6prefix = '%{Framed-IPv6-Prefix}', \ + framedinterfaceid = '%{Framed-Interface-Id}', \ + delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ + acctsessiontime = %{%{Acct-Session-Time}:-NULL}, \ + acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Input-Octets}:-0}', \ + acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Output-Octets}:-0}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + + # + # The update condition matched no existing sessions. Use + # the values provided in the update to create a new session. + # + query = "\ + INSERT INTO ${....acct_table1} \ + (${...column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ + '%{NAS-Port-Type}', \ + FROM_UNIXTIME(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ + ${....event_timestamp}, \ + NULL, \ + %{%{Acct-Session-Time}:-NULL}, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '%{%{Acct-Input-Gigawords}:-0}' << 32 | '%{%{Acct-Input-Octets}:-0}', \ + '%{%{Acct-Output-Gigawords}:-0}' << 32 | '%{%{Acct-Output-Octets}:-0}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}' \ + ${....class.packet_xlat})" + + # + # When using "sql_session_start", you should comment out + # the previous query, and enable this one. + # + # Just change the previous query to "-query", + # and this one to "query". The previous one + # will be ignored, and this one will be + # enabled. + # + -query = "\ + UPDATE ${....acct_table1} \ + SET \ + AcctSessionId = '%{Acct-Session-Id}', \ + AcctUniqueId = '%{Acct-Unique-Session-Id}', \ + AcctAuthentic = '%{Acct-Authentic}', \ + ConnectInfo_start = '%{Connect-Info}', \ + ServiceType = '%{Service-Type}', \ + FramedProtocol = '%{Framed-Protocol}', \ + framedipaddress = '%{Framed-IP-Address}', \ + framedipv6address = '%{Framed-IPv6-Address}', \ + framedipv6prefix = '%{Framed-IPv6-Prefix}', \ + framedinterfaceid = '%{Framed-Interface-Id}', \ + delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ + AcctUpdateTime = ${....event_timestamp}, \ + AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \ + AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Input-Octets}:-0}', \ + AcctOutputOctets = '%{%{Acct-Output-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Output-Octets}:-0}' \ + WHERE UserName = '%{SQL-User-Name}' \ + AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ + AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \ + AND NASPortType = '%{NAS-Port-Type}' \ + AND AcctStopTime IS NULL" + + } + + stop { + # + # Session has terminated, update the stop time and statistics. + # + query = "\ + UPDATE ${....acct_table2} SET \ + acctstoptime = ${....event_timestamp}, \ + acctsessiontime = %{%{Acct-Session-Time}:-NULL}, \ + acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Input-Octets}:-0}', \ + acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Output-Octets}:-0}', \ + acctterminatecause = '%{Acct-Terminate-Cause}', \ + connectinfo_stop = '%{Connect-Info}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + + # + # The update condition matched no existing sessions. Use + # the values provided in the update to create a new session. + # + query = "\ + INSERT INTO ${....acct_table2} \ + (${...column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ + '%{NAS-Port-Type}', \ + FROM_UNIXTIME(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ + ${....event_timestamp}, \ + ${....event_timestamp}, \ + %{%{Acct-Session-Time}:-NULL}, \ + '%{Acct-Authentic}', \ + '', \ + '%{Connect-Info}', \ + '%{%{Acct-Input-Gigawords}:-0}' << 32 | '%{%{Acct-Input-Octets}:-0}', \ + '%{%{Acct-Output-Gigawords}:-0}' << 32 | '%{%{Acct-Output-Octets}:-0}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Acct-Terminate-Cause}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}' \ + ${....class.packet_xlat})" + + # + # When using "sql_session_start", you should comment out + # the previous query, and enable this one. + # + # Just change the previous query to "-query", + # and this one to "query". The previous one + # will be ignored, and this one will be + # enabled. + # + -query = "\ + UPDATE ${....acct_table1} \ + SET \ + AcctSessionId = '%{Acct-Session-Id}', \ + AcctUniqueId = '%{Acct-Unique-Session-Id}', \ + AcctAuthentic = '%{Acct-Authentic}', \ + ConnectInfo_start = '%{Connect-Info}', \ + ServiceType = '%{Service-Type}', \ + FramedProtocol = '%{Framed-Protocol}', \ + framedipaddress = '%{Framed-IP-Address}', \ + framedipv6address = '%{Framed-IPv6-Address}', \ + framedipv6prefix = '%{Framed-IPv6-Prefix}', \ + framedinterfaceid = '%{Framed-Interface-Id}', \ + delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ + AcctStopTime = ${....event_timestamp}, \ + AcctUpdateTime = ${....event_timestamp}, \ + AcctSessionTime = %{Acct-Session-Time}, \ + AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Input-Octets}:-0}', \ + AcctOutputOctets = '%{%{Acct-Output-Gigawords}:-0}' \ + << 32 | '%{%{Acct-Output-Octets}:-0}', \ + AcctTerminateCause = '%{Acct-Terminate-Cause}', \ + ConnectInfo_stop = '%{Connect-Info}' \ + WHERE UserName = '%{SQL-User-Name}' \ + AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ + AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \ + AND NASPortType = '%{NAS-Port-Type}' \ + AND AcctStopTime IS NULL" + + } + + # + # No Acct-Status-Type == ignore the packet + # + accounting { + query = "SELECT true" + } + } +} + + +####################################################################### +# Authentication Logging Queries +####################################################################### +# postauth_query - Insert some info after authentication +####################################################################### + +post-auth { + # Write SQL queries to a logfile. This is potentially useful for bulk inserts + # when used with the rlm_sql_null driver. +# logfile = ${logdir}/post-auth.sql + + query = "\ + INSERT INTO ${..postauth_table} \ + (username, reply, authdate ${..class.column_name}) \ + VALUES ( \ + '%{SQL-User-Name}', \ + '%{reply:Packet-Type}', \ + '%S.%M' \ + ${..class.reply_xlat})" +} \ No newline at end of file diff --git a/files/radius.conf b/files/radius.conf new file mode 100644 index 0000000..7105a01 --- /dev/null +++ b/files/radius.conf @@ -0,0 +1,1143 @@ +# -*- text -*- +## +## radiusd.conf -- FreeRADIUS server configuration file - 3.2.7 +## +## http://www.freeradius.org/ +## $Id: 376892e151857fa35c22662769acef3dcea08ecc $ +## + +###################################################################### +# +# The format of this (and other) configuration file is +# documented in "man unlang". There are also READMEs in many +# subdirectories: +# +# raddb/README.rst +# How to upgrade from v2. +# +# raddb/mods-available/README.rst +# How to use mods-available / mods-enabled. +# All of the modules are in individual files, +# along with configuration items and full documentation. +# +# raddb/sites-available/README +# virtual servers, "listen" sections, clients, etc. +# The "sites-available" directory contains many +# worked examples of common configurations. +# +# raddb/certs/README.md +# How to create certificates for EAP or RadSec. +# +# Every configuration item in the server is documented +# extensively in the comments in the example configuration +# files. +# +# Before editing this (or any other) configuration file, PLEASE +# read "man radiusd". See the section titled DEBUGGING. It +# outlines a method where you can quickly create the +# configuration you want, with minimal effort. +# +# Run the server in debugging mode, and READ the output. +# +# $ radiusd -X +# +# We cannot emphasize this point strongly enough. The vast +# majority of problems can be solved by carefully reading the +# debugging output, which includes warnings about common issues, +# and suggestions for how they may be fixed. +# +# There may be a lot of output, but look carefully for words like: +# "warning", "error", "reject", or "failure". The messages there +# will usually be enough to guide you to a solution. +# +# More documentation on "radiusd -X" is available on the wiki: +# https://wiki.freeradius.org/radiusd-X +# +# If you are going to ask a question on the mailing list, then +# explain what you are trying to do, and include the output from +# debugging mode (radiusd -X). Failure to do so means that all +# of the responses to your question will be people telling you +# to "post the output of radiusd -X". +# +# Guidelines for posting to the mailing list are on the wiki: +# https://wiki.freeradius.org/list-help +# +# Please read those guidelines before posting to the list. +# +# Further documentation is available in the "doc" directory +# of the server distribution, or on the wiki at: +# https://wiki.freeradius.org/ +# +# New users to RADIUS should read the Technical Guide. That guide +# explains how RADIUS works, how FreeRADIUS works, and what each +# part of a RADIUS system does. It is not just "configure FreeRADIUS"! +# https://networkradius.com/doc/FreeRADIUS-Technical-Guide.pdf +# +# More documentation on dictionaries, modules, unlang, etc. is also +# available on the Network RADIUS web site: +# https://networkradius.com/freeradius-documentation/ +# + +###################################################################### + +prefix = /usr +exec_prefix = /usr +sysconfdir = /etc +localstatedir = /var +sbindir = ${exec_prefix}/sbin +logdir = /var/log/freeradius +raddbdir = /etc/freeradius +radacctdir = ${logdir}/radacct + +# +# name of the running server. See also the "-n" command-line option. +name = freeradius + +# Location of config and logfiles. +confdir = ${raddbdir} +modconfdir = ${confdir}/mods-config +certdir = ${confdir}/certs +cadir = ${confdir}/certs +run_dir = ${localstatedir}/run/${name} + +# Should likely be ${localstatedir}/lib/radiusd +db_dir = ${raddbdir} + +# +# libdir: Where to find the rlm_* modules. +# +# This should be automatically set at configuration time. +# +# If the server builds and installs, but fails at execution time +# with an 'undefined symbol' error, then you can use the libdir +# directive to work around the problem. +# +# The cause is usually that a library has been installed on your +# system in a place where the dynamic linker CANNOT find it. When +# executing as root (or another user), your personal environment MAY +# be set up to allow the dynamic linker to find the library. When +# executing as a daemon, FreeRADIUS MAY NOT have the same +# personalized configuration. +# +# To work around the problem, find out which library contains that symbol, +# and add the directory containing that library to the end of 'libdir', +# with a colon separating the directory names. NO spaces are allowed. +# +# e.g. libdir = /usr/local/lib:/opt/package/lib +# +# You can also try setting the LD_LIBRARY_PATH environment variable +# in a script which starts the server. +# +# If that does not work, then you can re-configure and re-build the +# server to NOT use shared libraries, via: +# +# ./configure --disable-shared +# make +# make install +# +libdir = /usr/lib/freeradius + +# pidfile: Where to place the PID of the RADIUS server. +# +# The server may be signalled while it's running by using this +# file. +# +# This file is written when ONLY running in daemon mode. +# +# e.g.: kill -HUP `cat /var/run/radiusd/radiusd.pid` +# +pidfile = ${run_dir}/${name}.pid + +# panic_action: Command to execute if the server dies unexpectedly. +# +# FOR PRODUCTION SYSTEMS, ACTIONS SHOULD ALWAYS EXIT. +# AN INTERACTIVE ACTION MEANS THE SERVER IS NOT RESPONDING TO REQUESTS. +# AN INTERACTICE ACTION MEANS THE SERVER WILL NOT RESTART. +# +# THE SERVER MUST NOT BE ALLOWED EXECUTE UNTRUSTED PANIC ACTION CODE +# PATTACH CAN BE USED AS AN ATTACK VECTOR. +# +# The panic action is a command which will be executed if the server +# receives a fatal, non user generated signal, i.e. SIGSEGV, SIGBUS, +# SIGABRT or SIGFPE. +# +# This can be used to start an interactive debugging session so +# that information regarding the current state of the server can +# be acquired. +# +# The following string substitutions are available: +# - %e The currently executing program e.g. /sbin/radiusd +# - %p The PID of the currently executing program e.g. 12345 +# +# Standard ${} substitutions are also allowed. +# +# An example panic action for opening an interactive session in GDB would be: +# +#panic_action = "gdb %e %p" +# +# Again, don't use that on a production system. +# +# An example panic action for opening an automated session in GDB would be: +# +#panic_action = "gdb -silent -x ${raddbdir}/panic.gdb %e %p 2>&1 | tee ${logdir}/gdb-${name}-%p.log" +# +# That command can be used on a production system. +# + +# max_request_time: The maximum time (in seconds) to handle a request. +# +# Requests which take more time than this to process may be killed, and +# a REJECT message is returned. +# +# WARNING: If you notice that requests take a long time to be handled, +# then this MAY INDICATE a bug in the server, in one of the modules +# used to handle a request, OR in your local configuration. +# +# This problem is most often seen when using an SQL database. If it takes +# more than a second or two to receive an answer from the SQL database, +# then it probably means that you haven't indexed the database. See your +# SQL server documentation for more information. +# +# Useful range of values: 5 to 120 +# +max_request_time = 30 + +# cleanup_delay: The time to wait (in seconds) before cleaning up +# a reply which was sent to the NAS. +# +# The RADIUS request is normally cached internally for a short period +# of time, after the reply is sent to the NAS. The reply packet may be +# lost in the network, and the NAS will not see it. The NAS will then +# re-send the request, and the server will respond quickly with the +# cached reply. +# +# If this value is set too low, then duplicate requests from the NAS +# MAY NOT be detected, and will instead be handled as separate requests. +# +# If this value is set too high, then the server will cache too many +# requests, and some new requests may get blocked. (See 'max_requests'.) +# +# Useful range of values: 2 to 30 +# +cleanup_delay = 5 + +# max_requests: The maximum number of requests which the server keeps +# track of. This should be 256 multiplied by the number of clients. +# e.g. With 4 clients, this number should be 1024. +# +# If this number is too low, then when the server becomes busy, +# it will not respond to any new requests, until the 'cleanup_delay' +# time has passed, and it has removed the old requests. +# +# If this number is set too high, then the server will use a bit more +# memory for no real benefit. +# +# If you aren't sure what it should be set to, it's better to set it +# too high than too low. Setting it to 1000 per client is probably +# the highest it should be. +# +# Useful range of values: 256 to infinity +# +max_requests = 16384 + +# hostname_lookups: Log the names of clients or just their IP addresses +# e.g., www.freeradius.org (on) or 206.47.27.232 (off). +# +# The default is 'off' because it would be overall better for the net +# if people had to knowingly turn this feature on, since enabling it +# means that each client request will result in AT LEAST one lookup +# request to the nameserver. Enabling hostname_lookups will also +# mean that your server may stop randomly for 30 seconds from time +# to time, if the DNS requests take too long. +# +# Turning hostname lookups off also means that the server won't block +# for 30 seconds, if it sees an IP address which has no name associated +# with it. +# +# allowed values: {no, yes} +# +hostname_lookups = no + +# +# Run a "Post-Auth-Type Client-Lost" section. This ONLY happens when +# the server sends an Access-Challenge, and then client does not +# respond to it. The goal is to allow administrators to log +# something when the client does not respond. +# +# See sites-available/default, "Post-Auth-Type Client-Lost" for more +# information. +# +#postauth_client_lost = no + +# +# Some NASes will aggressively retransmit packets, and cause a DoS of +# the RADIUS infrastructure. They should follow he recommended +# retransmission behavior of RFC 5080 Section 2.2.2, but it seems +# that only (some) RADIUS servers follow that guidance. +# +# When a duplicate packet is received from the NAS, the server will +# see when the last retransmission was done. If it is within the +# "proxy_dedup_window", the retransmitted packet is dropped. +# +# i.e. There is zero benefit to sending the same RADIUS packet +# multiple times in one second. There is, in fact, serious harm +# in doing so. Aggressive retransmissions can result in network +# congestion, and ultimately failure of the RADIUS infrastructure. +# +# This behavior *cannot* be disabled. +# +# Allowed values here are 1..10. Only integers are supported. +# +#proxy_dedup_window = 1 + +# +# Unlang behavior options +# +unlang { + # + # By default, the "return" keyword will cause the current process + # section to complete. These two options allow "return" to be + # used to just exit "group" sections or "policy" sections + # + # Setting this to yes, will cause "return" within a group to + # exit the group but continue processing after that. + # +# group_stop_return = no + + # + # Setting this to yes, will cause "return" within a policy to + # exit the policy but continue processing after that. + # +# policy_stop_return = no +} + +# +# Logging section. The various "log_*" configuration items +# will eventually be moved here. +# +log { + # + # Destination for log messages. This can be one of: + # + # files - log to "file", as defined below. + # syslog - to syslog (see also the "syslog_facility", below. + # stdout - standard output + # stderr - standard error. + # + # The command-line option "-X" over-rides this option, and forces + # logging to go to stdout. + # + destination = files + + # + # Highlight important messages sent to stderr and stdout. + # + # Option will be ignored (disabled) if output if TERM is not + # an xterm or output is not to a TTY. + # + colourise = yes + + # + # The logging messages for the server are appended to the + # tail of this file if destination == "files" + # + # If the server is running in debugging mode, this file is + # NOT used. + # + file = ${logdir}/radius.log + + # + # Which syslog facility to use, if ${destination} == "syslog" + # + # The exact values permitted here are OS-dependent. You probably + # don't want to change this. + # + syslog_facility = daemon + + # Log the full User-Name attribute, as it was found in the request. + # + # allowed values: {no, yes} + # + stripped_names = no + + # Log all (accept and reject) authentication results to the log file. + # + # This is the same as setting "auth_accept = yes" and + # "auth_reject = yes" + # + # allowed values: {no, yes} + # + auth = no + + # Log Access-Accept results to the log file. + # + # This is only used if "auth = no" + # + # allowed values: {no, yes} + # +# auth_accept = no + + # Log Access-Reject results to the log file. + # + # This is only used if "auth = no" + # + # allowed values: {no, yes} + # +# auth_reject = no + + # Log passwords with the authentication requests. + # auth_badpass - logs password if it's rejected + # auth_goodpass - logs password if it's correct + # + # allowed values: {no, yes} + # + auth_badpass = no + auth_goodpass = no + + # Log additional text at the end of the "Login OK" messages. + # for these to work, the "auth" and "auth_goodpass" or "auth_badpass" + # configurations above have to be set to "yes". + # + # The strings below are dynamically expanded, which means that + # you can put anything you want in them. However, note that + # this expansion can be slow, and can negatively impact server + # performance. + # +# msg_goodpass = "" +# msg_badpass = "" + + # The message when the user exceeds the Simultaneous-Use limit. + # + msg_denied = "You are already logged in - access denied" + + # Suppress "secret" attributes when printing them in debug mode. + # + # Secrets are NOT tracked across xlat expansions. If your + # configuration puts secrets into other strings, they will + # still get printed. + # + # Setting this to "yes" means that the server prints + # + # <<< secret >>> + # + # instead of the value, for attriburtes which contain secret + # information. e.g. User-Name, Tunnel-Password, etc. + # + # This configuration is disabled by default. It is extremely + # important for administrators to be able to debug user logins + # by seeing what is actually being sent. + # + suppress_secrets = yes +} + +# The program to execute to do concurrency checks. +checkrad = ${sbindir}/checkrad + +# +# ENVIRONMENT VARIABLES +# +# You can reference environment variables using an expansion like +# `$ENV{PATH}`. However it is sometimes useful to be able to also set +# environment variables. This section lets you do that. +# +# The main purpose of this section is to allow administrators to keep +# RADIUS-specific configuration in the RADIUS configuration files. +# For example, if you need to set an environment variable which is +# used by a module. You could put that variable into a shell script, +# but that's awkward. Instead, just list it here. +# +# Note that these environment variables are set AFTER the +# configuration file is loaded. So you cannot set FOO here, and +# expect to reference it via `$ENV{FOO}` in another configuration file. +# You should instead just use a normal configuration variable for +# that. +# +ENV { + # + # Set environment varable `FOO` to value '/bar/baz'. + # + # NOTE: Note that you MUST use '='. You CANNOT use '+=' to append + # values. + # +# FOO = '/bar/baz' + + # + # Delete environment variable `BAR`. + # +# BAR + + + # + # If the server needs kerberos credentials, then they can be placed + # into the following keytab file. + # + # This also permits the server to use those credentials when it is + # run in debug mode. + # +# KRB5_CLIENT_KTNAME = ${raddbdir}/radiusd.keytab + + # + # `LD_PRELOAD` is special. It is normally set before the + # application runs, and is interpreted by the dynamic linker. + # Which means you cannot set it inside of an application, and + # expect it to load libraries. + # + # Since this functionality is useful, we extend it here. + # + # You can set + # + # LD_PRELOAD = /path/to/library.so + # + # and the server will load the named libraries. Multiple + # libraries can be loaded by specificing multiple individual + # `LD_PRELOAD` entries. + # + # +# LD_PRELOAD = /path/to/library1.so +# LD_PRELOAD = /path/to/library2.so +} + +# SECURITY CONFIGURATION +# +# There may be multiple methods of attacking on the server. This +# section holds the configuration items which minimize the impact +# of those attacks +# +security { + # chroot: directory where the server does "chroot". + # + # The chroot is done very early in the process of starting + # the server. After the chroot has been performed it + # switches to the "user" listed below (which MUST be + # specified). If "group" is specified, it switches to that + # group, too. Any other groups listed for the specified + # "user" in "/etc/group" are also added as part of this + # process. + # + # The current working directory (chdir / cd) is left + # *outside* of the chroot until all of the modules have been + # initialized. This allows the "raddb" directory to be left + # outside of the chroot. Once the modules have been + # initialized, it does a "chdir" to ${logdir}. This means + # that it should be impossible to break out of the chroot. + # + # If you are worried about security issues related to this + # use of chdir, then simply ensure that the "raddb" directory + # is inside of the chroot, and be sure to do "cd raddb" + # BEFORE starting the server. + # + # If the server is statically linked, then the only files + # that have to exist in the chroot are ${run_dir} and + # ${logdir}. If you do the "cd raddb" as discussed above, + # then the "raddb" directory has to be inside of the chroot + # directory, too. + # +# chroot = /path/to/chroot/directory + + # user/group: The name (or #number) of the user/group to run radiusd as. + # + # If these are commented out, the server will run as the + # user/group that started it. In order to change to a + # different user/group, you MUST be root ( or have root + # privileges ) to start the server. + # + # We STRONGLY recommend that you run the server with as few + # permissions as possible. That is, if you're not using + # shadow passwords, the user and group items below should be + # set to radius'. + # + # NOTE that some kernels refuse to setgid(group) when the + # value of (unsigned)group is above 60000; don't use group + # "nobody" on these systems! + # + # On systems with shadow passwords, you might have to set + # 'group = shadow' for the server to be able to read the + # shadow password file. If you can authenticate users while + # in debug mode, but not in daemon mode, it may be that the + # debugging mode server is running as a user that can read + # the shadow info, and the user listed below can not. + # + # The server will also try to use "initgroups" to read + # /etc/groups. It will join all groups where "user" is a + # member. This can allow for some finer-grained access + # controls. + # + user = freerad + group = freerad + + # Core dumps are a bad thing. This should only be set to + # 'yes' if you're debugging a problem with the server. + # + # allowed values: {no, yes} + # + allow_core_dumps = no + + # + # max_attributes: The maximum number of attributes + # permitted in a RADIUS packet. Packets which have MORE + # than this number of attributes in them will be dropped. + # + # If this number is set too low, then no RADIUS packets + # will be accepted. + # + # If this number is set too high, then an attacker may be + # able to send a small number of packets which will cause + # the server to use all available memory on the machine. + # + # Setting this number to 0 means "allow any number of attributes" + max_attributes = 200 + + # + # reject_delay: When sending an Access-Reject, it can be + # delayed for a few seconds. This may help slow down a DoS + # attack. It also helps to slow down people trying to brute-force + # crack a users password. + # + # Setting this number to 0 means "send rejects immediately" + # + # If this number is set higher than 'cleanup_delay', then the + # rejects will be sent at 'cleanup_delay' time, when the request + # is deleted from the internal cache of requests. + # + # This number can be a decimal, e.g. 3.4 + # + # Useful ranges: 1 to 5 + reject_delay = 1 + + # + # status_server: Whether or not the server will respond + # to Status-Server requests. + # + # When sent a Status-Server message, the server responds with + # an Access-Accept or Accounting-Response packet. + # + # This is mainly useful for administrators who want to "ping" + # the server, without adding test users, or creating fake + # accounting packets. + # + # It's also useful when a NAS marks a RADIUS server "dead". + # The NAS can periodically "ping" the server with a Status-Server + # packet. If the server responds, it must be alive, and the + # NAS can start using it for real requests. + # + # See also raddb/sites-available/status + # + status_server = yes + + # + # Global configuration for requiring Message-Authenticator in + # all Access-* packets sent over UDP or TCP. This flag is + # ignored for TLS. + # + # The number one way to protect yourself from the BlastRADIUS + # attack is to update all RADIUS servers, and then set this + # flag to "yes". If all RADIUS servers are updated, and if + # all of them have this flag set to "yes" for all clients, + # then your network is safe. You can then upgrade the + # clients when it is convenient, instead of rushing the + # upgrades. + # + # This flag sets the global default for all clients and home + # servers. It can be over-ridden in an individual client or + # home_server definition by adding the same flag to that + # section with an appropriate value. + # + # All upgraded RADIUS implementations should send + # Message-Authenticator in all Access-Request, Access-Accept, + # Access-Reject, and Access-Challenge packets. Once all + # systems are upgraded, setting this flag to "yes" is the + # best protection from the attack. + # + # The possible values and meanings for + # "require_message_authenticator" are; + # + # * "no" - allow Access-* packet which do not contain + # Message-Authenticator + # + # For a client, if this flag is set to "no", then the + # "limit_proxy_state" flag, below, is also checked. + # + # For a home_server, if this flag is set to "no", then the + # Access-Accept, Access-Reject, and Access-Challenge + # packets do not need to contain Message-Authenticator. + # + # The only reason to set this flag to "no" is when the + # RADIUS client or home server has not been updated. It is + # always safer to set this flag "no" in the individual + # client or home_server definition. The global flag SHOULD + # still be set to a safe value: "yes". + # + # WARNING: Setting this flag and the "limit_proxy_state" + # flag to "no" will allow MITM attackers to create fake + # Access-Accept packets to the NAS! At least one of them + # MUST be set to "yes" for the system to have any + # protection against the attack. + # + # * "yes" - Require that all Access-* packets (client and + # home_server) contain Message-Authenticator. If a packet + # does not contain Message-Authenticator, then it is + # discarded. + # + # * "auto" - Automatically determine the value of the flag, + # based on the first packet received from that client or + # home_server. + # + # If the packet does not contain Message-Authenticator, + # then the value of the flag is automatically switched to + # "no". + # + # If the packet contains Message-Authenticator but not + # EAP-Message, then the value of the flag is automatically + # switched to "yes". The server has to check for + # EAP-Message, because the previous RFCs require that the + # packet contains Message-Authenticator when it also + # contains EAP-Message. So having a Message-Authenticator + # in those packets doesn't give the server enough + # information to determined if the client or home_server + # has been updated. + # + # If the packet contains Message-Authenticator and + # EAP-Message, then the flag is left at the "auto" value. + # + # WARNING: This switch is done for the first packet + # received from that client or home server. The change + # does NOT persist across server restarts. You MUST change + # the to "yes" manually, in order to make a permanent + # change to the configuration. + # + # WARNING: If there are multiple NASes with the same source + # IP and client definitions, BUT the NASes have different + # behavior, then this flag WILL LIKELY BREAK YOUR NETWORK. + # + # That is, when there are multiple different RADIUS clients + # behind one NATed IP address, then these security settings + # have to be set to allow the MOST INSECURE packets to be + # processed. This is a terrible idea, and will leave your + # network vulnerable to the attack. Please upgrade all + # clients immediately. + # + # The only solution to that rare configuration is to set + # this flag to "no", in which case the network will work, + # but will be vulnerable to the attack. + # + require_message_authenticator = auto + + # + # Global configuration for limiting the combination of + # Proxy-State and Message-Authenticator. This flag only + # applies to Access-Request packets sent from a client, over + # UDP or TCP. This flag is ignored for TLS. + # + # This flag sets the global default for all clients. It can + # be over-ridden in an individual client definition by adding + # the same flag to that section with an appropriate value. + # + # If "require_message_authenticator" is set to "yes", this + # configuration item is ignored. + # + # If "require_message_authenticator" is set to "no", this + # configuration item is checked. + # + # The possible values and meanings for "limit_proxy_state" are; + # + # * "no" - allow any Access-Request packets from the client, + # even packets which contain the BlastRADIUS attack. + # Please be aware that in this configuration the server + # will complain for EVERY packet which it receives. + # + # The only reason to set this flag to "no" is when the + # client is a proxy, AND it does not send + # Message-Authenticator in Access-Request packets. Even + # then, the best approach to fix the issue is to (1) update + # the proxy to send Message-Authenticator, and if that + # can't be done, then (2) set this flag to "no", but ONLY + # for that one client. The global flag SHOULD still be set + # to a safe value: "yes". + # + # WARNING: Setting both this flag and the + # "require_message_authenticator" flag to "no" will allow + # MITM attackers to spoof Access-Request packets, and then + # to create fake Access-Accept packets to the NAS! At + # least one of these configuration items MUST be set to + # "yes" for the system to have any protection against the + # attack. + # + # * "yes" - Allow Access-Request packets without + # Message-Authenticator, but only when they do not contain + # Proxy-State. Packets which contain Proxy-State MUST also + # contain Message-Authenticator, otherwise they are + # discarded. + # + # This setting is safe for most NASes, GGSNs, BRAS, etc. + # Most regular RADIUS clients do not send Proxy-State + # attributes for Access-Request packets that they originate. + # However some aggregators (e.g. Wireless LAN Controllers) + # may act as a RADIUS proxy for requests from their cohort + # of managed devices, and in such cases will provide a + # Proxy-State attribute. For those systems, you _must_ look + # at the actual packets to determine what to do. It may be + # that the only way to fix the vulnerability is to upgrade + # the WLC, and set "require_message_authenticator" to "yes". + # + # * "auto" - Automatically determine the value of the flag, + # based on the first Access-Request packet received from + # that client. + # + # If the packet contains Proxy-State but no + # Message-Authenticator, then the value of the flag is + # automatically switched to "no". + # + # For all other situations, the value of the flag is + # automatically switched to "yes". + # + # WARNING: This switch is done for the first packet + # received from that client. The change does NOT persist + # across server restarts. You MUST change the to "yes" + # manually, in order to make a permanent change to the + # configuration. + # + # WARNING: If there are multiple NASes with the same source + # IP and client definitions, BUT the NASes have different + # behavior, then this flag WILL LIKELY BREAK YOUR NETWORK. + # + # That is, when there are multiple different RADIUS clients + # behind one NATed IP address, then these security settings + # have to be set to allow the MOST INSECURE packets to be + # processed. This is a terrible idea, and will leave your + # network vulnerable to the attack. Please upgrade all + # clients immediately. + # + # The only solution to that rare configuration is to set + # this flag to "no", in which case the network will work, + # but will be vulnerable to the attack. + # + limit_proxy_state = auto + + +} + +# PROXY CONFIGURATION +# +# proxy_requests: Turns proxying of RADIUS requests on or off. +# +# The server has proxying turned on by default. If your system is NOT +# set up to proxy requests to another server, then you can turn proxying +# off here. This will save a small amount of resources on the server. +# +# If you have proxying turned off, and your configuration files say +# to proxy a request, then an error message will be logged. +# +# To disable proxying, change the "yes" to "no", and comment the +# $INCLUDE line. +# +# allowed values: {no, yes} +# +proxy_requests = yes +$INCLUDE proxy.conf + + +# CLIENTS CONFIGURATION +# +# Client configuration is defined in "clients.conf". +# + +# The 'clients.conf' file contains all of the information from the old +# 'clients' and 'naslist' configuration files. We recommend that you +# do NOT use 'client's or 'naslist', although they are still +# supported. +# +# Anything listed in 'clients.conf' will take precedence over the +# information from the old-style configuration files. +# +$INCLUDE clients.conf + + +# THREAD POOL CONFIGURATION +# +# The thread pool is a long-lived group of threads which +# take turns (round-robin) handling any incoming requests. +# +# You probably want to have a few spare threads around, +# so that high-load situations can be handled immediately. If you +# don't have any spare threads, then the request handling will +# be delayed while a new thread is created, and added to the pool. +# +# You probably don't want too many spare threads around, +# otherwise they'll be sitting there taking up resources, and +# not doing anything productive. +# +# The numbers given below should be adequate for most situations. +# +thread pool { + # Number of servers to start initially --- should be a reasonable + # ballpark figure. + start_servers = 5 + + # Limit on the total number of servers running. + # + # If this limit is ever reached, clients will be LOCKED OUT, so it + # should NOT BE SET TOO LOW. It is intended mainly as a brake to + # keep a runaway server from taking the system with it as it spirals + # down... + # + # You may find that the server is regularly reaching the + # 'max_servers' number of threads, and that increasing + # 'max_servers' doesn't seem to make much difference. + # + # If this is the case, then the problem is MOST LIKELY that + # your back-end databases are taking too long to respond, and + # are preventing the server from responding in a timely manner. + # + # The solution is NOT do keep increasing the 'max_servers' + # value, but instead to fix the underlying cause of the + # problem: slow database, or 'hostname_lookups=yes'. + # + # For more information, see 'max_request_time', above. + # + max_servers = 32 + + # Server-pool size regulation. Rather than making you guess + # how many servers you need, FreeRADIUS dynamically adapts to + # the load it sees, that is, it tries to maintain enough + # servers to handle the current load, plus a few spare + # servers to handle transient load spikes. + # + # It does this by periodically checking how many servers are + # waiting for a request. If there are fewer than + # min_spare_servers, it creates a new spare. If there are + # more than max_spare_servers, some of the spares die off. + # The default values are probably OK for most sites. + # + min_spare_servers = 3 + max_spare_servers = 10 + + # When the server receives a packet, it places it onto an + # internal queue, where the worker threads (configured above) + # pick it up for processing. The maximum size of that queue + # is given here. + # + # When the queue is full, any new packets will be silently + # discarded. + # + # The most common cause of the queue being full is that the + # server is dependent on a slow database, and it has received + # a large "spike" of traffic. When that happens, there is + # very little you can do other than make sure the server + # receives less traffic, or make sure that the database can + # handle the load. + # +# max_queue_size = 65536 + + # Clean up old threads periodically. For no reason other than + # it might be useful. + # + # '0' is a special value meaning 'infinity', or 'the servers never + # exit' + max_requests_per_server = 0 + + # Automatically limit the number of accounting requests. + # This configuration item tracks how many requests per second + # the server can handle. It does this by tracking the + # packets/s received by the server for processing, and + # comparing that to the packets/s handled by the child + # threads. + # + + # If the received PPS is larger than the processed PPS, *and* + # the queue is more than half full, then new accounting + # requests are probabilistically discarded. This lowers the + # number of packets that the server needs to process. Over + # time, the server will "catch up" with the traffic. + # + # Throwing away accounting packets is usually safe and low + # impact. The NAS will retransmit them in a few seconds, or + # even a few minutes. Vendors should read RFC 5080 Section 2.2.1 + # to see how accounting packets should be retransmitted. Using + # any other method is likely to cause network meltdowns. + # + auto_limit_acct = no +} + +###################################################################### +# +# SNMP notifications. Uncomment the following line to enable +# snmptraps. Note that you MUST also configure the full path +# to the "snmptrap" command in the "trigger.conf" file. +# +#$INCLUDE trigger.conf + +# MODULE CONFIGURATION +# +# The names and configuration of each module is located in this section. +# +# After the modules are defined here, they may be referred to by name, +# in other sections of this configuration file. +# +modules { + # + # Each module has a configuration as follows: + # + # name [ instance ] { + # config_item = value + # ... + # } + # + # The 'name' is used to load the 'rlm_name' library + # which implements the functionality of the module. + # + # The 'instance' is optional. To have two different instances + # of a module, it first must be referred to by 'name'. + # The different copies of the module are then created by + # inventing two 'instance' names, e.g. 'instance1' and 'instance2' + # + # The instance names can then be used in later configuration + # INSTEAD of the original 'name'. See the 'radutmp' configuration + # for an example. + # + + # + # Some modules have ordering issues. e.g. "sqlippool" uses + # the configuration from "sql". In that case, the "sql" + # module must be read off of disk before the "sqlippool". + # However, the directory inclusion below just reads the + # directory from start to finish. Which means that the + # modules are read off of disk randomly. + # + # You can list individual modules *before* the directory + # inclusion. Those modules will be loaded first. Then, when + # the directory is read, those modules will be skipped and + # not read twice. + # +# $INCLUDE mods-enabled/sql + + # + # All modules are in ther mods-enabled/ directory. Files + # matching the regex /[a-zA-Z0-9_.]+/ are read. The + # modules are initialized ONLY if they are referenced in a + # processing section, such as authorize, authenticate, + # accounting, pre/post-proxy, etc. + # + $INCLUDE mods-enabled/ +} + +# Instantiation +# +# This section sets the instantiation order of the modules. listed +# here will get started up BEFORE the sections like authorize, +# authenticate, etc. get examined. +# +# This section is not strictly needed. When a section like authorize +# refers to a module, the module is automatically loaded and +# initialized. However, some modules may not be listed in any of the +# processing sections, so they should be listed here. +# +# Also, listing modules here ensures that you have control over +# the order in which they are initialized. If one module needs +# something defined by another module, you can list them in order +# here, and ensure that the configuration will be OK. +# +# After the modules listed here have been loaded, all of the modules +# in the "mods-enabled" directory will be loaded. Loading the +# "mods-enabled" directory means that unlike Version 2, you usually +# don't need to list modules here. +# +instantiate { + # + # We list the counter module here so that it registers + # the check_name attribute before any module which sets + # it +# daily + + # subsections here can be thought of as "virtual" modules. + # + # e.g. If you have two redundant SQL servers, and you want to + # use them in the authorize and accounting sections, you could + # place a "redundant" block in each section, containing the + # exact same text. Or, you could uncomment the following + # lines, and list "redundant_sql" in the authorize and + # accounting sections. + # + # The "virtual" module defined here can also be used with + # dynamic expansions, under a few conditions: + # + # * The section is "redundant", or "load-balance", or + # "redundant-load-balance" + # * The section contains modules ONLY, and no sub-sections + # * all modules in the section are using the same rlm_ + # driver, e.g. They are all sql, or all ldap, etc. + # + # When those conditions are satisfied, the server will + # automatically register a dynamic expansion, using the + # name of the "virtual" module. In the example below, + # it will be "redundant_sql". You can then use this expansion + # just like any other: + # + # update reply { + # Filter-Id := "%{redundant_sql: ... }" + # } + # + # In this example, the expansion is done via module "sql1", + # and if that expansion fails, using module "sql2". + # + # For best results, configure the "pool" subsection of the + # module so that "retry_delay" is non-zero. That will allow + # the redundant block to quickly ignore all "down" SQL + # databases. If instead we have "retry_delay = 0", then + # every time the redundant block is used, the server will try + # to open a connection to every "down" database, causing + # problems. + # + #redundant redundant_sql { + # sql1 + # sql2 + #} +} + +###################################################################### +# +# Policies are virtual modules, similar to those defined in the +# "instantiate" section above. +# +# Defining a policy in one of the policy.d files means that it can be +# referenced in multiple places as a *name*, rather than as a series of +# conditions to match, and actions to take. +# +# Policies are something like subroutines in a normal language, but +# they cannot be called recursively. They MUST be defined in order. +# If policy A calls policy B, then B MUST be defined before A. +# +###################################################################### +policy { + $INCLUDE policy.d/ +} + +###################################################################### +# +# Load virtual servers. +# +# This next $INCLUDE line loads files in the directory that +# match the regular expression: /[a-zA-Z0-9_.]+/ +# +# It allows you to define new virtual servers simply by placing +# a file into the raddb/sites-enabled/ directory. +# +$INCLUDE sites-enabled/ + +###################################################################### +# +# All of the other configuration sections like "authorize {}", +# "authenticate {}", "accounting {}", have been moved to the +# the file: +# +# raddb/sites-available/default +# +# This is the "default" virtual server that has the same +# configuration as in version 1.0.x and 1.1.x. The default +# installation enables this virtual server. You should +# edit it to create policies for your local site. +# +# For more documentation on virtual servers, see: +# +# raddb/sites-available/README +# +###################################################################### \ No newline at end of file diff --git a/templates/ConfigMap/mods-config.yaml b/templates/ConfigMap/mods-config.yaml new file mode 100644 index 0000000..aec90d9 --- /dev/null +++ b/templates/ConfigMap/mods-config.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-mods-config" (include "st-common.names.fullname" .) }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +data: +{{ (.Files.Glob "files/mods-config/queries.conf").AsConfig | indent 2 }} diff --git a/templates/ConfigMap/radius-conf.yaml b/templates/ConfigMap/radius-conf.yaml new file mode 100644 index 0000000..4d04b84 --- /dev/null +++ b/templates/ConfigMap/radius-conf.yaml @@ -0,0 +1,19 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-radius-conf" (include "st-common.names.fullname" .) }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +data: +{{ (.Files.Glob "files/radius.conf").AsConfig | indent 2 }} diff --git a/templates/Deployment.yaml b/templates/Deployment.yaml index 501bb7e..3a60f6a 100644 --- a/templates/Deployment.yaml +++ b/templates/Deployment.yaml @@ -280,6 +280,12 @@ spec: - name: freeradius-mods mountPath: /etc/freeradius/mods-enabled/dynamic_clients subPath: dynamic_clients + - name: freeradius-mods-config + mountPath: /etc/freeradius/mods-config/sql/main/mysql/queries.conf + subPath: queries.conf + - name: freeradius-radius-conf + mountPath: /etc/freeradius/radius.conf + subPath: radius.conf - name: freeradius-sites mountPath: /etc/freeradius/sites-enabled/default subPath: default @@ -325,6 +331,12 @@ spec: - name: freeradius-sites configMap: name: {{ printf "%s-sites" (include "st-common.names.fullname" .) }} + - name: freeradius-mods-config + configMap: + name: {{ printf "%s-mods-config" (include "st-common.names.fullname" .) }} + - name: freeradius-radius-conf + configMap: + name: {{ printf "%s-radius-conf" (include "st-common.names.fullname" .) }} - name: temp emptyDir: {} - name: shared-certs