diff options
Diffstat (limited to '')
31 files changed, 6487 insertions, 0 deletions
diff --git a/raddb/sites-available/README b/raddb/sites-available/README new file mode 100644 index 0000000..0805a75 --- /dev/null +++ b/raddb/sites-available/README @@ -0,0 +1,333 @@ +1. Virtual Servers. + + FreeRADIUS supports virtual servers. The virtual servers do NOT have +to be set up with the "sites-available" and "sites-enabled" +directories. You can still have one "radiusd.conf" file, and put the +server configuration there: + + ... + server { + authorize { + ... + } + authenticate { + ... + } + ... + } + ... + + The power of virtual servers lies in their ability to separate +policies. A policy can be placed into a virtual server, where it is +guaranteed to affect only the requests that are passed through that +virtual server. In 1.x, the policies were global, and it sometimes +took much effort to write a policy so that it only applied in certain +limited situations. + + +2. What do we mean by "virtual server"? + + + A virtual server is a (nearly complete) RADIUS server, just like a +configuration for FreeRADIUS 1.x. However, FreeRADIUS can now run +multiple virtual servers at the same time. The virtual servers can +even proxy requests to each other! + + The simplest way to create a virtual server is to take the all of +the request processing sections from radius.conf, ("authorize" , +"authenticate", etc.) and wrap them in a "server {}" block, as above. + + You can create another virtual server by: + + 1) defining a new "server foo {...}" section in radiusd.conf + 2) Putting the normal "authorize", etc. sections inside of it + 3) Adding a "listen" section *inside* of the "server" section. + + e.g. + + ... + server foo { + listen { + ipaddr = 127.0.0.1 + port = 2000 + type = auth + } + + authorize { + update control { + Cleartext-Password := "bob" + } + pap + } + + authenticate { + pap + } + } + ... + + With that text added to "radiusd.conf", run the server in debugging +mode (radiusd -X), and in another terminal window, type: + +$ radtest bob bob localhost:2000 0 testing123 + + You should see the server return an Access-Accept. + + +3. Capabilities and limitations + + + The only sub-sections that can appear in a virtual server section +are: + + listen + client + authorize + authenticate + post-auth + pre-proxy + post-proxy + preacct + accounting + session + + All other configuration parameters (modules, etc.) are global. + + Inside of a virtual server, the authorize, etc. sections have their +normal meaning, and can contain anything that an authorize section +could contain in 1.x. + + When a "listen" section is inside of a virtual server definition, it +means that all requests sent to that IP/port will be processed through +the virtual server. There cannot be two "listen" sections with the +same IP address and port number. + + When a "client" section is inside of a virtual server definition, it +means that that client is known only to the "listen" sections that are +also inside of that virtual server. Not only is this client +definition available only to this virtual server, but the details of +the client configuration is also available only to this virtual +server. + + i.e. Two virtual servers can listen on different IP address and +ports, but both can have a client with IP address 127.0.0.1. The +shared secret for that client can be different for each virtual +server. + + +4. More complex "listen" capabilities + + The "listen" sections have a few additional configuration items that +were not in 1.x, and were not mentioned above. These configuration +items enable almost any mapping of IP / port to clients to virtual +servers. + + The configuration items are: + + virtual_server = <name> + + If set, all requests sent to this IP / port are processed + through the named virtual server. + + This directive can be used only for "listen" sections + that are global. i.e. It CANNOT be used if the + "listen" section is inside of a virtual server. + + clients = <name> + + If set, the "listen" section looks for a "clients" section: + + clients <name> { + ... + } + + It looks inside of that named "clients" section for + "client" subsections, at least one of which must + exist. Each client in that section is added to the + list of known clients for this IP / port. No other + clients are known. + + If it is set, it over-rides the list of clients (if + any) in the same virtual server. Note that the + clients are NOT additive! + + If it is not set, then the clients from the current + virtual server (if any) are used. If there are no + clients in this virtual server, then the global + clients are used. + + i.e. The most specific directive is used: + * configuration in this "listen" section + * clients in the same virtual server + * global clients + + The directives are also *exclusive*, not *additive*. + If you have one client in a virtual server, and + another client referenced from a "listen" section, + then that "listen" section will ONLY use the second + client. It will NOT use both clients. + + +5. More complex "client" capabilities + + The "client" sections have a few additional configuration items that +were not in 1.x, and were not mentioned above. These configuration +items enable almost any mapping of IP / port to clients to virtual +servers. + + The configuration items are: + + virtual_server = <name> + + If set, all requests from this client are processed + through the named virtual server. + + This directive can be used only for "client" sections + that are global. i.e. It CANNOT be used if the + "client" section is inside of a virtual server. + + If the "listen" section has a "server" entry, and a matching +client is found ALSO with a "server" entry, then the clients server is +used for that request. + + +6. Worked examples + + + Listening on one socket, and mapping requests from two clients to +two different servers. + + listen { + ... + } + client one { + ... + virtual_server = server_one + } + client two { + ... + virtual_server = server_two + } + server server_one { + authorize { + ... + } + ... + } + server server_two { + authorize { + ... + } + ... + } + + This could also be done as: + + + listen { + ... + virtual_server = server_one + } + client one { + ... + } + client two { + ... + virtual_server = server_two + } + server server_one { + authorize { + ... + } + ... + } + server server_two { + authorize { + ... + } + ... + } + + In this case, the default server for the socket is "server_one", so +there is no need to set that in the client "one" configuration. The +"server_two" configuration for client "two" over-rides the default +setting for the socket. + + Note that the following configuration will NOT work: + + listen { + ... + virtual_server = server_one + } + client one { + ... + } + server server_one { + authorize { + ... + } + ... + } + server server_two { + client two { + ... + } + authorize { + ... + } + ... + } + + In this example, client "two" is hidden inside of the virtual +server, where the "listen" section cannot find it. + + +7. Outlined examples + + This section outlines a number of examples, with alternatives. + + One server, multiple sockets + - multiple "listen" sections in a "server" section + + one server per client + - define multiple servers + - have a global "listen" section + - have multiple global "clients", each with "virtual_server = X" + + two servers, each with their own sockets + - define multiple servers + - put "client" sections into each "server" + - put a "listen" section into each "server" + + Each server can list the same client IP, and the secret + can be different + + two sockets, sharing a list of clients, but pointing to different servers + - define global "listen" sections + - in each, set "virtual_server = X" + - in each, set "clients = Y" + - define "clients Y" section, containing multiple clients. + + This also means that you can have a third socket, which + doesn't share any of these clients. + + +8. How to decide what to do + + + If you want *completely* separate policies for a socket or a client, +then create a separate virtual server. Then, map the request to that +server by setting configuration entries in a "listen" section or in a +"client" section. + + Start off with the common cases first. If most of the clients +and/or sockets get a particular policy, make that policy the default. +Configure it without paying attention to the sockets or clients you +want to add later, and without adding a second virtual server. Once +it works, then add the second virtual server. + + If you want to re-use the previously defined sockets with the second +virtual server, then you will need one or more global "client" +sections. Those clients will contain a "virtual_server = ..." entry +that will direct requests from those clients to the appropriate +virtual server. diff --git a/raddb/sites-available/abfab-tls b/raddb/sites-available/abfab-tls new file mode 100644 index 0000000..b8d0626 --- /dev/null +++ b/raddb/sites-available/abfab-tls @@ -0,0 +1,118 @@ +# +# Example configuration for ABFAB listening on TLS. +# +# $Id$ +# +listen { + ipaddr = * + port = 2083 + type = auth + proto = tcp + + tls { + tls_min_version = "1.2" + private_key_password = whatever + + # Moonshot tends to distribute certs separate from keys + private_key_file = ${certdir}/server.key + certificate_file = ${certdir}/server.pem + ca_file = ${cadir}/ca.pem + dh_file = ${certdir}/dh + fragment_size = 8192 + ca_path = ${cadir} + cipher_list = "DEFAULT" + cache { + enable = no + lifetime = 24 # hours + name = "abfab-tls" + # persist_dir = ${logdir}/abfab-tls + } + require_client_cert = yes + verify { + } + + psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}" + } + + virtual_server = abfab-idp + clients = radsec-abfab +} + +# There needs to be a separated "listen" section for IPv6. +# Typically it will be identical to the IPv4 one above, but there might be +# some differences (e.g. if a different certificate or port is desired) +listen { + ipaddr = :: + port = 2083 + type = auth + proto = tcp + + tls { + tls_min_version = "1.2" + private_key_password = whatever + + # Moonshot tends to distribute certs separate from keys + private_key_file = ${certdir}/server.key + certificate_file = ${certdir}/server.pem + ca_file = ${cadir}/ca.pem + dh_file = ${certdir}/dh + fragment_size = 8192 + ca_path = ${cadir} + cipher_list = "DEFAULT" + cache { + enable = no + lifetime = 24 # hours + name = "abfab-tls" + # persist_dir = ${logdir}/abfab-tls + } + require_client_cert = yes + verify { + } + + psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}" + } + + virtual_server = abfab-idp + clients = radsec-abfab +} + +clients radsec-abfab { + # + # Allow all clients, but require TLS. + # This client stanza will match other RP proxies from other + # realms established via the trustrouter. In general + # additional client stanzas are also required for local services. + # + client default { + ipaddr = 0.0.0.0/0 + proto = tls + } + + client default_ip6 { + ipaddr = ::/0 + proto = tls + } + + # An example local service + # client service_1 { + # ipaddr = 192.0.2.20 + # # You should either set gss_acceptor_host_name below + # # or set up policy to confirm that a client claims + # # the right acceptor hostname when using ABFAB. If + # # set, the RADIUS server will confirm that all + # # requests have this value for the acceptor host name + # gss_acceptor_host_name = "server.example.com" + # # If set, this acceptor realm name will be included. + # # Foreign realms will typically reject a request if this is not + # # properly set. + # gss_acceptor_realm_name = "example.com" + # # Additionally, trust_router_coi can be set; if set + # # it will override the default_community in the realm + # # module + # trust_router_coi = "community1.example.net" + # # In production depployments it is important to set + # # up certificate verification so that even if + # # clients spoof IP addresses, one client cannot + # # impersonate another. + # } +} diff --git a/raddb/sites-available/abfab-tr-idp b/raddb/sites-available/abfab-tr-idp new file mode 100644 index 0000000..be98568 --- /dev/null +++ b/raddb/sites-available/abfab-tr-idp @@ -0,0 +1,198 @@ +# +# This file represents a server that is implementing an identity +# provider for GSS-EAP (RFC 7055) using the trust router +# protocol for dynamic realm discovery. Any ABFAB identity +# provider is also an ABFAB relying party proxy. +# +# This file does not include a TLS listener; see abfab-tls for a simple +# example of a RADSEC listener for ABFAB. +# +# $Id$ +# + +server abfab-idp { +authorize { + psk_authorize + abfab_client_check + filter_username + preprocess + + # If you intend to use CUI and you require that the Operator-Name + # be set for CUI generation and you want to generate CUI also + # for your local clients then uncomment the operator-name + # below and set the operator-name for your clients in clients.conf +# operator-name + + # + # If you want to generate CUI for some clients that do not + # send proper CUI requests, then uncomment the + # cui below and set "add_cui = yes" for these clients in clients.conf +# cui + + # + # Do RFC 7542 bang path routing. If you want to only do standard + # RADIUS NAI routing, comment out the below line. + rfc7542 + + # Standard RADIUS NAI routing + if (!updated) { + suffix { + updated = 1 + noop = reject + } + } + + eap { + ok = return + } + + expiration + logintime +} + +authenticate { + # + # Allow EAP authentication. + eap +} + +# Post-Authentication +# Once we KNOW that the user has been authenticated, there are +# additional steps we can take. +post-auth { + # + # For EAP-TTLS and PEAP, add the cached attributes to the reply. + # The "session-state" attributes are automatically cached when + # an Access-Challenge is sent, and automatically retrieved + # when an Access-Request is received. + # + # The session-state attributes are automatically deleted after + # an Access-Reject or Access-Accept is sent. + # + # If both session-state and reply contain a User-Name attribute, remove + # the one in the reply if it is just a copy of the one in the request, so + # we don't end up with two User-Name attributes. + + if (session-state:User-Name && reply:User-Name && request:User-Name && (reply:User-Name == request:User-Name)) { + update reply { + &User-Name !* ANY + } + } + update { + &reply: += &session-state: + } + + # Create the CUI value and add the attribute to Access-Accept. + # Uncomment the line below if *returning* the CUI. +# cui + + # + # If you want to have a log of authentication replies, + # un-comment the following line, and enable the + # 'detail reply_log' module. +# reply_log + + # + # After authenticating the user, do another SQL query. + # + # See "Authentication Logging Queries" in `mods-config/sql/main/$driver/queries.conf` + -sql + + # + # Un-comment the following if you want to modify the user's object + # in LDAP after a successful login. + # +# ldap + + # For Exec-Program and Exec-Program-Wait + exec + # Remove reply message if the response contains an EAP-Message + remove_reply_message_if_eap + # Access-Reject packets are sent through the REJECT sub-section of the + # post-auth section. + # + # Add the ldap module name (or instance) if you have set + # 'edir = yes' in the ldap module configuration + # + Post-Auth-Type REJECT { + # log failed authentications in SQL, too. + -sql + attr_filter.access_reject + + # Insert EAP-Failure message if the request was + # rejected by policy instead of because of an + # authentication failure And already has an EAP message + # For non-ABFAB, we insert the failure all the time, but for ABFAB + # It's more desirable to preserve reply-message when we can + if (&reply:Eap-Message) { + eap + } + + # Remove reply message if the response contains an EAP-Message + remove_reply_message_if_eap + } +} +# +# When the server decides to proxy a request to a home server, +# the proxied request is first passed through the pre-proxy +# stage. This stage can re-write the request, or decide to +# cancel the proxy. +# +# Only a few modules currently have this method. +# +pre-proxy { + # Before proxing the request add an Operator-Name attribute identifying + # if the operator-name is found for this client. + # No need to uncomment this if you have already enabled this in + # the authorize section. +# operator-name + + # The client requests the CUI by sending a CUI attribute + # containing one zero byte. + # Uncomment the line below if *requesting* the CUI. +# cui + + # Uncomment the following line if you want to change attributes + # as defined in the preproxy_users file. +# files + + # Uncomment the following line if you want to filter requests + # sent to remote servers based on the rules defined in the + # 'attrs.pre-proxy' file. +# attr_filter.pre-proxy + + # If you want to have a log of packets proxied to a home + # server, un-comment the following line, and the + # 'detail pre_proxy_log' section, above. +# pre_proxy_log +} +# +# When the server receives a reply to a request it proxied +# to a home server, the request may be massaged here, in the +# post-proxy stage. +# +post-proxy { + + # If you want to have a log of replies from a home server, + # un-comment the following line, and the 'detail post_proxy_log' + # section, above. +# post_proxy_log + + # Uncomment the following line if you want to filter replies from + # remote proxies based on the rules defined in the 'attrs' file. +# attr_filter.post-proxy + + # + # If you are proxying LEAP, you MUST configure the EAP + # module, and you MUST list it here, in the post-proxy + # stage. + # + # You MUST also use the 'nostrip' option in the 'realm' + # configuration. Otherwise, the User-Name attribute + # in the proxied request will not match the user name + # hidden inside of the EAP packet, and the end server will + # reject the EAP request. + # + eap +} +} diff --git a/raddb/sites-available/aws-nlb b/raddb/sites-available/aws-nlb new file mode 100644 index 0000000..acea81e --- /dev/null +++ b/raddb/sites-available/aws-nlb @@ -0,0 +1,46 @@ +# -*- text -*- +###################################################################### +# +# A sample virtual server which handles "health checks" from Amazon +# elastic load balancer. +# +# https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-healthchecks.html +# +# In the Amazon system, configure "proto" as "tcp", and "port" as the port +# given below in the "listen" section. +# +# $Id$ +# +server aws-nlb { + +# +# This should be the IP address of the Amazon load balancer. +# +# If TCP checks come from multiple IP addresses, just list each IP in a separate "client" section. +# +client aws-nlb { + ipaddr = 192.0.2.1 + proto = tcp + secret = "this-will-never-be-used" +} + +# +# Listen on a port. Don't use 80, as that requires root permissions, +# and you don't want to run radiusd as root. +# +listen { + type = status + proto = tcp + ipaddr = * + port = 8000 +} + +# +# This will never get used, but it's here just in case we actually +# get sent RADIUS packets. +# +authorize { + reject +} + +} diff --git a/raddb/sites-available/buffered-sql b/raddb/sites-available/buffered-sql new file mode 100644 index 0000000..74574ac --- /dev/null +++ b/raddb/sites-available/buffered-sql @@ -0,0 +1,161 @@ +# -*- text -*- +###################################################################### +# +# In 2.0.0, radrelay functionality is integrated into the +# server core. This virtual server gives an example of +# using radrelay functionality inside of the server. +# +# In this example, the detail file is read, and the data +# is put into SQL. This configuration is used when a RADIUS +# server on this machine is receiving accounting packets, +# and writing them to the detail file. +# +# The purpose of this virtual server is to de-couple the storage +# of long-term accounting data in SQL from "live" information +# needed by the RADIUS server as it is running. +# +# The benefit of this approach is that for a busy server, the +# overhead of performing SQL queries may be significant. Also, +# if the SQL databases are large (as is typical for ones storing +# months of data), the INSERTs and UPDATEs may take a relatively +# long time. Rather than slowing down the RADIUS server by +# having it interact with a database, you can just log the +# packets to a detail file, and then read that file later at a +# time when the RADIUS server is typically lightly loaded. +# +# If you use on virtual server to log to the detail file, +# and another virtual server (i.e. this one) to read from +# the detail file, then this process will happen automatically. +# A sudden spike of RADIUS traffic means that the detail file +# will grow in size, and the server will be able to handle +# large volumes of traffic quickly. When the traffic dies down, +# the server will have time to read the detail file, and insert +# the data into a long-term SQL database. +# +# $Id$ +# +###################################################################### + +server buffered-sql { + listen { + type = detail + + # The location where the detail file is located. + # This should be on local disk, and NOT on an NFS + # mounted location! + # + # On most systems, this should support file globbing + # e.g. "${radacctdir}/detail-*:*" + # This lets you write many smaller detail files as in + # the example in radiusd.conf: ".../detail-%Y%m%d:%H" + # Writing many small files is often better than writing + # one large file. File globbing also means that with + # a common naming scheme for detail files, then you can + # have many detail file writers, and only one reader. + # + filename = "${radacctdir}/detail-*" + + # + # The server can read accounting packets from the + # detail file much more quickly than those packets + # can be written to a database. If the database is + # overloaded, then bad things can happen. + # + # The server will keep track of how long it takes to + # process an entry from the detail file. It will + # then pause between handling entries. This pause + # allows databases to "catch up", and gives the + # server time to notice that other packets may have + # arrived. + # + # The pause is calculated dynamically, to ensure that + # the load due to reading the detail files is limited + # to a small percentage of CPU time. The + # "load_factor" configuration item is a number + # between 1 and 100. The server will try to keep the + # percentage of time taken by "detail" file entries + # to "load_factor" percentage of the CPU time. + # + # If the "load_factor" is set to 100, then the server + # will read packets as fast as it can, usually + # causing databases to go into overload. + # + load_factor = 10 + + # + # Set the interval for polling the detail file. + # If the detail file doesn't exist, the server will + # wake up, and poll for it every N seconds. + # + # Useful range of values: 1 to 60 + # + poll_interval = 1 + + # + # Set the retry interval for when the home server + # does not respond. The current packet will be + # sent repeatedly, at this interval, until the + # home server responds. + # + # Useful range of values: 5 to 30 + # + retry_interval = 30 + + # + # Track progress through the detail file. When the detail + # file is large, and the server is re-started, it will + # read from the START of the file. + # + # Setting "track = yes" means it will skip packets which + # have already been processed. The default is "no". + # + # track = yes + + # + # In some circumstances it may be desirable for the + # server to start up, process a detail file, and + # immediately quit. To do this enable the "one_shot" + # option below. + # + # Do not enable this for normal server operation. The + # default is "no". + # + # one_shot = no + } + + # + # Pre-accounting. Decide which accounting type to use. + # + preacct { + preprocess + + # + # Ensure that we have a semi-unique identifier for every + # request, and many NAS boxes are broken. + acct_unique + + # + # Read the 'acct_users' file. This isn't always + # necessary, and can be deleted if you do not use it. + files + } + + # + # Accounting. Log the accounting data. + # + accounting { + # + # Log traffic to an SQL database. + # + # See "Accounting queries" in mods-config/sql/main/$driver/queries.conf + # sql + + + # Cisco VoIP specific bulk accounting + # pgsql-voip + + } + + # The requests are not being proxied, so no pre/post-proxy + # sections are necessary. +} diff --git a/raddb/sites-available/challenge b/raddb/sites-available/challenge new file mode 100644 index 0000000..c3aeb08 --- /dev/null +++ b/raddb/sites-available/challenge @@ -0,0 +1,123 @@ +# +# This file gives an example of using Challenge-Response +# +# In this example, the user logs in with a password, which has +# to be "hello". The server will send them a challenge +# consisting of a random number 0..9. The user has to respond +# with that number. +# +# +# $Id$ +# +listen { + type = auth + ipaddr = * + port = 2000 + virtual_server = challenge +} + +server challenge { +authorize { + # + # OTP requires a password. + # + if (!User-Password) { + reject + } + + # + # If there's no State attribute, then this is the first + # request from the user. + # + if (!State) { + # + # Set the authentication to use step 1. + update control { + Auth-Type := Step1 + + # + # For testing we will just set the password to "hello". + # + # Normally the password comes from "ldap" or "sql". + # + Cleartext-Password := "hello" + +# ldap +# sql +# ... + } + } + else { + # + # Check that the password looks like an OTP + # + if (User-Password !~ /[0-9]{6}/) { + reject + } + + # + # Set the authentication to use step 2. + # Set the "known good" password to the number + # saved in the session-state list. + # + update control { + Auth-Type := Step2 + + # + # For testing, ensure that the user enters the same password. + # + # Normally this section should look up a TOTP-Secret, and + # + Cleartext-Password := &session-state:Tmp-Integer-0 + + # + # Normally this section should also set &control:TOTP-Secret, too. + # + TOTP-Password := &User-Password + } + } +} + +authenticate { + Auth-Type Step1 { + # If the password doesn't match, the user is rejected + # immediately. + pap + + # + # For testing, just use a 6 digit random OTP. + # + update session-state { + Tmp-Integer-0 := "%{randstr:nnnnnn}" + } + + # + # For testing, tell the user what OTP to enter. + # + # Don't do this in production... + # + update reply { + Reply-Message := "Please enter OTP %{session-state:Tmp-Integer-0}" + } + + # + # Send an Access-Challenge. + # See raddb/policy.d/control for the definition + # of "challenge" + # + challenge + } + + Auth-Type Step2 { + # + # For testing, do PAP authentication with the password. + # + pap + + # + # Normally you'd do TOTP checks via the TOTP module. + # +# totp + } +} +} diff --git a/raddb/sites-available/channel_bindings b/raddb/sites-available/channel_bindings new file mode 100644 index 0000000..b9f0ac7 --- /dev/null +++ b/raddb/sites-available/channel_bindings @@ -0,0 +1,17 @@ +# +# A virtual server which is used to validate channel-bindings. +# +# $Id$ +# +server channel_bindings { + # + # Only the "authorize" section is needed. + # + authorize { + # In general this section should include a policy for each type + # of channel binding that may be in use. For example each lower + # layer such as GSS-EAP (RFC 7055) or IEEE 802.11I is likely to + # need a separate channel binding policy. + abfab_channel_bindings + } +} diff --git a/raddb/sites-available/check-eap-tls b/raddb/sites-available/check-eap-tls new file mode 100644 index 0000000..69065e1 --- /dev/null +++ b/raddb/sites-available/check-eap-tls @@ -0,0 +1,135 @@ +# This virtual server allows EAP-TLS to reject access requests +# based on some attributes of the certificates involved. +# +# To use this virtual server, you must enable it in the tls +# section of mods-enabled/eap as well as adding a link to this +# file in sites-enabled/. +# +# +# Value-pairs that are available for checking include: +# +# TLS-Client-Cert-Subject +# TLS-Client-Cert-Issuer +# TLS-Client-Cert-Common-Name +# TLS-Client-Cert-Subject-Alt-Name-Email +# +# To see a full list of attributes, run the server in debug mode +# with this virtual server configured, and look at the attributes +# passed in to this virtual server. +# +# +# This virtual server is also useful when using EAP-TLS as it is +# only called once, just before the final Accept is about to be +# returned from eap, whereas the outer authorize section is called +# multiple times for each challenge / response. For this reason, +# here may be a good location to put authentication logging, and +# modules that check for further authorization, especially if they +# hit external services such as sql or ldap. + + +server check-eap-tls { + + +# Authorize - this is the only section required. +# +# To accept the access request, set Auth-Type = Accept, otherwise +# set it to Reject. + +authorize { + + # + # By default, we just accept the request: + # + update config { + &Auth-Type := Accept + } + + + # + # Check the client certificate matches a string, and reject otherwise + # + +# if ("%{TLS-Client-Cert-Common-Name}" == 'client.example.com') { +# update config { +# &Auth-Type := Accept +# } +# } +# else { +# update config { +# &Auth-Type := Reject +# } +# update reply { +# &Reply-Message := "Your certificate is not valid." +# } +# } + + + # + # Check the client certificate common name against the supplied User-Name + # +# if (&User-Name == "host/%{TLS-Client-Cert-Common-Name}") { +# update config { +# &Auth-Type := Accept +# } +# } +# else { +# update config { +# &Auth-Type := Reject +# } +# } + + + # + # This is a convenient place to call LDAP, for example, when using + # EAP-TLS, as it will only be called once, after all certificates as + # part of the EAP-TLS challenge process have been verified. + # + # An example could be to use LDAP to check that the connecting host, as + # well as presenting a valid certificate, is also in a group based on + # the User-Name (assuming this contains the service principal name). + # Settings such as the following could be used in the ldap module + # configuration: + # + # basedn = "dc=example, dc=com" + # filter = "(servicePrincipalName=%{User-Name})" + # base_filter = "(objectClass=computer)" + # groupname_attribute = cn + # groupmembership_filter = "(&(objectClass=group)(member=%{control:Ldap-UserDn}))" + +# ldap + + # Now let's test membership of an LDAP group (the ldap bind user will + # need permission to read this group membership): + +# if (!(Ldap-Group == "Permitted-Laptops")) { +# update config { +# &Auth-Type := Reject +# } +# } + + # or, to be more specific, you could use the group's full DN: + # if (!(Ldap-Group == "CN=Permitted-Laptops,OU=Groups,DC=example,DC=org")) { + + + # + # This may be a better place to call the files modules when using + # EAP-TLS, as it will only be called once, after the challenge-response + # iteration has completed. + # + +# files + + + # + # Log all request attributes, plus TLS certificate details, to the + # auth_log file. Again, this is just once per connection request, so + # may be preferable than in the outer authorize section. It is + # suggested that 'auth_log' also be in the outer post-auth and + # Post-Auth REJECT sections to log reply packet details, too. + # + + auth_log + +} +} + diff --git a/raddb/sites-available/coa b/raddb/sites-available/coa new file mode 100644 index 0000000..c10f88e --- /dev/null +++ b/raddb/sites-available/coa @@ -0,0 +1,49 @@ +# -*- text -*- +###################################################################### +# +# Sample virtual server for receiving a CoA or Disconnect-Request packet. +# + +# Listen on the CoA port. +# +# This uses the normal set of clients, with the same secret as for +# authentication and accounting. +# +listen { + type = coa + ipaddr = * + port = 3799 + virtual_server = coa +} + +server coa { + # When a packet is received, it is processed through the + # recv-coa section. This applies to *both* CoA-Request and + # Disconnect-Request packets. + recv-coa { + # CoA && Disconnect packets can be proxied in the same + # way as authentication or accounting packets. + # Just set Proxy-To-Realm, or Home-Server-Pool, and the + # packets will be proxied. + + # Do proxying based on realms here. You don't need + # "IPASS" or "ntdomain", as the proxying is based on + # the Operator-Name attribute. It contains the realm, + # and ONLY the realm (prefixed by a '1') + suffix + + # Insert your own policies here. + ok + } + + # When a packet is sent, it is processed through the + # send-coa section. This applies to *both* CoA-Request and + # Disconnect-Request packets. + send-coa { + # Sample module. + ok + } + + # You can use pre-proxy and post-proxy sections here, too. + # They will be processed for sending && receiving proxy packets. +} diff --git a/raddb/sites-available/coa-relay b/raddb/sites-available/coa-relay new file mode 100644 index 0000000..05fd6bc --- /dev/null +++ b/raddb/sites-available/coa-relay @@ -0,0 +1,331 @@ +# -*- text -*- +###################################################################### +# +# This virtual server simplifies the process of sending CoA-Request or +# Disconnect-Request packets to a NAS. +# +# This virtual server will receive CoA-Request or Disconnect-Request +# packets that contain *minimal* identifying information. e.g. Just +# a User-Name, or maybe just an Acct-Session-Id attribute. It will +# look up that information in a database in order to find the rest of +# the session data. e.g. NAS-IP-Address, NAS-Identifier, NAS-Port, +# etc. That information will be added to the packet, which will then +# be sent to the NAS. +# +# This process is useful because NASes require the CoA packets to +# contain "session identification" attributes in order to to do CoA +# or Disconnect. If the attributes aren't in the packet, then the +# NAS will NAK the request. This NAK happens even if you ask to +# disconnect "User-Name = bob", and there is only one session with a +# "bob" active. +# +# Using this virtual server makes the CoA or Disconnect process +# easier. Just tell FreeRADIUS to disconnect "User-Name = bob", and +# FreeRADIUS will take care of adding the "session identification" +# attributes. +# +# The process is as follows: +# +# - A CoA/Disconnect-Request is received by FreeRADIUS. +# - The radacct table is searched for active sessions that match each of +# the provided identifier attributes: User-Name, Acct-Session-Id. The +# search returns the owning NAS and Acct-Unique-Id for the matching +# session/s. +# - The original CoA/Disconnect-Request content is written to a detail file +# with custom attributes representing the NAS and Acct-Session-Id. +# - A detail reader follows the file and originates CoA/Disconenct-Requests +# containing the original content, relayed to the corresponding NAS for +# each session using the custom attributes. +# +# This simplifies scripting directly against a set of NAS devices since a +# script need only send a single CoA/Disconnect to FreeRADIUS which will +# then: +# +# - Lookup all active sessions belonging to a user, in the case that only a +# User-Name attribute is provided in the request +# - Handle routing of the request to the correct NAS, in the case of a +# multi-NAS setup +# +# For example, to disconnect a specific session: +# +# $ echo 'Acct-Session-Id = "769df3 312343"' | \ +# radclient 127.0.0.1 disconnect testing123 +# +# To perform a CoA update of all active sessions belonging to a user: +# +# $ cat <<EOF | radclient 127.0.0.1 coa testing123 +# User-Name = bob +# Cisco-AVPair = "subscriber:sub-qos-policy-out=q_out_uncapped" +# EOF +# +# In addition to configuring and activating this site, a detail +# writer module must be configured in mods-enabled: +# +# detail detail_coa { +# filename = ${radacctdir}/detail_coa +# escape_filenames = no +# permissions = 0600 +# header = "%t" +# locking = yes +# } +# + + +# Listen on a local CoA port. +# +# This uses the normal set of clients, with the same secret as for +# authentication and accounting. +# +listen { + type = coa + ipaddr = 127.0.0.1 + port = 3799 + virtual_server = coa +} + +# +# Receive CoA/Disconnect, lookup sessions, write them to a detail file +# +server coa { + # + # When a packet is received, it is processed through the + # recv-coa section. This applies to *both* CoA-Request and + # Disconnect-Request packets. + # + recv-coa { + # + # Lookup all active sessions matching User-Name and/or + # Acct-Session-Id and write each session (which includes to + # owning NAS and session ID) to a detail file. + # + # Returns a single result in the format: + # + # NasIpAddress1#AcctSessionId1|NasIPAddress2#AcctSessionId2|... + # + # i.e. each session is separated by '|', and attributes + # within a session are separated by '#' + # + # You will likely have to update the SELECT to add in + # any other "session identification" attributes + # needed by the NAS. These may include NAS-Port, + # NAS-Identifier, etc. Only the NAS vendor knows + # what these attributes are unfortunately, so we + # cannot give more detailed advice here. + # + update control { + + # + # Example MySQL lookup + # +# Tmp-String-0 := "%{sql:SELECT IFNULL(GROUP_CONCAT(CONCAT(nasipaddress,'#',acctsessionid) separator '|'),'') FROM (SELECT * FROM radacct WHERE ('%{User-Name}'='' OR UserName='%{User-Name}') AND ('%{Acct-Session-Id}'='' OR acctsessionid = '%{Acct-Session-Id}') AND AcctStopTime IS NULL) a}" + + # + # Example PostgreSQL lookup + # +# Tmp-String-0 := "%{sql:SELECT STRING_AGG(CONCAT(nasipaddress,'#',acctsessionid),'|') FROM (SELECT * FROM radacct WHERE ('%{User-Name}'='' OR UserName='%{User-Name}') AND ('%{Acct-Session-Id}'='' OR acctsessionid = '%{Acct-Session-Id}') AND AcctStopTime IS NULL) a}" + + } + + # + # Split the string and split into pieces. + # + if (&control:Tmp-String-0 != "" && "%{explode:&control:Tmp-String-0 |}") { + foreach &control:Tmp-String-0 { + if ("%{Foreach-Variable-0}" =~ /([^#]*)#(.*)/) { + update request { + COA-Packet-Type := "%{Packet-Type}" + + COA-Packet-DST-IP-Address := "%{1}" + COA-Acct-Session-Id := "%{2}" + + # + # Add any other attributes here. + # + + # Set the CoA/Disconnect port + COA-Packet-DST-Port := 1700 + + # SQL-User-Name was left over + # from the xlat + SQL-User-Name !* ANY + + # Uncomment if the NAS does not + # expect User-Name + #User-Name !* ANY + + } + + # + # If we're sending a CoA packet, send it out. + # + if (COA-Packet-DST-IP-Address && \ + COA-Acct-Session-Id != "") { + detail_coa.accounting + } + } + } + } else { + # No sessions found + reject + } + + } +} + +# +# Detail file reader that processes the queue of CoA/Disconnect requests +# +server coa-buffered-reader { + listen { + # + # See sites-available/buffered-sql for more details on + # all the options available for the detail reader. + # + type = detail + filename = "${radacctdir}/detail_coa" + load_factor = 90 + track = yes + } + + # + # For historical reasons packets from the detail file reader are + # processed through the "accounting" section. + # + accounting { + switch &COA-Packet-Type { + case "Disconnect-Request" { + update { + # Include given attributes + disconnect: += request:[*] + + disconnect:Packet-DST-IP-Address := \ + &COA-Packet-DST-IP-Address + disconnect:Packet-DST-Port := \ + &COA-Packet-DST-Port + disconnect:Acct-Session-Id := \ + &COA-Acct-Session-Id + + # Some NASs want these, others don't + disconnect:Event-Timestamp := "%l" + disconnect:Message-Authenticator := 0x00 + + # Remove this. We're not accounting + disconnect:Acct-Delay-Time !* ANY + + } + } + + case "CoA-Request" { + update { + # Include given attributes + coa: += request:[*] + + coa:Packet-DST-IP-Address := \ + &COA-Packet-DST-IP-Address + coa:Packet-DST-Port := \ + &COA-Packet-DST-Port + coa:Acct-Session-Id := \ + &COA-Acct-Session-Id + + # Some NASs want these, others don't + coa:Event-Timestamp := "%l" + coa:Message-Authenticator := 0x00 + + # + # Remove attributes which will confuse the NAS + # + # The NAS will "helpfully" NAK the packet + # if it contains attributes which are NOT + # "session identification" attributes. + # + # Those attributes should be listed here. + # + coa:Acct-Delay-Time !* ANY + coa:Proxy-State !* ANY + } + } + + } + + # + # ACK the CoA / Disconnect packet. + # + ok + } +} + + +# The CoA packet is in the "proxy-request" attribute list. +# The CoA reply (if any) is in the "proxy-reply" attribute list. +# +server originate-coa-relay { + # + # Handle the responses here. + # + post-proxy { + switch &proxy-reply:Packet-Type { + case CoA-ACK { + ok + } + + case CoA-NAK { + # the NAS didn't like the CoA request + ok + } + + case Disconnect-ACK { + ok + } + + case Disconnect-NAK { + # the NAS didn't like the Disconnect request + ok + } + + # Invalid packet type. This shouldn't happen. + case { + fail + } + } + + # + # These methods are run when there is NO response + # to the request. + # + Post-Proxy-Type Fail-CoA { + ok + } + + Post-Proxy-Type Fail-Disconnect { + ok + } + } +} + + +# +# Homeserver CoA / Disconnect endpoints +# +# See proxy.conf for more details on configuring a home_server and +# home_server_pool. +# +home_server coa-nas1 { + type = coa + + # Update these to match your NAS + ipaddr = 192.0.2.1 + port = 1700 + secret = testing1234 + + coa { + irt = 2 + mrt = 16 + mrc = 5 + mrd = 30 + } +} +home_server_pool coa-nas1 { + type = fail-over + home_server = coa-nas1 + virtual_server = originate-coa-relay +} diff --git a/raddb/sites-available/control-socket b/raddb/sites-available/control-socket new file mode 100644 index 0000000..97ba9ef --- /dev/null +++ b/raddb/sites-available/control-socket @@ -0,0 +1,92 @@ +# -*- text -*- +###################################################################### +# +# Control socket interface. +# +# In the future, we will add username/password checking for +# connections to the control socket. We will also add +# command authorization, where the commands entered by the +# administrator are run through a virtual server before +# they are executed. +# +# For now, anyone who has permission to connect to the socket +# has nearly complete control over the server. Be warned! +# +# This functionality is NOT enabled by default. +# +# See also the "radmin" program, which is used to communicate +# with the server over the control socket. +# +# $Id$ +# +###################################################################### +listen { + # + # Listen on the control socket. + # + type = control + + # + # Socket location. + # + # This file is created with the server's uid and gid. + # It's permissions are r/w for that user and group, and + # no permissions for "other" users. These permissions form + # minimal security, and should not be relied on. + # + socket = ${run_dir}/${name}.sock + + # + # Peercred auth + # + # By default the server users the peercred feature of unix + # sockets to get the UID and GID of the user connecting to + # the socket. You may choose to disable this functionality + # and rely on the file system for enforcing permissions. + # + # On most Unix systems, the permissions set on the socket + # are not enforced, but the ones on the directory containing + # the socket are. + # + # To use filesystem permissions you should create a new + # directory just to house the socket file, and set + # appropriate permissions on that. + # +# peercred = no +# socket = ${run_dir}/control/${name}.sock + + # + # The following two parameters perform authentication and + # authorization of connections to the control socket. + # + # If not set, then ANYONE can connect to the control socket, + # and have complete control over the server. This is likely + # not what you want. + # + # One, or both, of "uid" and "gid" should be set. If set, the + # corresponding value is checked. Unauthorized users result + # in an error message in the log file, and the connection is + # closed. + # + + # + # Name of user that is allowed to connect to the control socket. + # +# uid = radius + + # + # Name of group that is allowed to connect to the control socket. + # +# gid = radius + + # + # Access mode. + # + # This can be used to give *some* administrators access to + # monitor the system, but not to change it. + # + # ro = read only access (default) + # rw = read/write access. + # +# mode = rw +} diff --git a/raddb/sites-available/copy-acct-to-home-server b/raddb/sites-available/copy-acct-to-home-server new file mode 100644 index 0000000..cd085e0 --- /dev/null +++ b/raddb/sites-available/copy-acct-to-home-server @@ -0,0 +1,202 @@ +# -*- text -*- +###################################################################### +# +# In 2.0.0, radrelay functionality is integrated into the +# server core. This virtual server gives an example of +# using radrelay functionality inside of the server. +# +# In this example, the detail file is read, and the packets +# are proxied to a home server. You will have to configure +# realms, home_server_pool, and home_server in proxy.conf +# for this to work. +# +# The purpose of this virtual server is to enable duplication +# of information across a load-balanced, or fail-over set of +# servers. For example, if a group of clients lists two +# home servers (primary, secondary), then RADIUS accounting +# messages will go only to one server at a time. This file +# configures a server (primary, secondary) to send copies of +# the accounting information to each other. +# +# That way, each server has the same set of information, and +# can make the same decision about the user. +# +# $Id$ +# +###################################################################### + +server copy-acct-to-home-server { + listen { + type = detail + + # + # See sites-available/buffered-sql for more details on + # all the options available for the detail reader. + # + + ###################################################### + # + # !!!! WARNING !!!! + # + # The detail file reader acts just like a NAS. + # + # This means that if accounting fails, the packet + # is re-tried FOREVER. It is YOUR responsibility + # to write an accounting policy that returns "ok" + # if the packet was processed properly, "fail" on + # a database error, AND "ok" if you want to ignore + # the packet (e.g. no Acct-Status-Type). + # + # Neither the detail file write OR the detail file + # reader look at the contents of the packets. They + # just either dump the packet verbatim to the file, + # or read it verbatim from the file and pass it to + # the server. + # + ###################################################### + + + # The location where the detail file is located. + # This should be on local disk, and NOT on an NFS + # mounted location! + # + # On most systems, this should support file globbing + # e.g. "${radacctdir}/detail-*:*" + # This lets you write many smaller detail files as in + # the example in radiusd.conf: ".../detail-%Y%m%d:%H" + # Writing many small files is often better than writing + # one large file. File globbing also means that with + # a common naming scheme for detail files, then you can + # have many detail file writers, and only one reader. + # + # Do NOT copy the "filename" configuration from the + # "detail" module here. It won't work. Instead, use + # file globbing (or wildcards), such as: + # + # filename = ${radacctdir}/reader1/detail-* + # + filename = ${radacctdir}/detail + + # + # The server can read accounting packets from the + # detail file much more quickly than those packets + # can be written to a database. If the database is + # overloaded, then bad things can happen. + # + # The server will keep track of how long it takes to + # process an entry from the detail file. It will + # then pause between handling entries. This pause + # allows databases to "catch up", and gives the + # server time to notice that other packets may have + # arrived. + # + # The pause is calculated dynamically, to ensure that + # the load due to reading the detail files is limited + # to a small percentage of CPU time. The + # "load_factor" configuration item is a number + # between 1 and 100. The server will try to keep the + # percentage of time taken by "detail" file entries + # to "load_factor" percentage of the CPU time. + # + # If the "load_factor" is set to 100, then the server + # will read packets as fast as it can, usually + # causing databases to go into overload. + # + load_factor = 10 + + # + # Track progress through the detail file. When the detail + # file is large, and the server is re-started, it will + # read from the START of the file. + # + # Setting "track = yes" means it will skip packets which + # have already been processed. The default is "no". + # + # track = yes + + } + + # + # Pre-accounting. Decide which accounting type to use. + # + preacct { + preprocess + + # Since we're just proxying, we don't need acct_unique. + + # + # Look for IPASS-style 'realm/', and if not found, look for + # '@realm', and decide whether or not to proxy, based on + # that. + # + # Accounting requests are generally proxied to the same + # home server as authentication requests. +# IPASS +# suffix +# ntdomain + + # + # Edit proxy.conf to add a "home_server" section, + # which points to the other server. + # + # Then set that home_server name here. + # + update control { + Home-Server-Name := "name_of_home_server_from_proxy.conf" + } + + # + # Read the 'acct_users' file. This isn't always + # necessary, and can be deleted if you do not use it. + files + } + + # + # Accounting. Log the accounting data. + # + accounting { + # + # Since we're proxying, we don't log anything + # locally. Ensure that the accounting section + # "succeeds" by forcing an "ok" return. + ok + } + + + # + # When the server decides to proxy a request to a home server, + # the proxied request is first passed through the pre-proxy + # stage. This stage can re-write the request, or decide to + # cancel the proxy. + # + # Only a few modules currently have this method. + # + pre-proxy { + + # If you want to have a log of packets proxied to a home + # server, un-comment the following line, and the + # 'detail pre_proxy_log' section in radiusd.conf. + # pre_proxy_log + } + + # + # When the server receives a reply to a request it proxied + # to a home server, the request may be massaged here, in the + # post-proxy stage. + # + post-proxy { + # + + # If you want to have a log of replies from a home + # server, un-comment the following line, and the + # 'detail post_proxy_log' section in radiusd.conf. + # post_proxy_log + + + # Uncomment the following line if you want to filter + # replies from remote proxies based on the rules + # defined in the 'attrs' file. + + # attr_filter + } +} diff --git a/raddb/sites-available/decoupled-accounting b/raddb/sites-available/decoupled-accounting new file mode 100644 index 0000000..abf455c --- /dev/null +++ b/raddb/sites-available/decoupled-accounting @@ -0,0 +1,139 @@ +# -*- text -*- +###################################################################### +# +# This is a sample configuration for "decoupled" accounting. +# "Decoupled" accounting is where the accounting packets are +# NOT written "live" to the back-end database. This method +# can only be used if you are not interested in "live" +# accounting. i.e. Where you can tolerate delays that may be +# a few seconds, before accounting packets get written to +# the DB. +# +# Oddly enough, this method can speed up the processing of +# accounting packets, as all database activity is serialized. +# +# This file is NOT meant to be used as-is. It needs to be +# edited to match your local configuration. +# +# $Id$ +# +###################################################################### + +# Define a virtual server to write the accounting packets. +# Any "listen" section that listens on an accounting port should +# set "virtual_server = write-detail.example.com +server write_detail.example.com { + accounting { + # + # Write the "detail" files. + # + # See raddb/modules/detail.example.com for more info. + detail.example.com + } + + # That's it! +} + +# Define a virtual server to process the accounting packets. +server read-detail.example.com { + # Read accounting packets from the detail file(s) for + # the home server. + listen { + type = detail + filename = "${radacctdir}/detail.example.com/detail-*:*" + load_factor = 10 + track = yes + } + + # All packets read from the detail file are processed through + # the preacct && accounting sections. + # + # The following text is copied verbatim from sites-available/default. + # You should edit it for your own local configuration. + +# +# Pre-accounting. Decide which accounting type to use. +# +preacct { + preprocess + + # + # Ensure that we have a semi-unique identifier for every + # request, and many NAS boxes are broken. + acct_unique + + # + # Look for IPASS-style 'realm/', and if not found, look for + # '@realm', and decide whether or not to proxy, based on + # that. + # + # Accounting requests are generally proxied to the same + # home server as authentication requests. +# IPASS + suffix +# ntdomain + + # + # Read the 'acct_users' file + files +} + +# +# Accounting. Log the accounting data. +# +accounting { + # + # Create a 'detail'ed log of the packets. + # Note that accounting requests which are proxied + # are also logged in the detail file. + detail +# daily + + # Update the wtmp file + # + # If you don't use "radlast", you can delete this line. + unix + + # + # For Simultaneous-Use tracking. + # + # Due to packet losses in the network, the data here + # may be incorrect. There is little we can do about it. + radutmp +# sradutmp + + # + # Return an address to the IP Pool when we see a stop record. + # + # Ensure that &control:Pool-Name is set to determine which + # pool of IPs are used. +# sqlippool + + # + # Log traffic to an SQL database. + # + # NOTE! You will have to ensure that any accounting packets + # NOT handled by the SQL module (e.g. "stop with zero session length" + # result in the accounting section still returning "ok". + # + # Otherwise, the server will think that the accounting packet + # was NOT handled properly, and will keep trying to process it + # through this virtual server! + # + # See "Accounting queries" in `mods-config/sql/main/$driver/queries.conf` +# sql + + # Cisco VoIP specific bulk accounting +# pgsql-voip + + # Filter attributes from the accounting response. + attr_filter.accounting_response + + # + # See "Autz-Type Status-Server" for how this works. + # +# Acct-Type Status-Server { +# +# } +} +} diff --git a/raddb/sites-available/default b/raddb/sites-available/default new file mode 100644 index 0000000..dbad8e4 --- /dev/null +++ b/raddb/sites-available/default @@ -0,0 +1,1153 @@ +###################################################################### +# +# As of 2.0.0, FreeRADIUS supports virtual hosts using the +# "server" section, and configuration directives. +# +# Virtual hosts should be put into the "sites-available" +# directory. Soft links should be created in the "sites-enabled" +# directory to these files. This is done in a normal installation. +# +# If you are using 802.1X (EAP) authentication, please see also +# the "inner-tunnel" virtual server. You will likely have to edit +# that, too, for authentication to work. +# +# $Id$ +# +###################################################################### +# +# Read "man radiusd" before editing this file. See the section +# titled DEBUGGING. It outlines a method where you can quickly +# obtain the configuration you want, without running into +# trouble. See also "man unlang", which documents the format +# of this file. +# +# This configuration is designed to work in the widest possible +# set of circumstances, with the widest possible number of +# authentication methods. This means that in general, you should +# need to make very few changes to this file. +# +# The best way to configure the server for your local system +# is to CAREFULLY edit this file. Most attempts to make large +# edits to this file will BREAK THE SERVER. Any edits should +# be small, and tested by running the server with "radiusd -X". +# Once the edits have been verified to work, save a copy of these +# configuration files somewhere. (e.g. as a "tar" file). Then, +# make more edits, and test, as above. +# +# There are many "commented out" references to modules such +# as ldap, sql, etc. These references serve as place-holders. +# If you need the functionality of that module, then configure +# it in radiusd.conf, and un-comment the references to it in +# this file. In most cases, those small changes will result +# in the server being able to connect to the DB, and to +# authenticate users. +# +###################################################################### + +server default { +# +# If you want the server to listen on additional addresses, or on +# additional ports, you can use multiple "listen" sections. +# +# Each section make the server listen for only one type of packet, +# therefore authentication and accounting have to be configured in +# different sections. +# +# The server ignore all "listen" section if you are using '-i' and '-p' +# on the command line. +# +listen { + # Type of packets to listen for. + # Allowed values are: + # auth listen for authentication packets + # acct listen for accounting packets + # auth+acct listen for both authentication and accounting packets + # proxy IP to use for sending proxied packets + # detail Read from the detail file. For examples, see + # raddb/sites-available/copy-acct-to-home-server + # status listen for Status-Server packets. For examples, + # see raddb/sites-available/status + # coa listen for CoA-Request and Disconnect-Request + # packets. For examples, see the file + # raddb/sites-available/coa + # + type = auth + + # Note: "type = proxy" lets you control the source IP used for + # proxying packets, with some limitations: + # + # * A proxy listener CANNOT be used in a virtual server section. + # * You should probably set "port = 0". + # * Any "clients" configuration will be ignored. + # + # See also proxy.conf, and the "src_ipaddr" configuration entry + # in the sample "home_server" section. When you specify the + # source IP address for packets sent to a home server, the + # proxy listeners are automatically created. + + # ipaddr/ipv4addr/ipv6addr - IP address on which to listen. + # If multiple ones are listed, only the first one will + # be used, and the others will be ignored. + # + # The configuration options accept the following syntax: + # + # ipv4addr - IPv4 address (e.g.192.0.2.3) + # - wildcard (i.e. *) + # - hostname (radius.example.com) + # Only the A record for the host name is used. + # If there is no A record, an error is returned, + # and the server fails to start. + # + # ipv6addr - IPv6 address (e.g. 2001:db8::1) + # - wildcard (i.e. *) + # - hostname (radius.example.com) + # Only the AAAA record for the host name is used. + # If there is no AAAA record, an error is returned, + # and the server fails to start. + # + # ipaddr - IPv4 address as above + # - IPv6 address as above + # - wildcard (i.e. *), which means IPv4 wildcard. + # - hostname + # If there is only one A or AAAA record returned + # for the host name, it is used. + # If multiple A or AAAA records are returned + # for the host name, only the first one is used. + # If both A and AAAA records are returned + # for the host name, only the A record is used. + # + # ipv4addr = * + # ipv6addr = * + ipaddr = * + + # Port on which to listen. + # Allowed values are: + # integer port number (1812) + # 0 means "use /etc/services for the proper port" + port = 0 + + # Some systems support binding to an interface, in addition + # to the IP address. This feature isn't strictly necessary, + # but for sites with many IP addresses on one interface, + # it's useful to say "listen on all addresses for eth0". + # + # If your system does not support this feature, you will + # get an error if you try to use it. + # +# interface = eth0 + + # Per-socket lists of clients. This is a very useful feature. + # + # The name here is a reference to a section elsewhere in + # radiusd.conf, or clients.conf. Having the name as + # a reference allows multiple sockets to use the same + # set of clients. + # + # If this configuration is used, then the global list of clients + # is IGNORED for this "listen" section. Take care configuring + # this feature, to ensure you don't accidentally disable a + # client you need. + # + # See clients.conf for the configuration of "per_socket_clients". + # +# clients = per_socket_clients + + # + # Set the default UDP receive buffer size. In most cases, + # the default values set by the kernel are fine. However, in + # some cases the NASes will send large packets, and many of + # them at a time. It is then possible to overflow the + # buffer, causing the kernel to drop packets before they + # reach FreeRADIUS. Increasing the size of the buffer will + # avoid these packet drops. + # +# recv_buff = 65536 + + # + # Connection limiting for sockets with "proto = tcp". + # + # This section is ignored for other kinds of sockets. + # + limit { + # + # Limit the number of simultaneous TCP connections to the socket + # + # The default is 16. + # Setting this to 0 means "no limit" + max_connections = 16 + + # The per-socket "max_requests" option does not exist. + + # + # The lifetime, in seconds, of a TCP connection. After + # this lifetime, the connection will be closed. + # + # Setting this to 0 means "forever". + lifetime = 0 + + # + # The idle timeout, in seconds, of a TCP connection. + # If no packets have been received over the connection for + # this time, the connection will be closed. + # + # Setting this to 0 means "no timeout". + # + # We STRONGLY RECOMMEND that you set an idle timeout. + # + idle_timeout = 30 + } +} + +# +# This second "listen" section is for listening on the accounting +# port, too. +# +listen { + ipaddr = * +# ipv6addr = :: + port = 0 + type = acct +# interface = eth0 +# clients = per_socket_clients + + limit { + # The number of packets received can be rate limited via the + # "max_pps" configuration item. When it is set, the server + # tracks the total number of packets received in the previous + # second. If the count is greater than "max_pps", then the + # new packet is silently discarded. This helps the server + # deal with overload situations. + # + # The packets/s counter is tracked in a sliding window. This + # means that the pps calculation is done for the second + # before the current packet was received. NOT for the current + # wall-clock second, and NOT for the previous wall-clock second. + # + # Useful values are 0 (no limit), or 100 to 10000. + # Values lower than 100 will likely cause the server to ignore + # normal traffic. Few systems are capable of handling more than + # 10K packets/s. + # + # It is most useful for accounting systems. Set it to 50% + # more than the normal accounting load, and you can be sure that + # the server will never get overloaded + # +# max_pps = 0 + + # Only for "proto = tcp". These are ignored for "udp" sockets. + # +# idle_timeout = 0 +# lifetime = 0 +# max_connections = 0 + } +} + +# IPv6 versions of the above - read their full config to understand options +listen { + type = auth + ipv6addr = :: # any. ::1 == localhost + port = 0 +# interface = eth0 +# clients = per_socket_clients + limit { + max_connections = 16 + lifetime = 0 + idle_timeout = 30 + } +} + +listen { + ipv6addr = :: + port = 0 + type = acct +# interface = eth0 +# clients = per_socket_clients + + limit { +# max_pps = 0 +# idle_timeout = 0 +# lifetime = 0 +# max_connections = 0 + } +} + +# Authorization. First preprocess (hints and huntgroups files), +# then realms, and finally look in the "users" file. +# +# Any changes made here should also be made to the "inner-tunnel" +# virtual server. +# +# The order of the realm modules will determine the order that +# we try to find a matching realm. +# +# Make *sure* that 'preprocess' comes before any realm if you +# need to setup hints for the remote radius server +authorize { + # + # Take a User-Name, and perform some checks on it, for spaces and other + # invalid characters. If the User-Name appears invalid, reject the + # request. + # + # See policy.d/filter for the definition of the filter_username policy. + # + filter_username + + # + # Some broken equipment sends passwords with embedded zeros. + # i.e. the debug output will show + # + # User-Password = "password\000\000" + # + # This policy will fix it to just be "password". + # +# filter_password + + # + # The preprocess module takes care of sanitizing some bizarre + # attributes in the request, and turning them into attributes + # which are more standard. + # + # It takes care of processing the 'raddb/mods-config/preprocess/hints' + # and the 'raddb/mods-config/preprocess/huntgroups' files. + preprocess + + # If you intend to use CUI and you require that the Operator-Name + # be set for CUI generation and you want to generate CUI also + # for your local clients then uncomment the operator-name + # below and set the operator-name for your clients in clients.conf +# operator-name + + # + # If you want to generate CUI for some clients that do not + # send proper CUI requests, then uncomment the + # cui below and set "add_cui = yes" for these clients in clients.conf +# cui + + # + # If you want to have a log of authentication requests, + # un-comment the following line. +# auth_log + + # + # The chap module will set 'Auth-Type := CHAP' if we are + # handling a CHAP request and Auth-Type has not already been set + chap + + # + # If the users are logging in with an MS-CHAP-Challenge + # attribute for authentication, the mschap module will find + # the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP' + # to the request, which will cause the server to then use + # the mschap module for authentication. + mschap + + # + # If you have a Cisco SIP server authenticating against + # FreeRADIUS, uncomment the following line, and the 'digest' + # line in the 'authenticate' section. + digest + + # + # The WiMAX specification says that the Calling-Station-Id + # is 6 octets of the MAC. This definition conflicts with + # RFC 3580, and all common RADIUS practices. If you are using + # old style WiMAX (non LTE) the un-commenting the "wimax" module + # here means that it will fix the Calling-Station-Id attribute to + # the normal format as specified in RFC 3580 Section 3.21. + # + # If you are using WiMAX 2.1 (LTE) then un-commenting will allow + # the module to handle SQN resyncronisation. Prior to calling the + # module it is necessary to populate the following attributes + # with the relevant keys: + # control:WiMAX-SIM-Ki + # control:WiMAX-SIM-OPc + # + # If WiMAX-Re-synchronization-Info is found in the request then + # the module will attempt to extract SQN and store it in + # control:WiMAX-SIM-SQN. Also a copy of RAND is extracted to + # control:WiMAX-SIM-RAND. + # + # If the SIM cannot be authenticated using Ki and OPc then reject + # will be returned. +# wimax + + # + # Look for IPASS style 'realm/', and if not found, look for + # '@realm', and decide whether or not to proxy, based on + # that. +# IPASS + + # + # Look for realms in user@domain format + suffix +# ntdomain + + # + # This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP + # authentication. + # + # It also sets the EAP-Type attribute in the request + # attribute list to the EAP type from the packet. + # + # The EAP module returns "ok" or "updated" if it is not yet ready + # to authenticate the user. The configuration below checks for + # "ok", and stops processing the "authorize" section if so. + # + # Any LDAP and/or SQL servers will not be queried for the + # initial set of packets that go back and forth to set up + # TTLS or PEAP. + # + # The "updated" check is commented out for compatibility with + # previous versions of this configuration, but you may wish to + # uncomment it as well; this will further reduce the number of + # LDAP and/or SQL queries for TTLS or PEAP. + # + eap { + ok = return +# updated = return + } + + # + # Pull crypt'd passwords from /etc/passwd or /etc/shadow, + # using the system API's to get the password. If you want + # to read /etc/passwd or /etc/shadow directly, see the + # mods-available/passwd module. + # +# unix + + # + # Read the 'users' file. In v3, this is located in + # raddb/mods-config/files/authorize + files + + # + # Look in an SQL database. The schema of the database + # is meant to mirror the "users" file. + # + # See "Authorization Queries" in mods-available/sql + -sql + + # + # If you are using /etc/smbpasswd, and are also doing + # mschap authentication, the un-comment this line, and + # configure the 'smbpasswd' module. +# smbpasswd + + # + # The ldap module reads passwords from the LDAP database. + -ldap + + # + # If you're using Active Directory and PAP, then uncomment + # the following lines, and the "Auth-Type LDAP" section below. + # + # This will let you do PAP authentication to AD. + # +# if ((ok || updated) && User-Password && !control:Auth-Type) { +# update control { +# &Auth-Type := ldap +# } +# } + + # + # Enforce daily limits on time spent logged in. +# daily + + # + expiration + logintime + + # + # If no other module has claimed responsibility for + # authentication, then try to use PAP. This allows the + # other modules listed above to add a "known good" password + # to the request, and to do nothing else. The PAP module + # will then see that password, and use it to do PAP + # authentication. + # + # This module should be listed last, so that the other modules + # get a chance to set Auth-Type for themselves. + # + pap + + # + # If "status_server = yes", then Status-Server messages are passed + # through the following section, and ONLY the following section. + # This permits you to do DB queries, for example. If the modules + # listed here return "fail", then NO response is sent. + # +# Autz-Type Status-Server { +# +# } + + # + # RADIUS/TLS (or RadSec) connections are processed through + # this section. See sites-available/tls, and the configuration + # item "check_client_connections" for more information. + # + # The request contains TLS client certificate attributes, + # and nothing else. The debug output will print which + # attributes are available on your system. + # + # If the section returns "ok" or "updated", then the + # connection is accepted. Otherwise the connection is + # terminated. + # + Autz-Type New-TLS-Connection { + ok + } +} + + +# Authentication. +# +# +# This section lists which modules are available for authentication. +# Note that it does NOT mean 'try each module in order'. It means +# that a module from the 'authorize' section adds a configuration +# attribute 'Auth-Type := FOO'. That authentication type is then +# used to pick the appropriate module from the list below. +# + +# In general, you SHOULD NOT set the Auth-Type attribute. The server +# will figure it out on its own, and will do the right thing. The +# most common side effect of erroneously setting the Auth-Type +# attribute is that one authentication method will work, but the +# others will not. +# +# The common reasons to set the Auth-Type attribute by hand +# is to either forcibly reject the user (Auth-Type := Reject), +# or to or forcibly accept the user (Auth-Type := Accept). +# +# Note that Auth-Type := Accept will NOT work with EAP. +# +# Please do not put "unlang" configurations into the "authenticate" +# section. Put them in the "post-auth" section instead. That's what +# the post-auth section is for. +# +authenticate { + # + # PAP authentication, when a back-end database listed + # in the 'authorize' section supplies a password. The + # password can be clear-text, or encrypted. + Auth-Type PAP { + pap + } + + # + # Most people want CHAP authentication + # A back-end database listed in the 'authorize' section + # MUST supply a CLEAR TEXT password. Encrypted passwords + # won't work. + Auth-Type CHAP { + chap + } + + # + # MSCHAP authentication. + Auth-Type MS-CHAP { + mschap + } + + # + # For old names, too. + # + mschap + + # + # If you have a Cisco SIP server authenticating against + # FreeRADIUS, uncomment the following line, and the 'digest' + # line in the 'authorize' section. + digest + + # + # Pluggable Authentication Modules. +# pam + + # Uncomment it if you want to use ldap for authentication + # + # Note that this means "check plain-text password against + # the ldap database", which means that EAP won't work, + # as it does not supply a plain-text password. + # + # We do NOT recommend using this. LDAP servers are databases. + # They are NOT authentication servers. FreeRADIUS is an + # authentication server, and knows what to do with authentication. + # LDAP servers do not. + # + # However, it is necessary for Active Directory, because + # Active Directory won't give the passwords to FreeRADIUS. + # +# Auth-Type LDAP { +# ldap +# } + + # + # Allow EAP authentication. + eap + + # + # The older configurations sent a number of attributes in + # Access-Challenge packets, which wasn't strictly correct. + # If you want to filter out these attributes, uncomment + # the following lines. + # +# Auth-Type eap { +# eap { +# handled = 1 +# } +# if (handled && (Response-Packet-Type == Access-Challenge)) { +# attr_filter.access_challenge.post-auth +# handled # override the "updated" code from attr_filter +# } +# } +} + + +# +# Pre-accounting. Decide which accounting type to use. +# +preacct { + preprocess + + # + # Merge Acct-[Input|Output]-Gigawords and Acct-[Input-Output]-Octets + # into a single 64bit counter Acct-[Input|Output]-Octets64. + # +# acct_counters64 + + # + # Session start times are *implied* in RADIUS. + # The NAS never sends a "start time". Instead, it sends + # a start packet, *possibly* with an Acct-Delay-Time. + # The server is supposed to conclude that the start time + # was "Acct-Delay-Time" seconds in the past. + # + # The code below creates an explicit start time, which can + # then be used in other modules. It will be *mostly* correct. + # Any errors are due to the 1-second resolution of RADIUS, + # and the possibility that the time on the NAS may be off. + # + # The start time is: NOW - delay - session_length + # + +# update request { +# &FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}" +# } + + + # + # Ensure that we have a semi-unique identifier for every + # request, and many NAS boxes are broken. + acct_unique + + # + # Look for IPASS-style 'realm/', and if not found, look for + # '@realm', and decide whether or not to proxy, based on + # that. + # + # Accounting requests are generally proxied to the same + # home server as authentication requests. +# IPASS + suffix +# ntdomain + + # + # Read the 'acct_users' file + files +} + +# +# Accounting. Log the accounting data. +# +accounting { + # Update accounting packet by adding the CUI attribute + # recorded from the corresponding Access-Accept + # use it only if your NAS boxes do not support CUI themselves +# cui + # + # Create a 'detail'ed log of the packets. + # Note that accounting requests which are proxied + # are also logged in the detail file. + detail +# daily + + # Update the wtmp file + # + # If you don't use "radlast", you can delete this line. + unix + + # + # For Simultaneous-Use tracking. + # + # Due to packet losses in the network, the data here + # may be incorrect. There is little we can do about it. +# radutmp +# sradutmp + + # + # Return an address to the IP Pool when we see a stop record. + # + # Ensure that &control:Pool-Name is set to determine which + # pool of IPs are used. +# sqlippool + + # + # Log traffic to an SQL database. + # + # See "Accounting queries" in mods-available/sql + -sql + + # + # If you receive stop packets with zero session length, + # they will NOT be logged in the database. The SQL module + # will print a message (only in debugging mode), and will + # return "noop". + # + # You can ignore these packets by uncommenting the following + # three lines. Otherwise, the server will not respond to the + # accounting request, and the NAS will retransmit. + # +# if (noop) { +# ok +# } + + # Cisco VoIP specific bulk accounting +# pgsql-voip + + # For Exec-Program and Exec-Program-Wait + exec + + # Filter attributes from the accounting response. + attr_filter.accounting_response + + # + # See "Autz-Type Status-Server" for how this works. + # +# Acct-Type Status-Server { +# +# } +} + + +# Session database, used for checking Simultaneous-Use. Either the radutmp +# or rlm_sql module can handle this. +# The rlm_sql module is *much* faster +session { +# radutmp + + # + # See "Simultaneous Use Checking Queries" in mods-available/sql +# sql +} + + +# Post-Authentication +# Once we KNOW that the user has been authenticated, there are +# additional steps we can take. +post-auth { + # + # If you need to have a State attribute, you can + # add it here. e.g. for later CoA-Request with + # State, and Service-Type = Authorize-Only. + # +# if (!&reply:State) { +# update reply { +# State := "0x%{randstr:16h}" +# } +# } + + # + # Reject packets where User-Name != TLS-Client-Cert-Common-Name + # There is no reason for users to lie about their names. + # + # In general, User-Name == EAP Identity == TLS-Client-Cert-Common-Name + # +# verify_tls_client_common_name + + # + # If there is no Stripped-User-Name in the request, AND we have a client cert, + # then create a Stripped-User-Name from the TLS client certificate information. + # + # Note that this policy MUST be edited for your local system! + # We do not know which fields exist in which certificate, as + # there is no standard here. There is no way for us to have + # a default configuration which "just works" everywhere. We + # can only make recommendations. + # + # The Stripped-User-Name is updated so that it is logged in + # the various "username" fields. This logging means that you + # can associate a particular session with a particular client + # certificate. + # +# if (&EAP-Message && !&Stripped-User-Name && &TLS-Client-Cert-Serial) { +# update request { +# &Stripped-User-Name := "%{%{TLS-Client-Cert-Subject-Alt-Name-Email}:-%{%{TLS-Client-Cert-Common-Name}:-%{TLS-Client-Cert-Serial}}}" +# } +# + # + # Create a Class attribute which is a hash of a bunch + # of information which we hope exists. This + # attribute should be echoed back in + # Accounting-Request packets, which will let the + # administrator correlate authentication and + # accounting. + # +# update reply { +# Class += "%{md5:%{Calling-Station-Id}%{Called-Station-Id}%{TLS-Client-Cert-Subject-Alt-Name-Email}%{TLS-Client-Cert-Common-Name}%{TLS-Client-Cert-Serial}%{NAS-IPv6-Address}%{NAS-IP-Address}%{NAS-Identifier}%{NAS-Port}" +# } +# +# } + + # + # For EAP-TTLS and PEAP, add the cached attributes to the reply. + # The "session-state" attributes are automatically cached when + # an Access-Challenge is sent, and automatically retrieved + # when an Access-Request is received. + # + # The session-state attributes are automatically deleted after + # an Access-Reject or Access-Accept is sent. + # + # If both session-state and reply contain a User-Name attribute, remove + # the one in the reply if it is just a copy of the one in the request, so + # we don't end up with two User-Name attributes. + + if (session-state:User-Name && reply:User-Name && request:User-Name && (reply:User-Name == request:User-Name)) { + update reply { + &User-Name !* ANY + } + } + update { + &reply: += &session-state: + } + + # + # Refresh leases when we see a start or alive. Return an address to + # the IP Pool when we see a stop record. + # + # Ensure that &control:Pool-Name is set to determine which + # pool of IPs are used. +# sqlippool + + + # Create the CUI value and add the attribute to Access-Accept. + # Uncomment the line below if *returning* the CUI. +# cui + + # Create empty accounting session to make simultaneous check + # more robust. See the accounting queries configuration in + # raddb/mods-config/sql/main/*/queries.conf for details. + # + # The "sql_session_start" policy is defined in + # raddb/policy.d/accounting. See that file for more details. +# sql_session_start + + # + # If you want to have a log of authentication replies, + # un-comment the following line, and enable the + # 'detail reply_log' module. +# reply_log + + # + # After authenticating the user, do another SQL query. + # + # See "Authentication Logging Queries" in mods-available/sql + -sql + + # + # Un-comment the following if you want to modify the user's object + # in LDAP after a successful login. + # +# ldap + + # For Exec-Program and Exec-Program-Wait + exec + + # + # In order to calcualate the various keys for old style WiMAX + # (non LTE) you will need to define the WiMAX NAI, usually via + # + # update request { + # &WiMAX-MN-NAI = "%{User-Name}" + # } + # + # If you want various keys to be calculated, you will need to + # update the reply with "template" values. The module will see + # this, and replace the template values with the correct ones + # taken from the cryptographic calculations. e.g. + # + # update reply { + # &WiMAX-FA-RK-Key = 0x00 + # &WiMAX-MSK = "%{reply:EAP-MSK}" + # } + # + # You may want to delete the MS-MPPE-*-Keys from the reply, + # as some WiMAX clients behave badly when those attributes + # are included. See "raddb/modules/wimax", configuration + # entry "delete_mppe_keys" for more information. + # + # For LTE style WiMAX you need to populate the following with the + # relevant values: + # control:WiMAX-SIM-Ki + # control:WiMAX-SIM-OPc + # control:WiMAX-SIM-AMF + # control:WiMAX-SIM-SQN + # +# wimax + + # If there is a client certificate (EAP-TLS, sometimes PEAP + # and TTLS), then some attributes are filled out after the + # certificate verification has been performed. These fields + # MAY be available during the authentication, or they may be + # available only in the "post-auth" section. + # + # The first set of attributes contains information about the + # issuing certificate which is being used. The second + # contains information about the client certificate (if + # available). +# +# update reply { +# Reply-Message += "%{TLS-Cert-Serial}" +# Reply-Message += "%{TLS-Cert-Expiration}" +# Reply-Message += "%{TLS-Cert-Subject}" +# Reply-Message += "%{TLS-Cert-Issuer}" +# Reply-Message += "%{TLS-Cert-Common-Name}" +# Reply-Message += "%{TLS-Cert-Subject-Alt-Name-Email}" +# +# Reply-Message += "%{TLS-Client-Cert-Serial}" +# Reply-Message += "%{TLS-Client-Cert-Expiration}" +# Reply-Message += "%{TLS-Client-Cert-Subject}" +# Reply-Message += "%{TLS-Client-Cert-Issuer}" +# Reply-Message += "%{TLS-Client-Cert-Common-Name}" +# Reply-Message += "%{TLS-Client-Cert-Subject-Alt-Name-Email}" +# } + + # Insert class attribute (with unique value) into response, + # aids matching auth and acct records, and protects against duplicate + # Acct-Session-Id. Note: Only works if the NAS has implemented + # RFC 2865 behaviour for the class attribute, AND if the NAS + # supports long Class attributes. Many older or cheap NASes + # only support 16-octet Class attributes. +# insert_acct_class + + # MacSEC requires the use of EAP-Key-Name. However, we don't + # want to send it for all EAP sessions. Therefore, the EAP + # modules put required data into the EAP-Session-Id attribute. + # This attribute is never put into a request or reply packet. + # + # Uncomment the next few lines to copy the required data into + # the EAP-Key-Name attribute +# if (&reply:EAP-Session-Id) { +# update reply { +# EAP-Key-Name := &reply:EAP-Session-Id +# } +# } + + # Remove reply message if the response contains an EAP-Message + remove_reply_message_if_eap + + # + # Access-Reject packets are sent through the REJECT sub-section of the + # post-auth section. + # + # Add the ldap module name (or instance) if you have set + # 'edir = yes' in the ldap module configuration + # + # The "session-state" attributes are not available here. + # + Post-Auth-Type REJECT { + # log failed authentications in SQL, too. + -sql + attr_filter.access_reject + + # Insert EAP-Failure message if the request was + # rejected by policy instead of because of an + # authentication failure + eap + + # Remove reply message if the response contains an EAP-Message + remove_reply_message_if_eap + } + + # + # Filter access challenges. + # + Post-Auth-Type Challenge { +# remove_reply_message_if_eap +# attr_filter.access_challenge.post-auth + } + + # + # The Client-Lost section will be run for a request when + # FreeRADIUS has given up waiting for an end-users client to + # respond. This is most useful for logging EAP sessions where + # the client stopped responding (likely because the + # certificate was not acceptable.) i.e. this is not for + # RADIUS clients, but for end-user systems. + # + # This will only be triggered by new packets arriving, + # and will be run at some point in the future *after* the + # original request has been discarded. + # + # Therefore the *ONLY* attributes that are available here + # are those in the session-state list. If you want data + # to log, make sure it is copied to &session-state: + # before the client stops responding. NONE of the other + # original attributes (request, reply, etc) will be + # available. + # + # This section will only be run if `postauth_client_lost` + # is enabled in the main configuration in `radiusd.conf`. + # + # Note that there are MANY reasons why an end users system + # might not respond: + # + # * it could not get the packet due to firewall issues + # * it could not get the packet due to a lossy network + # * the users system might not like the servers cert + # * the users system might not like something else... + # + # In some cases, the client is helpful enough to send us a + # TLS Alert message, saying what it doesn't like about the + # certificate. In other cases, no such message is available. + # + # All that we can know on the FreeRADIUS side is that we sent + # an Access-Challenge, and the client never sent anything + # else. The reasons WHY this happens are buried inside of + # the logs on the client system. No amount of looking at the + # FreeRADIUS logs, or poking the FreeRADIUS configuration + # will tell you why the client gave up. The answers are in + # the logs on the client side. And no, the FreeRADIUS team + # didn't write the client, so we don't know where those logs + # are, or how to get at them. + # + # Information about the TLS state changes is in the + # &session-state:TLS-Session-Information attribute. + # + Post-Auth-Type Client-Lost { + # + # Debug ALL of the TLS state changes done during the + # EAP negotiation. + # +# %{debug_attr:&session-state:TLS-Session-Information[*]} + + # + # Debug the LAST TLS state change done during the EAP + # negotiation. For errors, this is usually a TLS + # alert from the client saying something like + # "unknown CA". + # +# %{debug_attr:&session-state:TLS-Session-Information[n]} + + # + # Debug the last module failure message. This may be + # useful, or it may refer to a server-side failure + # which did not cause the client to stop talking to the server. + # +# %{debug_attr:&session-state:Module-Failure-Message} + } + + # + # If the client sends EAP-Key-Name in the request, + # then echo the real value back in the reply. + # + if (EAP-Key-Name && &reply:EAP-Session-Id) { + update reply { + &EAP-Key-Name := &reply:EAP-Session-Id + } + } +} + +# +# When the server decides to proxy a request to a home server, +# the proxied request is first passed through the pre-proxy +# stage. This stage can re-write the request, or decide to +# cancel the proxy. +# +# Only a few modules currently have this method. +# +pre-proxy { + # Before proxing the request add an Operator-Name attribute identifying + # if the operator-name is found for this client. + # No need to uncomment this if you have already enabled this in + # the authorize section. +# operator-name + + # The client requests the CUI by sending a CUI attribute + # containing one zero byte. + # Uncomment the line below if *requesting* the CUI. +# cui + + # Uncomment the following line if you want to change attributes + # as defined in the preproxy_users file. +# files + + # Uncomment the following line if you want to filter requests + # sent to remote servers based on the rules defined in the + # 'attrs.pre-proxy' file. +# attr_filter.pre-proxy + + # If you want to have a log of packets proxied to a home + # server, un-comment the following line, and the + # 'detail pre_proxy_log' section, above. +# pre_proxy_log +} + +# +# When the server receives a reply to a request it proxied +# to a home server, the request may be massaged here, in the +# post-proxy stage. +# +post-proxy { + + # If you want to have a log of replies from a home server, + # un-comment the following line, and the 'detail post_proxy_log' + # section, above. +# post_proxy_log + + # Uncomment the following line if you want to filter replies from + # remote proxies based on the rules defined in the 'attrs' file. +# attr_filter.post-proxy + + # + # If you are proxying LEAP, you MUST configure the EAP + # module, and you MUST list it here, in the post-proxy + # stage. + # + # You MUST also use the 'nostrip' option in the 'realm' + # configuration. Otherwise, the User-Name attribute + # in the proxied request will not match the user name + # hidden inside of the EAP packet, and the end server will + # reject the EAP request. + # + eap + + # + # If the server tries to proxy a request and fails, then the + # request is processed through the modules in this section. + # + # The main use of this section is to permit robust proxying + # of accounting packets. The server can be configured to + # proxy accounting packets as part of normal processing. + # Then, if the home server goes down, accounting packets can + # be logged to a local "detail" file, for processing with + # radrelay. When the home server comes back up, radrelay + # will read the detail file, and send the packets to the + # home server. + # + # See the "mods-available/detail.example.com" file for more + # details on writing a detail file specifically for one + # destination. + # + # See the "sites-available/robust-proxy-accounting" virtual + # server for more details on reading this "detail" file. + # + # With this configuration, the server always responds to + # Accounting-Requests from the NAS, but only writes + # accounting packets to disk if the home server is down. + # +# Post-Proxy-Type Fail-Accounting { +# detail.example.com +# } +} +} diff --git a/raddb/sites-available/dhcp b/raddb/sites-available/dhcp new file mode 100644 index 0000000..4f5ed51 --- /dev/null +++ b/raddb/sites-available/dhcp @@ -0,0 +1,584 @@ +# -*- text -*- +###################################################################### +# +# This is a virtual server that handles DHCP. +# +# See raddb/mods-available/dhcp_sqlippool for the IP Pool configuration. +# +# See raddb/policy.d/dhcp_sqlippool for the "glue" code that allows +# the RADIUS based "sqlippool" module to be used for DHCP. +# +# See raddb/mods-config/sql/ippool/ for the schemas. +# +# See raddb/sites-available/dhcp for instructions on how to configure +# the DHCP server. +# +# $Id$ +# +###################################################################### + +# +# The DHCP functionality goes into a virtual server. +# +server dhcp { + +# Define a DHCP socket. +# +# The default port below is 6700, so you don't break your network. +# If you want it to do real DHCP, change this to 67, and good luck! +# +# You can also bind the DHCP socket to an interface. +# See below, and raddb/radiusd.conf for examples. +# +# This lets you run *one* DHCP server instance and have it listen on +# multiple interfaces, each with a separate policy. +# +# If you have multiple interfaces, it is a good idea to bind the +# listen section to an interface. You will also need one listen +# section per interface. +# +# FreeBSD does *not* support binding sockets to interfaces. Therefore, +# if you have multiple interfaces, broadcasts may go out of the wrong +# one, or even all interfaces. The solution is to use the "setfib" command. +# If you have a network "10.10.0/24" on LAN1, you will need to do: +# +# Pick any IP on the 10.10.0/24 network +# $ setfib 1 route add default 10.10.0.1 +# +# Edit /etc/rc.local, and add a line: +# setfib 1 /path/to/radiusd +# +# The kern must be built with the following options: +# options ROUTETABLES=2 +# or any value larger than 2. +# +# The other only solution is to update FreeRADIUS to use BPF sockets. +# +listen { + # This is a dhcp socket. + type = dhcp + + # IP address to listen on. Will usually be the IP of the + # interface, or 0.0.0.0 + ipaddr = 127.0.0.1 + + # source IP address for unicast packets sent by the + # DHCP server. + # + # The source IP for unicast packets is chosen from the first + # one of the following items which returns a valid IP + # address: + # + # src_ipaddr + # ipaddr + # reply:DHCP-Server-IP-Address + # reply:DHCP-DHCP-Server-Identifier + # + src_ipaddr = 127.0.0.1 + + # The port should be 67 for a production network. Don't set + # it to 67 on a production network unless you really know + # what you're doing. Even if nothing is configured below, the + # server may still NAK legitimate responses from clients. + port = 6700 + + # Interface name we are listening on. See comments above. +# interface = lo0 + + # The DHCP server defaults to allowing broadcast packets. + # Set this to "no" only when the server receives *all* packets + # from a relay agent. i.e. when *no* clients are on the same + # LAN as the DHCP server. + # + # It's set to "no" here for testing. It will usually want to + # be "yes" in production, unless you are only dealing with + # relayed packets. + broadcast = no + + # On Linux if you're running the server as non-root, you + # will need to do: + # + # sudo setcap cap_net_admin=ei /path/to/radiusd + # + # This will allow the server to set ARP table entries + # for newly allocated IPs + + # De-duplicate DHCP packets. If clients don't receive + # a reply within their timeout, most will re-transmit. + # A reply to either packet will satisfy, so de-duplicating + # helps manage load on a busy server + performance { + skip_duplicate_checks = no + } +} + +# Packets received on the socket will be processed through one +# of the following sections, named after the DHCP packet type. +# See dictionary.dhcp for the packet types. + +# Return packets will be sent to, in preference order: +# DHCP-Gateway-IP-Address +# DHCP-Client-IP-Address +# DHCP-Your-IP-Address +# At least one of these attributes should be set at the end of each +# section for a response to be sent. + +# An internal attribute of DHCP-Network-Subnet is set to provide +# a basis for determining the network that a client belongs to. This +# is a hierarchical assignment based on: +# +# - DHCP-Relay-Link-Selection +# - DHCP-Subnet-Selection-Option +# - DHCP-Gateway-IP-Address +# - DHCP-Client-IP-Address +# +# Except for cases where all IP allocation is performed using a mapping from +# the device MAC address to a fixed IP address the DHCP configuration will +# involve the use of one or more pools. +# +# Each pool should be composed of a set of equally valid IP addresses for the +# devices designated as users of the pool. During IP allocation the choice of +# pool is driven by setting the Pool-Name attribute which may either be +# specified directly or chosen (usually with the help of the dhcp_network +# module) based on the initial value of DHCP-Network-Subnet. +# +# DHCP-Network-Subnet indicates the network from which the request is +# originating. In cases where the originating network alone is insufficent to +# define the required IP allocated policy, DHCP-Network-Subnet may be +# overridden to force the selection of a particular pool. +# +# IP addresses belonging to a single pool that is designated for a Layer 2 +# network containing multiple subnets (a "shared-network" or "multinet" +# configuration as defined by some other DHCP servers), will by definition be +# members of distinct subnets that require their own DHCP reply parameters. In +# this case the dhcp_subnet policy can be used to set the correct +# DHCP-Subnet-Mask, DHCP-Router-Address and DHCP-Broadcast-Address options +# based on the allocated IP. + +dhcp DHCP-Discover { + + # The DHCP Server Identifier is set here since is returned in OFFERs + update control { + &DHCP-DHCP-Server-Identifier = 192.0.2.2 + } + + # Call a policy (defined in policy.d/dhcp) to set common reply attributes + dhcp_common + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # If clients need to be assigned to a particular network based on + # an attribute in the packet rather than the calculated + # DHCP-Network-Subnet described above, then call a policy + # (defined in policy.d/dhcp) to perform the override + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple subnets use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Do a simple mapping of MAC to assigned IP. + # + # See below for the definition of the "mac2ip" + # module. + # + #mac2ip + + # Or, allocate IPs from the DHCP pool in SQL. You may need to + # set the pool name here if you haven't set it elsewhere. + #update control { + # &Pool-Name := "local" + #} + #dhcp_sqlippool + + # If the IP address was not allocated, do something else. + # You could call a Perl, Python, or Java script here. + #if (notfound) { + # ... + #} + + # "Shared-networks" may have multiple IP subnets co-existing in a + # single Layer 2 network. If the pool for the network contains + # addresses from more that one subnet then the setting subnet-specific + # DHCP-Subnet-Mask, DHCP-Router-Address and DHCP-Broadcast-Address + # parameters must be performed after the allocation of the IP address. + # + # Set any subnet-specific parameters using this policy. + # + # Enable mods-available/dhcp_files AND uncomment dhcp_subnet in + # policy.d/dhcp to use this. + # + #dhcp_subnet + + # Use a "files" module to lookup options based on DHCP-Group-Name + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_group_options + + # Use a "files" module to lookup host specific options + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_hosts + + # As an alternative or complement to configuration files based lookup + # for options data you can instead use an SQL database. Example + # configuration is found in dhcp_policy_sql in policy.d/dhcp which + # will need to be adapted to your requirements. + #dhcp_policy_sql + + # Set the type of packet to send in reply. + # + # The server will look at the DHCP-Message-Type attribute to + # determine which type of packet to send in reply. Common + # values would be DHCP-Offer, DHCP-Ack or DHCP-NAK. See + # dictionary.dhcp for all the possible values. + # + # DHCP-Do-Not-Respond can be used to tell the server to not + # respond. + # + # In the event that DHCP-Message-Type is not set then the + # server will fall back to determining the type of reply + # based on the rcode of this section. + # + #update reply { + # DHCP-Message-Type = DHCP-Offer + #} + # + # If DHCP-Message-Type is not set, returning "ok" or + # "updated" from this section will respond with a DHCP-Offer + # message. + # + # Other rcodes will tell the server to not return any response. + # + #ok +} + +dhcp DHCP-Request { + + # You must set the DHCP Server Identifier here since this is returned + # in ACKs and is used to determine whether a request containing a + # "server-ip" field is intended for this server + update control { + &DHCP-DHCP-Server-Identifier = 192.0.2.2 + } + + # If the request is not for this server then silently discard it + if (&request:DHCP-DHCP-Server-Identifier && \ + &request:DHCP-DHCP-Server-Identifier != &control:DHCP-DHCP-Server-Identifier) { + do_not_respond + } + + # Response packet type. See DHCP-Discover section above. + #update reply { + # &DHCP-Message-Type = DHCP-Ack + #} + + # Call a policy (defined in policy.d/dhcp) to set common reply attributes + dhcp_common + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple subnets use this in place of dhcp_common + # Enable mods-available/dhcp_files AND uncomment dhcp_subnet in + # policy.d/dhcp to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Do a simple mapping of MAC to assigned IP. + # + # See below for the definition of the "mac2ip" + # module. + # + #mac2ip + + # Or, allocate IPs from the DHCP pool in SQL. You may need to + # set the pool name here if you haven't set it elsewhere. +# update control { +# &Pool-Name := "local" +# } +# dhcp_sqlippool_request + + # If the IP was not allocated, do something else. + # You could call a Perl, Python, or Java script here. + #if (notfound) { + # ... + #} + + # "Shared-networks" may have multiple IP subnets co-existing in a + # single Layer 2 network. If the pool for the network contains + # addresses from more that one subnet then the setting subnet-specific + # DHCP-Subnet-Mask, DHCP-Router-Address and DHCP-Broadcast-Address + # parameters must be performed after the allocation of the IP address. + # + # Set any subnet-specific parameters using this policy. + # + #dhcp_subnet + + # Use a "files" module to lookup options based on DHCP-Group-Name + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_group_options + + # Use a "files" module to lookup host specific options + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_hosts + + # As an alternative or complement to configuration files based lookup + # for options data you can instead use an SQL database. Example + # configuration is found in dhcp_policy_sql in policy.d/dhcp which + # will need to be adapted to your requirements. + #dhcp_policy_sql + + # If DHCP-Message-Type is not set, returning "ok" or + # "updated" from this section will respond with a DHCP-Ack + # packet. + # + # "handled" will not return a packet, all other rcodes will + # send back a DHCP-NAK. + # + #ok +} + +# +# Other DHCP packet types +# +# There should be a separate section for each DHCP message type. +# By default this configuration will ignore them all. Any packet type +# not defined here will be responded to with a DHCP-NAK. + +dhcp DHCP-Decline { + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple networks use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Use a policy that set options from data stored in an SQL database + #dhcp_policy_sql + + # If using IPs from a DHCP pool in SQL then you may need to set the + # pool name here if you haven't set it elsewhere and release the IP. +# update control { +# &Pool-Name := "local" +# } +# dhcp_sqlippool_decline + + update reply { + &DHCP-Message-Type = DHCP-Do-Not-Respond + } + reject +} + +# +# A dummy config for Inform packets - this should match the +# options set in the Request section above, except Inform replies +# must not set Your-IP-Address or IP-Address-Lease-Time +# +dhcp DHCP-Inform { + # Call a policy (defined in policy.d/dhcp) to set common reply attributes + dhcp_common + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and network options + # For multiple networks use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Use a policy with calls a "files" module of the same name to lookup + # subnet options + # Enable mods-available/dhcp_files AND uncomment dhcp_subnet in + # policy.d/dhcp to use this + # Options are set in mods-config/files/dhcp + #dhcp_subnet + + # Use a "files" module to lookup options based on DHCP-Group-Name + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_group_options + + # Use a "files" module to lookup host specific options + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_hosts + + # Use a policy that set options from data stored in an SQL database + #dhcp_policy_sql + + ok +} + +# +# For Windows 7 boxes +# +#dhcp DHCP-Inform { +# update reply { +# Packet-Dst-Port = 67 +# DHCP-Message-Type = DHCP-ACK +# DHCP-DHCP-Server-Identifier = "%{Packet-Dst-IP-Address}" +# DHCP-Site-specific-28 = 0x0a00 +# } +# ok +#} + +dhcp DHCP-Release { + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple subnets use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # If using IPs from a DHCP pool in SQL then you may need to set the + # pool name here if you haven't set it elsewhere and release the IP. +# update control { +# &Pool-Name := "local" +# } +# dhcp_sqlippool_release + + update reply { + &DHCP-Message-Type = DHCP-Do-Not-Respond + } + reject +} + + +dhcp DHCP-Lease-Query { + # The thing being queried for is implicit + # in the packets. + + # has MAC, asking for IP, etc. + if (&DHCP-Client-Hardware-Address) { + # look up MAC in database + } + + # has IP, asking for MAC, etc. + elsif (&DHCP-Your-IP-Address) { + # look up IP in database + } + + # has host name, asking for IP, MAC, etc. + elsif (&DHCP-Client-Identifier) { + # look up identifier in database + } + else { + update reply { + &DHCP-Message-Type = DHCP-Lease-Unknown + } + + ok + + # stop processing + return + } + + # + # We presume that the database lookup returns "notfound" + # if it can't find anything. + # + if (notfound) { + update reply { + &DHCP-Message-Type = DHCP-Lease-Unknown + } + ok + return + } + + # + # Add more logic here. Is the lease inactive? + # If so, respond with DHCP-Lease-Unassigned. + # + # Otherwise, respond with DHCP-Lease-Active + # + + # + # Also be sure to return ALL information about + # the lease. + # + + # + # The reply types are: + # + # DHCP-Lease-Unknown + # DHCP-Lease-Active + # DHCP-Lease-Unassigned + # + update reply { + &DHCP-Message-Type = DHCP-Lease-Unassigned + } + +} + +} + +###################################################################### +# +# This next section is a sample configuration for the "passwd" +# module, that reads flat-text files. It should go into +# radiusd.conf, in the "modules" section. +# +# The file is in the format <mac>,<ip> +# +# 00:01:02:03:04:05,192.0.2.100 +# 01:01:02:03:04:05,192.0.2.101 +# 02:01:02:03:04:05,192.0.2.102 +# +# This lets you perform simple static IP assignment. +# +# There is a preconfigured "mac2ip" module setup in +# mods-available/mac2ip. To use it do: +# +# # cd raddb/ +# # ln -s ../mods-available/mac2ip mods-enabled/mac2ip +# # mkdir mods-config/passwd +# +# Then create the file mods-config/passwd/mac2ip with the above +# format. +# +###################################################################### + + +# This is an example only - see mods-available/mac2ip instead; do +# not uncomment these lines here. +# +#passwd mac2ip { +# filename = ${confdir}/mac2ip +# format = "*DHCP-Client-Hardware-Address:=DHCP-Your-IP-Address" +# delimiter = "," +#} diff --git a/raddb/sites-available/dhcp.relay b/raddb/sites-available/dhcp.relay new file mode 100644 index 0000000..76d1e10 --- /dev/null +++ b/raddb/sites-available/dhcp.relay @@ -0,0 +1,44 @@ +# -*- text -*- +###################################################################### +# +# This is a virtual server that handles DHCP relaying +# +# Only one server can listen on a socket, so you cannot +# do DHCP relaying && run a DHCP server at the same time. +# +###################################################################### + +server dhcp.eth1 { + listen { + ipaddr = * + port = 67 + type = dhcp + interface = eth1 + } + + # Packets received on the socket will be processed through one + # of the following sections, named after the DHCP packet type. + # See dictionary.dhcp for the packet types. + dhcp DHCP-Discover { + update config { + # IP Address of the DHCP server + &DHCP-Relay-To-IP-Address := 192.0.2.2 + } + update request { + # IP Address of the DHCP relay (ourselves) + &DHCP-Gateway-IP-Address := 192.0.2.1 + } + ok + } + + dhcp DHCP-Request { + update config { + # IP Address of the DHCP server + &DHCP-Relay-To-IP-Address := 192.0.2.2 + } + update request { + &DHCP-Gateway-IP-Address := 192.0.2.2 + } + ok + } +} diff --git a/raddb/sites-available/dynamic-clients b/raddb/sites-available/dynamic-clients new file mode 100644 index 0000000..0459a7f --- /dev/null +++ b/raddb/sites-available/dynamic-clients @@ -0,0 +1,222 @@ +# -*- text -*- +###################################################################### +# +# Sample configuration file for dynamically updating the list +# of RADIUS clients at run time. +# +# Everything is keyed off of a client "network". (e.g. 192.0.2/24) +# This configuration lets the server know that clients within +# that network are defined dynamically. +# +# When the server receives a packet from an unknown IP address +# within that network, it tries to find a dynamic definition +# for that client. If the definition is found, the IP address +# (and other configuration) is added to the server's internal +# cache of "known clients", with a configurable lifetime. +# +# Further packets from that IP address result in the client +# definition being found in the cache. Once the lifetime is +# reached, the client definition is deleted, and any new requests +# from that client are looked up as above. +# +# If the dynamic definition is not found, then the request is +# treated as if it came from an unknown client. i.e. It is +# silently discarded. +# +# As part of protection from Denial of Service (DoS) attacks, +# the server will add only one new client per second. This CANNOT +# be changed, and is NOT configurable. +# +# $Id$ +# +###################################################################### + +# +# Define a network where clients may be dynamically defined. +client dynamic { + # + # You MUST specify a netmask! + # IPv4 /32 or IPv6 /128 are NOT allowed! + ipaddr = 192.0.2.0/24 + + # + # Any other configuration normally found in a "client" + # entry can be used here. + + # + # A shared secret does NOT have to be defined. It can + # be left out. + + # + # Define the virtual server used to discover dynamic clients. + dynamic_clients = dynamic_clients + + # + # The directory where client definitions are stored. This + # needs to be used ONLY if the client definitions are stored + # in flat-text files. Each file in that directory should be + # ONE and only one client definition. The name of the file + # should be the IP address of the client. + # + # If you are storing clients in SQL, this entry should not + # be used. +# directory = ${confdir}/dynamic-clients/ + + # + # Define the lifetime (in seconds) for dynamic clients. + # They will be cached for this lifetime, and deleted afterwards. + # + # If the lifetime is "0", then the dynamic client is never + # deleted. The only way to delete the client is to re-start + # the server. + lifetime = 3600 +} + +# +# This is the virtual server referenced above by "dynamic_clients". +server dynamic_clients { + + # + # The only contents of the virtual server is the "authorize" section. + authorize { + + # + # Put any modules you want here. SQL, LDAP, "exec", + # Perl, etc. The only requirements is that the + # attributes MUST go into the control item list. + # + # The request that is processed through this section + # is EMPTY. There are NO attributes. The request is fake, + # and is NOT the packet that triggered the lookup of + # the dynamic client. + # + # The ONLY piece of useful information is either + # + # Packet-Src-IP-Address (IPv4 clients) + # Packet-Src-IPv6-Address (IPv6 clients) + # + # The attributes used to define a dynamic client mirror + # the configuration items in the "client" structure. + # + + # + # Example 1: Hard-code a client IP. This example is + # useless, but it documents the attributes + # you need. + # + update control { + + # + # Echo the IP address of the client. + &FreeRADIUS-Client-IP-Address = "%{Packet-Src-IP-Address}" + + # require_message_authenticator + &FreeRADIUS-Client-Require-MA = no + + # secret + &FreeRADIUS-Client-Secret = "testing123" + + # shortname + &FreeRADIUS-Client-Shortname = "%{Packet-Src-IP-Address}" + + # nas_type + &FreeRADIUS-Client-NAS-Type = "other" + + # virtual_server + # + # This can ONLY be used if the network client + # definition (e.g. "client dynamic" above) has + # NO virtual_server defined. + # + # If the network client definition does have a + # virtual_server defined, then that is used, + # and there is no need to define this attribute. + # + &FreeRADIUS-Client-Virtual-Server = "something" + + } + + # + # Example 2: Read the clients from "clients" files + # in a directory. + # + + # This requires you to uncomment the + # "directory" configuration in the + # "client dynamic" configuration above, + # and then put one file per IP address in + # that directory. + # + dynamic_clients + + # + # Example 3: Look the clients up in SQL. + # + # This requires the SQL module to be configured, of course. + if ("%{sql: SELECT nasname FROM nas WHERE nasname = '%{Packet-Src-IP-Address}'}") { + update control { + # + # Echo the IP. + &FreeRADIUS-Client-IP-Address = "%{Packet-Src-IP-Address}" + + # + # Do multiple SELECT statements to grab + # the various definitions. + &FreeRADIUS-Client-Shortname = "%{sql: SELECT shortname FROM nas WHERE nasname = '%{Packet-Src-IP-Address}'}" + + &FreeRADIUS-Client-Secret = "%{sql: SELECT secret FROM nas WHERE nasname = '%{Packet-Src-IP-Address}'}" + + &FreeRADIUS-Client-NAS-Type = "%{sql: SELECT type FROM nas WHERE nasname = '%{Packet-Src-IP-Address}'}" + + &FreeRADIUS-Client-Virtual-Server = "%{sql: SELECT server FROM nas WHERE nasname = '%{Packet-Src-IP-Address}'}" + } + + } + + # Do an LDAP lookup in the elements OU, check to see if + # the Packet-Src-IP-Address object has a "ou" + # attribute, if it does continue. Change "ACME.COM" to + # the real OU of your organization. + # + # Assuming the following schema: + # + # OU=Elements,OU=Radius,DC=ACME,DC=COM + # + # Elements will hold a record of every NAS in your + # Network. Create Group objects based on the IP + # Address of the NAS and set the "Location" or "l" + # attribute to the NAS Huntgroup the NAS belongs to + # allow them to be centrally managed in LDAP. + # + # e.g. CN=10.1.2.3,OU=Elements,OU=Radius,DC=ACME,DC=COM + # + # With a "l" value of "CiscoRTR" for a Cisco Router + # that has a NAS-IP-Address or Source-IP-Address of + # 10.1.2.3. + # + # And with a "ou" value of the shared secret password + # for the NAS element. ie "password" + if ("%{ldap:ldap:///OU=Elements,OU=Radius,DC=ACME,DC=COM?ou?sub?cn=%{Packet-Src-IP-Address}}") { + update control { + &FreeRADIUS-Client-IP-Address = "%{Packet-Src-IP-Address}" + + # Set the Client-Shortname to be the Location + # "l" just like in the Huntgroups, but this + # time to the shortname. + + &FreeRADIUS-Client-Shortname = "%{ldap:ldap:///OU=Elements,OU=Radius,DC=ACME,DC=COM?l?sub?cn=%{Packet-Src-IP-Address}}" + + # Lookup and set the Shared Secret based on + # the "ou" attribute. + &FreeRADIUS-Client-Secret = "%{ldap:ldap:///OU=Elements,OU=Radius,DC=ACME,DC=COM?ou?sub?cn=%{Packet-Src-IP-Address}}" + } + } + + # + # Tell the caller that the client was defined properly. + # + # If the authorize section does NOT return "ok", then + # the new client is ignored. + ok + } +} diff --git a/raddb/sites-available/example b/raddb/sites-available/example new file mode 100644 index 0000000..5f204aa --- /dev/null +++ b/raddb/sites-available/example @@ -0,0 +1,122 @@ +###################################################################### +# +# An example virtual server configuration. +# +# $Id$ +# +###################################################################### + + +# +# This client will be available to any "listen" section that +# are defined outside of a virtual server section. However, +# when the server receives a packet from this client, the +# request will be processed through the "example" virtual +# server, as the "client" section contains a configuration item +# to that effect. +# +# Note that this client will be able to send requests to any +# port defined in a global "listen" section. It will NOT, +# however, be able to send requests to a port defined in a +# "listen" section that is contained in a "server" section. +# +# With careful matching of configurations, you should be able +# to: +# +# - Define one authentication port, but process each client +# through a separate virtual server. +# +# - define multiple authentication ports, each with a private +# list of clients. +# +# - define multiple authentication ports, each of which may +# have the same client listed, but with different shared +# secrets +# +# FYI: We use an address in the 192.0.2.* space for this example, +# as RFC 3330 says that that /24 range is used for documentation +# and examples, and should not appear on the net. You shouldn't +# use it for anything, either. +# +client 192.0.2.10 { + shortname = example-client + secret = testing123 + virtual_server = example +} + +###################################################################### +# +# An example virtual server. It starts off with "server name {" +# The "name" is used to reference this server from a "listen" +# or "client" section. +# +###################################################################### +server example { + # + # Listen on 192.0.2.1:1812 for Access-Requests + # + # When the server receives a packet, it is processed + # through the "authorize", etc. sections listed here, + # NOT the global ones the "default" site. + # + listen { + ipaddr = 192.0.2.1 + port = 1821 + type = auth + } + + # + # This client is listed within the "server" section, + # and is therefore known ONLY to the socket defined + # in the "listen" section above. If the client IP + # sends a request to a different socket, the server + # will treat it as an unknown client, and will not + # respond. + # + # In contrast, the client listed at the top of this file + # is outside of any "server" section, and is therefore + # global in scope. It can send packets to any port + # defined in a global "listen" section. It CANNOT send + # packets to the listen section defined above, though. + # + # Note that you don't have to have a "virtual_server = example" + # line here, as the client is encapsulated within + # the "server" section. + # + client 192.0.2.9 { + shortname = example-client + secret = testing123 + } + + authorize { + # + # Some example policies. See "man unlang" for more. + # + if (&User-Name == 'bob') { + update control { + &Cleartext-Password := 'bob' + } + } + + # + # And then reject the user. The next line requires + # that the "always reject {}" section is defined in + # the "modules" section of radiusd.conf. + # + reject + } + + authenticate { + + } + + post-auth { + + Post-Auth-Type Reject { + update reply { + &Reply-Message = 'This is only an example.' + } + } + } + +} diff --git a/raddb/sites-available/google-ldap-auth b/raddb/sites-available/google-ldap-auth new file mode 100644 index 0000000..3be530f --- /dev/null +++ b/raddb/sites-available/google-ldap-auth @@ -0,0 +1,225 @@ +# -*- text -*- +######################################################################### +# +# The file contains a sample virtual server which uses Google +# Secure LDAP for authentication +# +# This file is designed to be used as an inner tunnel virtual +# server for EAP-TTLS-PAP authentication. +# +# Use this virtual server in conjunction with the sample Google +# Secure LDAP module configuration, which is in +# mods-available/ldap_google. +# +# Due to the poor performance of Google Secure LDAP, this +# configuration also caches information around accepts, rejects, +# and LDAP qeuries. See mods-available/cache_auth for the +# configuration of the various "cache" modules used here. +# +# The TTL on these caches should be tuned to match site policies +# - e.g. how long should a user be re-authenticated from a cache +# without performing an LDAP bind. +# +# Typically the caches are beneficial when performing +# authentication for 802.1x wifi where repeated authentications +# occur as users roam. We also recommend enabling the "cache" +# subsection of mods-available/eap. Both kinds of caching can +# be done at the same time, and both kinds of caching will help +# improve system performance and stability. +# +# $Id$ +# +######################################################################### + +server google-ldap { + +# +# This is only for testing, and not needed in general operation. +# +listen { + ipaddr = 127.0.0.1 + port = 18123 + type = auth +} + +authorize { + # + # Perform sanity checks on the supplied user name + # + filter_username + + # + # Perform sanity checks comparing inner and outer user name + # + filter_inner_identity + + # + # Split up user names in the form user@domain + # + split_username_nai + + # + # Check the authentication cache to see if this user + # recently sucessfully authenticated + # + update control { + &Cache-Status-Only := 'yes' + } + cache_auth_accept + + # + # If there's a cached User-Name / User-Password which matches + # what the user sent here, then the user has been + # authenticated. We can then avoid interacting with Google's + # LDAP server, which significantly improves the performance + # of user authentication. + # + if (ok) { + update { + &control:Auth-Type := Accept + } + return + } + + # + # Check the reject cache to see if this user was + # recently rejected + # + update control { + &Cache-Status-Only := 'yes' + } + cache_auth_reject + + # + # If there's a cached User-Name / User-Password which matches + # what the user sent here, then the user has been rejected. + # As with authentication above, we don't need to check + # Google's LDAP server, and can improve performance. + # + # Note that in may cases rejected users will try over and + # over again. This increased load can significantly affect + # performance, and can even prevent other users from + # authenticating! The solution is to just tell the bad users + # to "go away" as quickly as possible, while using minimal + # resources. + # + if (ok) { + update { + &Module-Failure-Message := "Rejected by cache entry" + } + reject + } + + # + # If group membership checks are required, then ensure that + # the relevant "cacheable_" option is set against the ldap + # instance, and call the ldap module here. + # + # If group membership is irrelevant, do not call ldap here + # to improve performance + # + # ldap_google + + # + # As Google LDAP does not return user passwords, + # authentication is only possible by LDAP "bind as user". So + # only PAP and TTLS+PAP will work. + # + # If the request contains a password, then force LDAP "bind + # as user". + # + if (&User-Password && !control:Auth-Type) { + update { + &control:Auth-Type := ldap + } + + # + # Look up a user's DN in the cache. + # + # The standard ldap auth mechanism is 3 steps + # - bind as admin user + # - lookup the user's DN + # - bind as the user + # + # Caching the DN removes the first two steps + # during the lifetime of the cache entry. + # + # If the ldap module is called above, then this cache + # call can be commented out; the DN will have been + # retrieved above by the "ldap_google" module. + # + update control { + &Cache-Read-Only := "yes" + } + cache_ldap_user_dn + + } +} + +authenticate { + # + # Use an LDAP "bind as user" to authenticate. Google will + # check the users' password, and will return success / fail. + # + Auth-Type LDAP { + ldap_google + } + +} + +# +# Google LDAP has no specific session section configuration +# +session { + +} + +# +# In post-auth the various caches get updated. +# +# Add in any additional policy required to set reply attributes +# +post-auth { + # + # Cache the user's DN. See the authorize section for + # how and why this would be used + # + cache_ldap_user_dn + + # + # If a user was authenticated by ldap, add the users name / + # password to the cache of successful authentications. + # + # Otherwise the user was authenticated via the + # cache_auth_accept call above, in the "authorize" section. + # + if (&control:Auth-Type == ldap) { + cache_auth_accept + } + + Post-Auth-Type REJECT { + attr_filter.access_reject + + # + # Record rejects in a cache, as a protection against + # repeated attempts from mis-configured clients. + # + if (&control:Auth-Type == ldap) { + cache_auth_reject + } + + # + # Clear the DN cache entry if it exists. + # If the DN cache is in use, retaining an incorrect + # DN entry could cause issues if the user's DN + # has changed. + # + update control { + &Cache-TTL := 0 + } + cache_ldap_user_dn + + } +} + +} diff --git a/raddb/sites-available/inner-tunnel b/raddb/sites-available/inner-tunnel new file mode 100644 index 0000000..10eeb55 --- /dev/null +++ b/raddb/sites-available/inner-tunnel @@ -0,0 +1,438 @@ +# -*- text -*- +###################################################################### +# +# This is a virtual server that handles *only* inner tunnel +# requests for EAP-TTLS and PEAP types. +# +# $Id$ +# +###################################################################### + +server inner-tunnel { + +# +# This next section is here to allow testing of the "inner-tunnel" +# authentication methods, independently from the "default" server. +# It is listening on "localhost", so that it can only be used from +# the same machine. +# +# $ radtest USER PASSWORD 127.0.0.1:18120 0 testing123 +# +# If it works, you have configured the inner tunnel correctly. To check +# if PEAP will work, use: +# +# $ radtest -t mschap USER PASSWORD 127.0.0.1:18120 0 testing123 +# +# If that works, PEAP should work. If that command doesn't work, then +# +# FIX THE INNER TUNNEL CONFIGURATION SO THAT IT WORKS. +# +# Do NOT do any PEAP tests. It won't help. Instead, concentrate +# on fixing the inner tunnel configuration. DO NOTHING ELSE. +# +listen { + ipaddr = 127.0.0.1 + port = 18120 + type = auth +} + + +# Authorization. First preprocess (hints and huntgroups files), +# then realms, and finally look in the "users" file. +# +# The order of the realm modules will determine the order that +# we try to find a matching realm. +# +# Make *sure* that 'preprocess' comes before any realm if you +# need to setup hints for the remote radius server +authorize { + # + # Take a User-Name, and perform some checks on it, for spaces and other + # invalid characters. If the User-Name appears invalid, reject the + # request. + # + # See policy.d/filter for the definition of the filter_username policy. + # + filter_username + + # + # Do checks on outer / inner User-Name, so that users + # can't spoof us by using incompatible identities + # +# filter_inner_identity + + # + # The chap module will set 'Auth-Type := CHAP' if we are + # handling a CHAP request and Auth-Type has not already been set + chap + + # + # If the users are logging in with an MS-CHAP-Challenge + # attribute for authentication, the mschap module will find + # the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP' + # to the request, which will cause the server to then use + # the mschap module for authentication. + mschap + + # + # Pull crypt'd passwords from /etc/passwd or /etc/shadow, + # using the system API's to get the password. If you want + # to read /etc/passwd or /etc/shadow directly, see the + # passwd module, above. + # +# unix + + # + # Look for IPASS style 'realm/', and if not found, look for + # '@realm', and decide whether or not to proxy, based on + # that. +# IPASS + + # + # Look for realms in user@domain format + # + # Note that proxying the inner tunnel authentication means + # that the user MAY use one identity in the outer session + # (e.g. "anonymous", and a different one here + # (e.g. "user@example.com"). The inner session will then be + # proxied elsewhere for authentication. If you are not + # careful, this means that the user can cause you to forward + # the authentication to another RADIUS server, and have the + # accounting logs *not* sent to the other server. This makes + # it difficult to bill people for their network activity. + # + suffix +# ntdomain + + # + # The "suffix" module takes care of stripping the domain + # (e.g. "@example.com") from the User-Name attribute, and the + # next few lines ensure that the request is not proxied. + # + # If you want the inner tunnel request to be proxied, delete + # the next few lines. + # + update control { + &Proxy-To-Realm := LOCAL + } + + # + # This module takes care of EAP-MSCHAPv2 authentication. + # + # It also sets the EAP-Type attribute in the request + # attribute list to the EAP type from the packet. + # + # The example below uses module failover to avoid querying all + # of the following modules if the EAP module returns "ok". + # Therefore, your LDAP and/or SQL servers will not be queried + # for the many packets that go back and forth to set up TTLS + # or PEAP. The load on those servers will therefore be reduced. + # + eap { + ok = return + } + + # + # Read the 'users' file + files + + # + # Look in an SQL database. The schema of the database + # is meant to mirror the "users" file. + # + # See "Authorization Queries" in `mods-config/sql/main/$driver/queries.conf` + -sql + + # + # If you are using /etc/smbpasswd, and are also doing + # mschap authentication, the un-comment this line, and + # enable the "smbpasswd" module. +# smbpasswd + + # + # The ldap module reads passwords from the LDAP database. + -ldap + + # + # Enforce daily limits on time spent logged in. +# daily + + expiration + logintime + + # + # If no other module has claimed responsibility for + # authentication, then try to use PAP. This allows the + # other modules listed above to add a "known good" password + # to the request, and to do nothing else. The PAP module + # will then see that password, and use it to do PAP + # authentication. + # + # This module should be listed last, so that the other modules + # get a chance to set Auth-Type for themselves. + # + pap +} + + +# Authentication. +# +# +# This section lists which modules are available for authentication. +# Note that it does NOT mean 'try each module in order'. It means +# that a module from the 'authorize' section adds a configuration +# attribute 'Auth-Type := FOO'. That authentication type is then +# used to pick the appropriate module from the list below. +# + +# In general, you SHOULD NOT set the Auth-Type attribute. The server +# will figure it out on its own, and will do the right thing. The +# most common side effect of erroneously setting the Auth-Type +# attribute is that one authentication method will work, but the +# others will not. +# +# The common reasons to set the Auth-Type attribute by hand +# is to either forcibly reject the user, or forcibly accept him. +# +authenticate { + # + # PAP authentication, when a back-end database listed + # in the 'authorize' section supplies a password. The + # password can be clear-text, or encrypted. + Auth-Type PAP { + pap + } + + # + # Most people want CHAP authentication + # A back-end database listed in the 'authorize' section + # MUST supply a CLEAR TEXT password. Encrypted passwords + # won't work. + Auth-Type CHAP { + chap + } + + # + # MSCHAP authentication. + Auth-Type MS-CHAP { + mschap + } + + # + # For old names, too. + # + mschap + + # + # Pluggable Authentication Modules. +# pam + + # Uncomment it if you want to use ldap for authentication + # + # Note that this means "check plain-text password against + # the ldap database", which means that EAP won't work, + # as it does not supply a plain-text password. + # + # We do NOT recommend using this. LDAP servers are databases. + # They are NOT authentication servers. FreeRADIUS is an + # authentication server, and knows what to do with authentication. + # LDAP servers do not. + # +# Auth-Type LDAP { +# ldap +# } + + # + # Allow EAP authentication. + eap +} + +###################################################################### +# +# There are no accounting requests inside of EAP-TTLS or PEAP +# tunnels. +# +###################################################################### + + +# Session database, used for checking Simultaneous-Use. Either the radutmp +# or rlm_sql module can handle this. +# The rlm_sql module is *much* faster +session { + radutmp + + # + # See "Simultaneous Use Checking Queries" in `mods-config/sql/main/$driver/queries.conf` +# sql +} + + +# Post-Authentication +# Once we KNOW that the user has been authenticated, there are +# additional steps we can take. +# +# Note that the last packet of the inner-tunnel authentication +# MAY NOT BE the last packet of the outer session. So updating +# the outer reply MIGHT work, and sometimes MIGHT NOT. The +# exact functionality depends on both the inner and outer +# authentication methods. +# +# If you need to send a reply attribute in the outer session, +# the ONLY safe way is to set "use_tunneled_reply = yes", and +# then update the inner-tunnel reply. +post-auth { + # If you want privacy to remain, see the + # Chargeable-User-Identity attribute from RFC 4372. + # If you want to use it just uncomment the line below. +# cui-inner + + # + # If you want the Access-Accept to contain the inner + # User-Name, uncomment the following lines. + # +# update outer.session-state { +# User-Name := &User-Name +# } + + # + # If you want to have a log of authentication replies, + # un-comment the following line, and enable the + # 'detail reply_log' module. +# reply_log + + # + # After authenticating the user, do another SQL query. + # + # See "Authentication Logging Queries" in `mods-config/sql/main/$driver/queries.conf` + -sql + + # + # Un-comment the following if you have set + # 'edir = yes' in the ldap module sub-section of + # the 'modules' section. + # +# ldap + + + # + # Un-comment the following if you want to generate Moonshot (ABFAB) TargetedIds + # + # IMPORTANT: This requires the UUID package to be installed, and a targeted_id_salt + # to be configured. + # + # This functionality also supports SQL backing. To use this functionality, enable + # and configure the moonshot-targeted-ids SQL module in the mods-enabled directory. + # Then remove the comments from the appropriate lines in each of the below + # policies in the policy.d/moonshot-targeted-ids file. + # +# moonshot_host_tid +# moonshot_realm_tid +# moonshot_coi_tid + + # + # Instead of "use_tunneled_reply", change this "if (0)" to an + # "if (1)". + # + if (0) { + # + # These attributes are for the inner-tunnel only, + # and MUST NOT be copied to the outer reply. + # + update reply { + User-Name !* ANY + Message-Authenticator !* ANY + EAP-Message !* ANY + Proxy-State !* ANY + MS-MPPE-Encryption-Types !* ANY + MS-MPPE-Encryption-Policy !* ANY + MS-MPPE-Send-Key !* ANY + MS-MPPE-Recv-Key !* ANY + } + + # + # Copy the inner reply attributes to the outer + # session-state list. The post-auth policy will take + # care of copying the outer session-state list to the + # outer reply. + # + update { + &outer.session-state: += &reply: + } + } + + # + # Access-Reject packets are sent through the REJECT sub-section of the + # post-auth section. + # + # Add the ldap module name (or instance) if you have set + # 'edir = yes' in the ldap module configuration + # + Post-Auth-Type REJECT { + # log failed authentications in SQL, too. + -sql + attr_filter.access_reject + + # + # Let the outer session know which module failed, and why. + # + update outer.session-state { + &Module-Failure-Message := &request:Module-Failure-Message + } + } +} + +# +# When the server decides to proxy a request to a home server, +# the proxied request is first passed through the pre-proxy +# stage. This stage can re-write the request, or decide to +# cancel the proxy. +# +# Only a few modules currently have this method. +# +pre-proxy { + # Uncomment the following line if you want to change attributes + # as defined in the preproxy_users file. +# files + + # Uncomment the following line if you want to filter requests + # sent to remote servers based on the rules defined in the + # 'attrs.pre-proxy' file. +# attr_filter.pre-proxy + + # If you want to have a log of packets proxied to a home + # server, un-comment the following line, and the + # 'detail pre_proxy_log' section, above. +# pre_proxy_log +} + +# +# When the server receives a reply to a request it proxied +# to a home server, the request may be massaged here, in the +# post-proxy stage. +# +post-proxy { + + # If you want to have a log of replies from a home server, + # un-comment the following line, and the 'detail post_proxy_log' + # section, above. +# post_proxy_log + + # Uncomment the following line if you want to filter replies from + # remote proxies based on the rules defined in the 'attrs' file. +# attr_filter.post-proxy + + # + # If you are proxying LEAP, you MUST configure the EAP + # module, and you MUST list it here, in the post-proxy + # stage. + # + # You MUST also use the 'nostrip' option in the 'realm' + # configuration. Otherwise, the User-Name attribute + # in the proxied request will not match the user name + # hidden inside of the EAP packet, and the end server will + # reject the EAP request. + # + eap +} + +} # inner-tunnel server block diff --git a/raddb/sites-available/originate-coa b/raddb/sites-available/originate-coa new file mode 100644 index 0000000..3325b88 --- /dev/null +++ b/raddb/sites-available/originate-coa @@ -0,0 +1,185 @@ +# -*- text -*- +###################################################################### +# +# The server can originate Change of Authorization (CoA) or +# Disconnect request packets. These packets are used to dynamically +# change the parameters of a users session (bandwidth, etc.), or +# to forcibly disconnect the user. +# +# There are some caveats. Not all NAS vendors support this +# functionality. Even for the ones that do, it may be difficult to +# find out what needs to go into a CoA-Request or Disconnect-Request +# packet. All we can suggest is to read the NAS documentation +# available from the vendor. That documentation SHOULD describe +# what information their equipment needs to see in a CoA packet. +# +# This information is usually a list of attributes such as: +# +# NAS-IP-Address (or NAS-IPv6 address) +# NAS-Identifier +# User-Name +# Acct-Session-Id +# +# CoA packets can be originated when a normal Access-Request or +# Accounting-Request packet is received. Simply update the +# "coa" list: +# +# update coa { +# &User-Name = "%{User-Name}" +# &Acct-Session-Id = "%{Acct-Session-Id}" +# &NAS-IP-Address = "%{NAS-IP-Address}" +# } +# +# And the CoA packet will be sent. You can also send Disconnect +# packets by using "update disconnect { ...". +# +# This "update coa" entry can be placed in any section (authorize, +# preacct, etc.), EXCEPT for pre-proxy and post-proxy. The CoA +# packets CANNOT be sent if the original request has been proxied. +# +# The CoA functionality works best when the RADIUS server and +# the NAS receiving CoA packets are on the same network. +# +# If "update coa { ... " is used, and then later it becomes necessary +# to not send a CoA request, the following example can suppress the +# CoA packet: +# +# update control { +# &Send-CoA-Request = No +# } +# +# The default destination of a CoA packet is the NAS (or client) +# the sent the original Access-Request or Accounting-Request. See +# raddb/clients.conf for a "coa_server" configuration that ties +# a client to a specific home server, or to a home server pool. +# +# If you need to send the packet to a different destination, update +# the "coa" list with one of: +# +# Packet-Dst-IP-Address = ... +# Packet-Dst-IPv6-Address = ... +# Home-Server-Pool = ... +# +# That specifies an Ipv4 or IPv6 address, or a home server pool +# (such as the "coa" pool example below). This use is not +# recommended, however, It is much better to point the client +# configuration directly at the CoA server/pool, as outlined +# earlier. +# +# If the CoA port is non-standard, you can also set: +# +# Packet-Dst-Port +# +# to have the value of the port. +# +###################################################################### + +# +# When CoA packets are sent to a NAS, the NAS is acting as a +# server (see RFC 5176). i.e. it has a type (accepts CoA and/or +# Disconnect packets), an IP address (or IPv6 address), a +# destination port, and a shared secret. +# +home_server example-coa { + type = coa + + # + # Note that a home server of type "coa" MUST be a real NAS, + # with an ipaddr or ipv6addr. It CANNOT point to a virtual + # server. + # + # Change this IP address to the IP address of the NAS. + # + ipaddr = 192.0.2.42 + port = 3799 + + # This secret SHOULD NOT be the same as the shared + # secret in a "client" section. + secret = testing1234 + + # CoA specific parameters. See raddb/proxy.conf for details. + coa { + irt = 2 + mrt = 16 + mrc = 5 + mrd = 30 + } +} + +# +# CoA servers can be put into pools, just like normal servers. +# +home_server_pool coa { + type = fail-over + + # Point to the CoA server above. + home_server = example-coa + + # CoA requests are run through the pre-proxy section. + # CoA responses are run through the post-proxy section. + virtual_server = originate-coa.example.com + + # + # Home server pools of type "coa" cannot (currently) have + # a "fallback" configuration. + # +} + +# +# When this virtual server is run, the original request has FINISHED +# processing. i.e. the reply has already been sent to the NAS. +# You can access the attributes in the original packet, reply, and +# control items, but changing them will have NO EFFECT. +# +# The CoA packet is in the "proxy-request" attribute list. +# The CoA reply (if any) is in the "proxy-reply" attribute list. +# +server originate-coa.example.com { + pre-proxy { + update proxy-request { + NAS-IP-Address = 192.0.2.42 + } + } + + # + # Handle the responses here. + # + post-proxy { + switch &proxy-reply:Packet-Type { + case CoA-ACK { + ok + } + + case CoA-NAK { + # the NAS didn't like the CoA request + ok + } + + case Disconnect-ACK { + ok + } + + case Disconnect-NAK { + # the NAS didn't like the Disconnect request + ok + } + + # Invalid packet type. This shouldn't happen. + case { + fail + } + } + + # + # These methods are run when there is NO response + # to the request. + # + Post-Proxy-Type Fail-CoA { + ok + } + + Post-Proxy-Type Fail-Disconnect { + ok + } + } +} diff --git a/raddb/sites-available/proxy-inner-tunnel b/raddb/sites-available/proxy-inner-tunnel new file mode 100644 index 0000000..938d954 --- /dev/null +++ b/raddb/sites-available/proxy-inner-tunnel @@ -0,0 +1,47 @@ +# -*- text -*- +###################################################################### +# +# This is a virtual server that handles *only* inner tunnel +# requests for EAP-TTLS and PEAP types. +# +# $Id$ +# +###################################################################### + +server proxy-inner-tunnel { + +# +# This example is very simple. All inner tunnel requests get +# proxied to another RADIUS server. +# +authorize { + # + # Do other things here, as necessary. + # + # e.g. run the "realms" module, to decide how to proxy + # the inner tunnel request. + # + + update control { + # You should update this to be one of your realms. + &Proxy-To-Realm := "example.com" + } +} + +authenticate { + # + # This is necessary so that the inner tunnel EAP-MSCHAPv2 + # method can be called. That method takes care of turning + # EAP-MSCHAPv2 into plain MS-CHAPv2, if necessary. + eap +} + +post-proxy { + # + # This is necessary for LEAP, or if you set: + # + # proxy_tunneled_request_as_eap = no + # + eap +} +} diff --git a/raddb/sites-available/resource-check b/raddb/sites-available/resource-check new file mode 100644 index 0000000..486c3b8 --- /dev/null +++ b/raddb/sites-available/resource-check @@ -0,0 +1,140 @@ +# -*- text -*- +###################################################################### +# +# This virtual server provides an example of how to dynamically amend the +# control flow within some virtual server's policy on the basis of the status +# of some resource, such as an external database. +# +# This resource-check virtual server receives periodic dummy server-status +# requests that trigger an arbitrary set of checks. On the basis of those +# checks the status of an instance of the rlm_always module, that we refer to +# as the "control module", is updated to reflect the system status. +# +# Elsewhere, some other virtual server (the "controlled virtual server") uses +# the control module to make decisions during the processing of incoming +# requests. By amending the status of the control module in response to the +# system status this virtual server is able to manipulate the outcome of the +# controlled virtual server. +# +# Firstly, the authorize section of this virtual server will need to be +# amended to check the status of the external resources and to set the status +# of the control module appropriately, as described in the inline comments +# below... +# +# In addition to configuring and activating this virtual server, a control +# module must be configured as an instance of rlm_always in mods-enabled, for +# example: +# +# always db_online { +# # Default to online +# rcode = ok +# } +# +# Now trigger the resource checks by sending a server-status request to this +# virtual server, as follows: +# +# echo "Message-Authenticator = 0x00" | \ +# radclient -r 1 -t 3 -q 127.0.0.1:18122 status testing123 +# +# The trigger could be invoked by a cron job or if more frequent checks than +# once per minute are required a systemd timer might be used. +# +# The current status of the control module can be examined at any time using +# radmin: +# +# radmin -e 'show module status db_online' +# +# For radmin to work requires that the control-socket virtual server is +# configured and enabled. +# +# The controlled virtual server will contain some control flow decision that +# uses the control module, for example: +# +# server default { +# +# ... +# +# authorize { +# +# # If the database is not healthy then remain silent to trigger +# # NAS failover +# # +# db_online { +# fail = 1 +# } +# if (fail) { +# do_not_respond +# } +# +# sql +# +# pap +# } +# +# ... +# +# +# The configuration for this virtual server follows and should be amended as +# required... +# + + +# +# Listen on a local port for Server-Status requests that trigger the resource +# checks. +# +# This uses the normal set of clients, with the same secret as for +# authentication and accounting. +# +listen { + type = status + ipaddr = 127.0.0.1 + port = 18122 + virtual_server = resource_check +} + + +# +# Within this virual server we provide only an Autz-Type Status-Server section +# whose task is to perform the resource checks and sets the status of the +# "control module" +# +server resource-check { + +authorize { + +Autz-Type Status-Server { + + # + # In this example we check whether a PostgreSQL database is in + # recovery (or inaccessible) and when this is the case we fail the + # db_online control module. + # + # Other modules could be used here. + # + # You can even invoke synchronous checks using the %{exec:...} xlat in + # which case timeout should be set to less than the check trigger + # interval to avoid buildup of checks when resources do not respond. + # See rlm_exec for details. + # + if ("%{sql:SELECT pg_is_in_recovery()}" != "f") { + + # Fail the db_online module, if it isn't already + if ("%{db_online:}" != "fail") { + %{db_online:fail} + } + + } else { + + # Set the db_online module status to alive, if it isn't already + if ("%{db_online:}" != "alive") { + %{db_online:alive} + } + + } + +} + +} + +} diff --git a/raddb/sites-available/robust-proxy-accounting b/raddb/sites-available/robust-proxy-accounting new file mode 100644 index 0000000..85f2f9d --- /dev/null +++ b/raddb/sites-available/robust-proxy-accounting @@ -0,0 +1,167 @@ +# -*- text -*- +###################################################################### +# +# This is a sample configuration for robust proxy accounting. +# accounting packets are proxied, OR logged locally if all +# home servers are down. When the home servers come back up, +# the accounting packets are forwarded. +# +# This method enables the server to proxy all packets to the +# home servers when they're up, AND to avoid writing to the +# detail file in most situations. +# +# In most situations, proxying of accounting messages is done +# in a "pass-through" fashion. If the home server does not +# respond, then the proxy server does not respond to the NAS. +# That means that the NAS must retransmit packets, sometimes +# forever. This example shows how the proxy server can still +# respond to the NAS, even if all home servers are down. +# +# This configuration could be done MUCH more simply if ALL +# packets were written to the detail file. But that would +# involve a lot more disk writes, which may not be a good idea. +# +# This file is NOT meant to be used as-is. It needs to be +# edited to match your local configuration. +# +# Please see the sites-available/default file, in the +# "Post-Proxy-Type Fail-Accounting" section. That should be +# configured to write packets to the "detail.example.com" +# file when proxying fails. The "listen" section below will +# then read packets from that file, and proxy them. +# +# See also mods-available/detail.example.com, which is the +# module that writes the "detail.example.com" file. +# +# +# $Id$ +# +###################################################################### + +# (1) Define two home servers. +home_server home1.example.com { + type = acct + ipaddr = 192.0.2.10 + port = 1813 + secret = testing123 + + # Mark this home server alive ONLY when it starts being responsive + status_check = request + username = "test_user_status_check" + + # Set the response timeout aggressively low. + # You MAY have to increase this, depending on tests with + # your local installation. + response_window = 6 +} + +home_server home2.example.com { + type = acct + ipaddr = 192.0.2.20 + port = 1813 + secret = testing123 + + # Mark this home server alive ONLY when it starts being responsive + status_check = request + username = "test_user_status_check" + + # Set the response timeout aggressively low. + # You MAY have to increase this, depending on tests with + # your local installation. + response_window = 6 +} + +# (2) Put all of the servers into a pool. +home_server_pool acct_pool.example.com { + type = load-balance # other types are OK, too. + + home_server = home1.example.com + home_server = home2.example.com + # add more home_server's here. + + # for pre/post-proxy policies + virtual_server = home.example.com +} + +# (3) Define a realm for these home servers. +# It should NOT be used as part of normal proxying decisions! +realm acct_realm.example.com { + acct_pool = acct_pool.example.com +} + +# (4) Define a detail file writer. +# See raddb/modules/detail.example.com + +# (5) Define a virtual server to handle pre/post-proxy re-writing +server home.example.com { + pre-proxy { + # Insert pre-proxy rules here + } + + post-proxy { + # Insert post-proxy rules here + + # This will be called when the CURRENT packet failed + # to be proxied. This may happen when one home server + # suddenly goes down, even though another home server + # may be alive. + # + # i.e. the current request has run out of time, so it + # cannot fail over to another (possibly) alive server. + # + # We want to respond to the NAS, so that it can stop + # re-sending the packet. We write the packet to the + # "detail" file, where it will be read, and sent to + # another home server. + # + Post-Proxy-Type Fail-Accounting { + detail.example.com + } + + # + # This section is run when there are problems + # proxying Access-Request packets + # + Post-Proxy-Type Fail-Authentication { + # add policies here + } + + } + + + # Read accounting packets from the detail file(s) for + # the home server. + # + # Note that you can have only ONE "listen" section reading + # detail files from a particular directory. That is why the + # destination host name is used as part of the directory name + # below. Having two "listen" sections reading detail files + # from the same directory WILL cause problems. The packets + # may be read by one, the other, or both "listen" sections. + listen { + type = detail + filename = "${radacctdir}/detail.example.com/detail-*:*" + load_factor = 10 + } + + # All packets read from the detail file are proxied back to + # the home servers. + # + # The normal pre/post-proxy rules are applied to them, too. + # + # If the home servers are STILL down, then the server stops + # reading the detail file, and queues the packets for a later + # retransmission. The Post-Proxy-Type "Fail" handler is NOT + # called. + # + # When the home servers come back up, the packets are forwarded, + # and the detail file processed as normal. + accounting { + # You may want accounting policies here... + + update control { + &Proxy-To-Realm := 'acct_realm.example.com' + } + } + +} diff --git a/raddb/sites-available/soh b/raddb/sites-available/soh new file mode 100644 index 0000000..86748b6 --- /dev/null +++ b/raddb/sites-available/soh @@ -0,0 +1,34 @@ +# This is a simple server for the MS SoH requests generated by the +# peap module - see "eap.conf" for more info + +# Requests are ONLY passed through the authorize section, and cannot +# current be proxied (in any event, the radius attributes used are +# internal). + +server soh-server { + authorize { + if (&SoH-Supported == no) { + # client NAKed our request for SoH - not supported, or turned off + update config { + &Auth-Type = Accept + } + } + else { + # client replied; check something - this is a local policy issue! + if (&SoH-MS-Windows-Health-Status =~ /antivirus (warn|error) /) { + update config { + &Auth-Type = Reject + } + update reply { + &Reply-Message = 'You must have antivirus enabled & installed!' + } + } + else { + update config { + &Auth-Type = Accept + } + } + } + } +} + diff --git a/raddb/sites-available/status b/raddb/sites-available/status new file mode 100644 index 0000000..e7d4346 --- /dev/null +++ b/raddb/sites-available/status @@ -0,0 +1,127 @@ +# -*- text -*- +###################################################################### +# +# A virtual server to handle ONLY Status-Server packets. +# +# Server statistics can be queried with a properly formatted +# Status-Server request. See dictionary.freeradius for comments. +# +# If radiusd.conf has "status_server = yes", then any client +# will be able to send a Status-Server packet to any port +# (listen section type "auth", "acct", or "status"), and the +# server will respond. +# +# If radiusd.conf has "status_server = no", then the server will +# ignore Status-Server packets to "auth" and "acct" ports. It +# will respond only if the Status-Server packet is sent to a +# "status" port. +# +# The server statistics are available ONLY on socket of type +# "status". Queries for statistics sent to any other port +# are ignored. +# +# Similarly, a socket of type "status" will not process +# authentication or accounting packets. This is for security. +# +# $Id$ +# +###################################################################### + +server status { + listen { + # ONLY Status-Server is allowed to this port. + # ALL other packets are ignored. + type = status + + ipaddr = 127.0.0.1 + port = 18121 + } + + # + # We recommend that you list ONLY management clients here. + # i.e. NOT your NASes or Access Points, and for an ISP, + # DEFINITELY not any RADIUS servers that are proxying packets + # to you. + # + # If you do NOT list a client here, then any client that is + # globally defined (i.e. all of them) will be able to query + # these statistics. + # + # Do you really want your partners seeing the internal details + # of what your RADIUS server is doing? + # + client admin { + ipaddr = 127.0.0.1 + secret = adminsecret + } + + # + # Simple authorize section. The "Autz-Type Status-Server" + # section will work here, too. See "raddb/sites-available/default". + authorize { + ok + + # respond to the Status-Server request. + Autz-Type Status-Server { + ok + } + } +} + +# Statistics can be queried via a number of methods: +# +# All packets received/sent by the server (1 = auth, 2 = acct) +# FreeRADIUS-Statistics-Type = 3 +# +# All packets proxied by the server (4 = proxy-auth, 8 = proxy-acct) +# FreeRADIUS-Statistics-Type = 12 +# +# All packets sent && received: +# FreeRADIUS-Statistics-Type = 15 +# +# Internal server statistics: +# FreeRADIUS-Statistics-Type = 16 +# +# All packets for a particular client (globally defined) +# FreeRADIUS-Statistics-Type = 35 +# FreeRADIUS-Stats-Client-IP-Address = 192.0.2.1 +# +# All packets for a client attached to a "listen" ip/port +# FreeRADIUS-Statistics-Type = 35 +# FreeRADIUS-Stats-Client-IP-Address = 192.0.2.1 +# FreeRADIUS-Stats-Server-IP-Address = 127.0.0.1 +# FreeRADIUS-Stats-Server-Port = 1812 +# +# All packets for a "listen" IP/port +# FreeRADIUS-Statistics-Type = 67 +# FreeRADIUS-Stats-Server-IP-Address = 127.0.0.1 +# FreeRADIUS-Stats-Server-Port = 1812 +# +# All packets for a home server IP / port +# FreeRADIUS-Statistics-Type = 131 +# FreeRADIUS-Stats-Server-IP-Address = 192.0.2.2 +# FreeRADIUS-Stats-Server-Port = 1812 + +# +# You can also get exponentially weighted moving averages of +# response times (in usec) of home servers. Just set the config +# item "historic_average_window" in a home_server section. +# +# By default it is zero (don't calculate it). Useful values +# are between 100, and 10,000. The server will calculate and +# remember the moving average for this window, and for 10 times +# that window. +# + +# +# Some of this could have been simplified. e.g. the proxy-auth and +# proxy-acct bits aren't completely necessary. But using them permits +# the server to be queried for ALL inbound && outbound packets at once. +# This gives a good snapshot of what the server is doing. +# +# Due to internal limitations, the statistics might not be exactly up +# to date. Do not expect all of the numbers to add up perfectly. +# The Status-Server packets are also counted in the total requests && +# responses. The responses are counted only AFTER the response has +# been sent. +# diff --git a/raddb/sites-available/tls b/raddb/sites-available/tls new file mode 100644 index 0000000..137fcbc --- /dev/null +++ b/raddb/sites-available/tls @@ -0,0 +1,696 @@ +###################################################################### +# +# RADIUS over TLS (radsec) +# +# When a new client connects, the various TLS parameters for the +# connection are available as dynamic expansions, e.g. +# +# %{listen:TLS-Client-Cert-Common-Name} +# +# Along with other TLS-Client-Cert-... attributes. +# These expansions will only exist if the relevant fields +# are in the client certificate. Read the debug output to see +# which fields are available. Look for output like the following: +# +# (0) TLS - Creating attributes from certificate OIDs +# (0) TLS-Client-Cert-Subject-Alt-Name-Dns := "one.example.org" +# (0) TLS-Client-Cert-Subject-Alt-Name-Dns := "two.example.org" +# ... +# +# It is also possible to distinguish between connections which have +# TLS enables, and ones which do not. The expansion: +# +# %{listen:tls} +# +# Will return "yes" if the connection has TLS enabled. It will +# return "no" if TLS is not enabled for a particular listen section. +# +# A number of TLS-Client-Cert-.. attributes holds X509v3 extensions +# data, attributes named the way OpenSSL names them. It is possible +# to extract data for an extension not known to OpenSSL by defining +# a custom string attribute which contains extension OID in it's +# name after 'TLS-Client-Cert-' prefix. E.g.: +# +# ATTRIBUTE TLS-Client-Cert-1.3.6.1.4.1.311.21.7 3002 string +# +# which will yield something simmilar to: +# +# (0) eap_tls: TLS - Creating attributes from certificate OIDs +# (0) eap_tls: TLS-Client-Cert-1.3.6.1.4.1.311.21.7 += "0x302e06" +# ... +# +###################################################################### + +listen { + ipaddr = * + port = 2083 + + # + # TCP and TLS sockets can accept Access-Request and + # Accounting-Request on the same socket. + # + # auth = only Access-Request + # acct = only Accounting-Request + # auth+acct = both + # coa = only CoA / Disconnect requests + # + type = auth+acct + + # For now, only TCP transport is allowed. + proto = tcp + + # Send packets to the default virtual server + virtual_server = default + + clients = radsec + + # + # Use the haproxy "PROXY protocol". + # + # This configuration allows for many FreeRADIUS servers to be + # behind a haproxy server. The "PROXY protocol" allows + # haproxy to send the actual client IP to FreeRADIUS. + # + # This will work ONLY for RadSec (TLS). Both the haproxy AND + # the RadSec client MUST be listed as allowed RADIUS clients. + # + # haproxy needs to have "send-proxy" configured for this server. + # Health checks should be turned off, as haproxy does not + # support RADIUS health checks. + # + # The main use of this feature is for scalability. There is no + # longer any need to have a RADIUS proxy as a load balancer. + # haproxy is fast, stable, and supports dynamic reloads! + # + # The only problem is that many RADIUS clients do not support + # RadSec. That situation will hopefully change over time. + # +# proxy_protocol = no + + # + # When this is set to "yes", new TLS connections + # are processed through a section called + # + # Autz-Type New-TLS-Connection { + # ... + # } + # + # The request contains TLS client certificate attributes, + # and nothing else. The debug output will print which + # attributes are available on your system. + # + # If the section returns "ok" or "updated", then the + # connection is accepted. Otherwise the connection is + # terminated. + # +# check_client_connections = yes + + # + # Connection limiting for sockets with "proto = tcp". + # + limit { + # + # Limit the number of simultaneous TCP connections to the socket + # + # The default is 16. + # Setting this to 0 means "no limit" + max_connections = 16 + + # The per-socket "max_requests" option does not exist. + + # + # The lifetime, in seconds, of a TCP connection. After + # this lifetime, the connection will be closed. + # + # Setting this to 0 means "forever". + lifetime = 0 + + # + # The idle timeout, in seconds, of a TCP connection. + # If no packets have been received over the connection for + # this time, the connection will be closed. + # + # Setting this to 0 means "no timeout". + # + # We STRONGLY RECOMMEND that you set an idle timeout. + # + idle_timeout = 30 + } + + # This is *exactly* the same configuration as used by the EAP-TLS + # module. It's OK for testing, but for production use it's a good + # idea to use different server certificates for EAP and for RADIUS + # transport. + # + # If you want only one TLS configuration for multiple sockets, + # then we suggest putting "tls { ...}" into radiusd.conf. + # The subsection below can then be changed into a reference: + # + # tls = ${tls} + # + # Which means "the tls sub-section is not here, but instead is in + # the top-level section called 'tls'". + # + # If you have multiple tls configurations, you can put them into + # sub-sections of a top-level "tls" section. There's no need to + # call them all "tls". You can then use: + # + # tls = ${tls.site1} + # + # to refer to the "site1" sub-section of the "tls" section. + # + tls { + private_key_password = whatever + private_key_file = ${certdir}/server.pem + + # Accept an expired Certificate Revocation List + # + # allow_expired_crl = no + + # If Private key & Certificate are located in + # the same file, then private_key_file & + # certificate_file must contain the same file + # name. + # + # If ca_file (below) is not used, then the + # certificate_file below MUST include not + # only the server certificate, but ALSO all + # of the CA certificates used to sign the + # server certificate. + certificate_file = ${certdir}/server.pem + + # Trusted Root CA list + # + # ALL of the CA's in this list will be trusted + # to issue client certificates for authentication. + # + # In general, you should use self-signed + # certificates for 802.1x (EAP) authentication. + # In that case, this CA file should contain + # *one* CA certificate. + # + # This parameter is used only for EAP-TLS, + # when you issue client certificates. If you do + # not use client certificates, and you do not want + # to permit EAP-TLS authentication, then delete + # this configuration item. + ca_file = ${cadir}/ca.pem + + # For DH cipher suites to work in OpenSSL < 1.1.0, + # you have to run OpenSSL to create the DH file + # first: + # + # openssl dhparam -out certs/dh 2048 + # + # For OpenSSL >= 1.1.0, just leave this commented + # out, and OpenSSL will do the right thing. + # +# dh_file = ${certdir}/dh + + # + # If your system doesn't have /dev/urandom, + # you will need to create this file, and + # periodically change its contents. + # + # For security reasons, FreeRADIUS doesn't + # write to files in its configuration + # directory. + # +# random_file = /dev/urandom + + # + # The default fragment size is 1K. + # However, it's possible to send much more data than + # that over a TCP connection. The upper limit is 64K. + # Setting the fragment size to more than 1K means that + # there are fewer round trips when setting up a TLS + # connection. But only if the certificates are large. + # + fragment_size = 8192 + + # include_length is a flag which is + # by default set to yes If set to + # yes, Total Length of the message is + # included in EVERY packet we send. + # If set to no, Total Length of the + # message is included ONLY in the + # First packet of a fragment series. + # + # include_length = yes + + # Check the Certificate Revocation List + # + # 1) Copy CA certificates and CRLs to same directory. + # 2) Execute 'c_rehash <CA certs&CRLs Directory>'. + # 'c_rehash' is OpenSSL's command. + # 3) uncomment the line below. + # 5) Restart radiusd + # check_crl = yes + ca_path = ${cadir} + + # OpenSSL does not reload contents of ca_path dir over time. + # That means that if check_crl is enabled and CRLs are loaded + # from ca_path dir, at some point CRLs will expire and + # RADIUSd will stop authenticating NASes. + # If ca_path_reload_interval is non-zero, it will force OpenSSL + # to reload all data from ca_path periodically + # + # Flush ca_path each hour + ca_path_reload_interval = 3600 + + # + # If check_cert_issuer is set, the value will + # be checked against the DN of the issuer in + # the client certificate. If the values do not + # match, the certificate verification will fail, + # rejecting the user. + # + # This check can be done more generally by checking + # the value of the TLS-Client-Cert-Issuer attribute. + # This check can be done via any mechanism you choose. + # + # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" + + # + # If check_cert_cn is set, the value will + # be xlat'ed and checked against the CN + # in the client certificate. If the values + # do not match, the certificate verification + # will fail rejecting the user. + # + # This check is done only if the previous + # "check_cert_issuer" is not set, or if + # the check succeeds. + # + # In 2.1.10 and later, this check can be done + # more generally by checking the value of the + # TLS-Client-Cert-Common-Name attribute. This check + # can be done via any mechanism you choose. + # + # check_cert_cn = %{User-Name} + # + # Set this option to specify the allowed + # TLS cipher suites. The format is listed + # in "man 1 ciphers". + cipher_list = "DEFAULT" + + # If enabled, OpenSSL will use server cipher list + # (possibly defined by cipher_list option above) + # for choosing right cipher suite rather than + # using client-specified list which is OpenSSl default + # behavior. Having it set to yes is a current best practice + # for TLS + cipher_server_preference = no + + # + # Older TLS versions are deprecated. But for RadSec, + # we CAN allow TLS 1.3. + # + tls_min_version = "1.2" + tls_max_version = "1.3" + + # + # Session resumption / fast reauthentication + # cache. + # + # The cache contains the following information: + # + # session Id - unique identifier, managed by SSL + # User-Name - from the Access-Accept + # Stripped-User-Name - from the Access-Request + # Cached-Session-Policy - from the Access-Accept + # + # The "Cached-Session-Policy" is the name of a + # policy which should be applied to the cached + # session. This policy can be used to assign + # VLANs, IP addresses, etc. It serves as a useful + # way to re-apply the policy from the original + # Access-Accept to the subsequent Access-Accept + # for the cached session. + # + # On session resumption, these attributes are + # copied from the cache, and placed into the + # reply list. + # + # You probably also want "use_tunneled_reply = yes" + # when using fast session resumption. + # + cache { + # + # Enable it. The default is "no". + # Deleting the entire "cache" subsection + # Also disables caching. + # + # + # The session cache requires the use + # of the "name" and "persist_dir" configuration items, below. + # + # The internal OpenSSL session cache has been permanently + # disabled. + # + # You can disallow resumption for a + # particular user by adding the following + # attribute to the control item list: + # + # Allow-Session-Resumption = No + # + # If "enable = no" below, you CANNOT + # enable resumption for just one user + # by setting the above attribute to "yes". + # + enable = no + + # + # Lifetime of the cached entries, in hours. + # The sessions will be deleted after this + # time. + # + lifetime = 24 # hours + + # + # Internal "name" of the session cache. + # Used to distinguish which TLS context + # sessions belong to. + # + # The server will generate a random value + # if unset. This will change across server + # restart so you MUST set the "name" if you + # want to persist sessions (see below). + # + # If you use IPv6, change the "ipaddr" below + # to "ipv6addr" + # + #name = "TLS ${..ipaddr} ${..port} ${..proto}" + + # + # Simple directory-based storage of sessions. + # Two files per session will be written, the SSL + # state and the cached VPs. This will persist session + # across server restarts. + # + # The server will need write perms, and the directory + # should be secured from anyone else. You might want + # a script to remove old files from here periodically: + # + # find ${logdir}/tlscache -mtime +2 -exec rm -f {} \; + # + # This feature REQUIRES "name" option be set above. + # + #persist_dir = "${logdir}/tlscache" + } + + # + # Require a client certificate. + # + require_client_cert = yes + + # + # As of version 2.1.10, client certificates can be + # validated via an external command. This allows + # dynamic CRLs or OCSP to be used. + # + # This configuration is commented out in the + # default configuration. Uncomment it, and configure + # the correct paths below to enable it. + # + verify { + # A temporary directory where the client + # certificates are stored. This directory + # MUST be owned by the UID of the server, + # and MUST not be accessible by any other + # users. When the server starts, it will do + # "chmod go-rwx" on the directory, for + # security reasons. The directory MUST + # exist when the server starts. + # + # You should also delete all of the files + # in the directory when the server starts. + # tmpdir = /tmp/radiusd + + # The command used to verify the client cert. + # We recommend using the OpenSSL command-line + # tool. + # + # The ${..ca_path} text is a reference to + # the ca_path variable defined above. + # + # The %{TLS-Client-Cert-Filename} is the name + # of the temporary file containing the cert + # in PEM format. This file is automatically + # deleted by the server when the command + # returns. + # client = "/path/to/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" + } + + # + # When the RadSec clients use SNI, the server will + # automatically choose the correct certificate from + # "realm_dir". See raddb/certs/realms/README.md for + # more information. + # + # Note that the default is to use the same set of + # realm certificates for both EAP and RadSec! If + # this is not what you want, you should use different + # subdirectories or each, e.g. ${certdir}/realms/radsec/, + # and ${certdir}/realms/eap/ + # + # realm_dir = ${certdir}/realms/ + } +} + +clients radsec { + client 127.0.0.1 { + ipaddr = 127.0.0.1 + + # + # Ensure that this client is TLS *only*. + # + proto = tls + + # + # TCP clients can have any shared secret. + # + # TLS clients MUST have the shared secret + # set to "radsec". Or, for "proto = tls", + # you can omit the secret, and it will + # automatically be set to "radsec". + # + secret = radsec + + # + # You can also use a "limit" section here. + # See raddb/clients.conf for examples. + # + # Note that BOTH limits are applied. You + # should therefore set the "listen" limits + # higher than the ones for each individual + # client. + # + } +} + +# +# When a request is proxied to a TLS-enabled home server, +# the TLS parameters are available via the expansion: +# +# %{proxy_listen: ... } +# +# The contents of the expansion are the same as described +# above with the %{listen: ... } expansion, and have similar +# meanings. "client" in this case is the proxy (this system) +# and "server" is the remote system (home server). +# +# Note that the %{proxy_listen: ... } parameters are available +# only AFTER the connection has been made to the home server. +# +home_server tls { + ipaddr = 127.0.0.1 + port = 2083 + + # type can be the same types as for the "listen" section/ + # e.g. auth, acct, auth+acct, coa + type = auth + secret = radsec + proto = tcp + status_check = none + + tls { + # + # Similarly to HTTP, the client can use Server Name + # Indication to inform the RadSec server as to which + # domain it is requesting. This selection allows + # multiple sites to exist at the same IP address. + # + # For example, an identity provider could host + # multiple sites, but present itself with one public + # IP address. If the RadSec clients do not use SNI, + # then they must be configured with the certificate + # of the identity provider. + # + # When SNI is used, the clients can be configured + # with the certificate of the hosted system that + # they're connecting to. This ability means that + # there is no need to change certificates when + # changing providers. In addition, there is no need + # to change the configuration of all RadSec clients + # when the hosting system changes its certifiates. + # Because the hosting system certificates are never used. + # + # Instead, each hosted company is responsible for its + # own certificates, and for its own clients. + # + # SNI also permits the use of a load balancer such as + # haproxy. That load balancer can terminate the TLS + # connection, and then use SNI to route the + # underlying RADIUS TCP traffic to a particular host. + # + # Note that "hostname" here is only for SNI, and is NOT + # the hostname or IP address we connect to. For that, + # see "ipaddr", above. + # + # hostname = "example.com" + + private_key_password = whatever + private_key_file = ${certdir}/client.pem + + # If Private key & Certificate are located in + # the same file, then private_key_file & + # certificate_file must contain the same file + # name. + # + # If ca_file (below) is not used, then the + # certificate_file below MUST include not + # only the server certificate, but ALSO all + # of the CA certificates used to sign the + # server certificate. + certificate_file = ${certdir}/client.pem + + # Trusted Root CA list + # + # ALL of the CA's in this list will be trusted + # to issue client certificates for authentication. + # + # In general, you should use self-signed + # certificates for 802.1x (EAP) authentication. + # In that case, this CA file should contain + # *one* CA certificate. + # + # This parameter is used only for EAP-TLS, + # when you issue client certificates. If you do + # not use client certificates, and you do not want + # to permit EAP-TLS authentication, then delete + # this configuration item. + ca_file = ${cadir}/ca.pem + + # + # Before version 3.2.1, outbound RadSec connections + # would put the home server certificate into the + # TLS-Client-Cert* attributes. Set this configuration + # item to "yes" in order to have the home server + # certificates placed into the "TLS-Cert-*" attributes. + # +# fix_cert_order = yes + + # + # For TLS-PSK, the key should be specified + # dynamically, instead of using a hard-coded + # psk_identity and psk_hexphrase. + # + # The input to the dynamic expansion will be the PSK + # identity supplied by the client, in the + # TLS-PSK-Identity attribute. The output of the + # expansion should be a hex string, of no more than + # 512 characters. The string should not be prefixed + # with "0x". e.g. "abcdef" is OK. "0xabcdef" is not. + # + # psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}" + + # + # For DH cipher suites to work, you have to + # run OpenSSL to create the DH file first: + # + # openssl dhparam -out certs/dh 1024 + # +# dh_file = ${certdir}/dh +# random_file = /dev/urandom + + # + # The default fragment size is 1K. + # However, TLS can send 64K of data at once. + # It can be useful to set it higher. + # + fragment_size = 8192 + + # include_length is a flag which is + # by default set to yes If set to + # yes, Total Length of the message is + # included in EVERY packet we send. + # If set to no, Total Length of the + # message is included ONLY in the + # First packet of a fragment series. + # + # include_length = yes + + # Check the Certificate Revocation List + # + # 1) Copy CA certificates and CRLs to same directory. + # 2) Execute 'c_rehash <CA certs&CRLs Directory>'. + # 'c_rehash' is OpenSSL's command. + # 3) uncomment the line below. + # 5) Restart radiusd + # check_crl = yes + ca_path = ${cadir} + + # + # If check_cert_issuer is set, the value will + # be checked against the DN of the issuer in + # the client certificate. If the values do not + # match, the certificate verification will fail, + # rejecting the user. + # + # In 2.1.10 and later, this check can be done + # more generally by checking the value of the + # TLS-Client-Cert-Issuer attribute. This check + # can be done via any mechanism you choose. + # + # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" + + # + # If check_cert_cn is set, the value will + # be xlat'ed and checked against the CN + # in the client certificate. If the values + # do not match, the certificate verification + # will fail rejecting the user. + # + # This check is done only if the previous + # "check_cert_issuer" is not set, or if + # the check succeeds. + # + # In 2.1.10 and later, this check can be done + # more generally by checking the value of the + # TLS-Client-Cert-Common-Name attribute. This check + # can be done via any mechanism you choose. + # + # check_cert_cn = %{User-Name} + # + # Set this option to specify the allowed + # TLS cipher suites. The format is listed + # in "man 1 ciphers". + cipher_list = "DEFAULT" + + # + # Connection timeout for outgoing TLS connections. + # Values are 1..30. + # + connect_timeout = 30 + } +} + +home_server_pool tls { + type = fail-over + home_server = tls +} + +realm tls { + auth_pool = tls +} diff --git a/raddb/sites-available/tls-cache b/raddb/sites-available/tls-cache new file mode 100644 index 0000000..e6451c5 --- /dev/null +++ b/raddb/sites-available/tls-cache @@ -0,0 +1,144 @@ +# -*- text -*- +###################################################################### +# +# This is a virtual server which handles TLS session caching. +# +# $Id$ +# +###################################################################### +# +# In mods-enabled/eap, "cache" subsection +# +# comment out +# +# persist_dir +# +# add +# +# virtual_server = tls-cache +# +# and set +# +# enable = yes +# +# In order to enable caching. +# + +# +# This virtual server SHOULD NOT have any "listen" sections. +# +# +# All of the cache sections key off of &request:TLS-Session-Id +# +# The cache sections also run the "post-auth" section of any +# module which they use. +# +# These sections do not need to return any specific codes (e.g. ok / +# fail /etc.). The cache functionality depends only on which +# attributes are saved / loaded. +# +# For example, if the "cache save" process fails, there is nothing +# that the server can do about that. The users authentication +# session will still succeed. The only difference from a successful +# "cache save" is that the user will be unable to resume their +# session. Instead, they will need to do a full re-authentication +# process. +# +# Similarly for "cache load". If the session (and/or) the VPs are +# not loaded from the cache, then the user will do a full +# re-authentication. +# +# Whilst any store can be used for tls session caching, whatever is +# chosen should be faster than performing a full re-authentication +server tls-cache { + +cache clear { + # clear the cache entry by keying off of &request:TLS-Session-Id + + # An example using redis +# "%{redis:DEL %{request:TLS-Session-ID}}" + + # An example using SQL +# "%{sql:DELETE FROM tls_cache WHERE session_id = '%{request:TLS-Session-ID}'}" +} + +cache save { + # use the key &request:TLS-Session-ID + # save &session-state:TLS-Session-Data + # save &reply:... + + # The &reply: list is initialized to the attributes + # which should be saved. This includes attributes + # mentioned in the "store" subsection of the "cache" + # section configuration. This is the same set of + # attributes which is saved when the 'persist_dir' + # configuration is used. + # + # Note the "store" subsection will only copy matching + # attributes from the &reply: list at the time that + # eap authentication succeeds. + # + # Other attributes can be saved by referring to them + # e.g. &outer.request:... + + # An example using redis +# update { +# &Tmp-String-0 := "%{session-state:TLS-Session-Data}|%{escape:%{reply:Tunnel-Private-Group-ID}}" +# } +# "%{redis: SET %{request:TLS-Session-ID} \"%{Tmp-String-0}\" EX 86400}" + + # An example using SQL +# "%{sql: INSERT INTO tls_cache (session_id, session_data, vlan, expiry) VALUES ('%{request:TLS-Session-ID}', '%{session-state:TLS-Session-Data}', '%{escape:%{reply:Tunnel-Private-Group-ID}}', DATE_ADD(NOW(), INTERVAL 24 HOUR))}" +} + +cache load { + # use the key &request:TLS-Session-ID + # load &session-state:TLS-Session-Data + # load &reply:... + + # Attributes returned in &reply: which are listed + # in the "store" subsection of the "cache" section + # configuration will be copied to &session-state: + # + # Certificate attributes returned in &reply: are added + # to &request: if they do not already exist and if + # EAP-Type is returned it is added to &control: + # + # Any other attributes returned are added to &reply: + + # An example using redis +# update { +# &Tmp-String-0 := "%{redis:GET %{request:TLS-Session-ID}}" +# } +# if (!&Tmp-String-0 || &Tmp-String-0 !~ /^([^|]+)\|([^|]+)$/) { +# return +# } +# update { +# &session-state:TLS-Session-Data := "%{1}" +# &reply:Tunnel-Private-Group-ID := "%{unescape:%{2}}" +# } + + # An example using SQL +# update { +# &Tmp-String-0 := "%{sql:SELECT CONCAT(session_data, '|', vlan) FROM session_cache WHERE session_id = '%{request:TLS-Session-ID}'}" +# } +# if (!&Tmp-String-0 || &Tmp-String-0 !~ /^([^|]+)\|([^|]+)$/) { +# return +# } +# update { +# &session-state:TLS-Session-Data := "%{1}" +# &reply:Tunnel-Private-Group-ID := "%{unescape:%{2}}" +# } +} + +cache refresh { + # refresh the cache entry by keying off of &request:TLS-Session-ID + + # An example using redis +# "%{redis:EXPIRE %{request:TLS-Session-ID} 86400}" + + # An example using SQL +# "%{sql:UPDATE tls_cache SET expiry = DATE_ADD(NOW(), INTERVAL 24 HOUR) WHERE session_id = '%{request:TLS-Session-ID}'}" +} + +} diff --git a/raddb/sites-available/totp b/raddb/sites-available/totp new file mode 100644 index 0000000..e42bf05 --- /dev/null +++ b/raddb/sites-available/totp @@ -0,0 +1,85 @@ +###################################################################### +# +# $Id$ +# +###################################################################### +# +# Simple server to do TOTP and not much else. +# +server totp { +authorize { + # + # TOTP only works for PAP + # + if (!&User-Password) { + reject + } + + # + # The 6-digit TOTP password should be at the end of the + # User-Password attribute. It can be at the beginning or at + # the end, it doesn't really make any difference. Just + # update the regular expression for whatever you want. + # + # If the password doesn't have 6 digits at the end, reject. + # + if (User-Password !~ /^(.*)([0-9]{6})$/) { + reject + } + + # + # Separate the two fields + # + update request { + User-Password := "%{1}" + TOTP-Password := "%{2}" + } + + # + # Get the users' real password and authorization credentials + # from somewhere, such as a database. This should also set + # + # &control:TOTP-Secret + # + -ldap + -sql + + # + # As an example, fake out the TOTP secret + # + # The value should be the base-32 version of the TOTP secret. + # + # Note that the TOTP secret is effectively a password, and + # should be kept secret! At this time, there is no way to + # "hide" or "encrypt" the TOTP secret for a user. Even if it + # was encrypted, the server would still need a key to decrypt + # it. So encrypying this field does not offer much benefit. + # + if (&User-Name == "bob") { + &control:TOTP-Secret := 12345678901234567890 + } + + # + # Verify the 6-digit TOTP password. If the module does not + # return "ok", then the TOTP password is wrong. + # + totp.authenticate + if (!ok) { + reject + } + + # + # Set Auth-Type = PAP + # + pap +} + +authenticate { + # + # Check the User-Password against whatever we found in LDAP + # or SQL. + # + pap +} + +} diff --git a/raddb/sites-available/virtual.example.com b/raddb/sites-available/virtual.example.com new file mode 100644 index 0000000..3c4aea7 --- /dev/null +++ b/raddb/sites-available/virtual.example.com @@ -0,0 +1,32 @@ +# -*- text -*- +###################################################################### +# +# Sample virtual server for internally proxied requests. +# +# See the "realm virtual.example.com" example in "proxy.conf". +# +# $Id$ +# +###################################################################### + +# +# You will want to edit this to your local needs. We suggest copying +# the text from the "default" file here, and then editing the text. +# That way, any changes to the "default" file will not affect this +# virtual server, and vice-versa. +# +# When this virtual server receives the request, the original +# attributes can be accessed as "outer.request", "outer.control", etc. +# See "man unlang" for more details. +# +server virtual.example.com { +authorize { + # insert policies here +} + +authenticate { + # insert policies here +} + +# etc. +} diff --git a/raddb/sites-available/vmps b/raddb/sites-available/vmps new file mode 100644 index 0000000..c5c5078 --- /dev/null +++ b/raddb/sites-available/vmps @@ -0,0 +1,98 @@ +# -*- text -*- +###################################################################### +# +# As of version 2.0.0, the server also supports the VMPS +# protocol. +# +# $Id$ +# +###################################################################### + +server vmps { + listen { + # VMPS sockets only support IPv4 addresses. + ipaddr = * + + # Port on which to listen. + # Allowed values are: + # integer port number + # 1589 is the default VMPS port. + port = 1589 + + # Type of packets to listen for. Here, it is VMPS. + type = vmps + + # Some systems support binding to an interface, in addition + # to the IP address. This feature isn't strictly necessary, + # but for sites with many IP addresses on one interface, + # it's useful to say "listen on all addresses for + # eth0". + # + # If your system does not support this feature, you will + # get an error if you try to use it. + # + # interface = eth0 + } + + # If you have switches that are allowed to send VMPS, but NOT + # RADIUS packets, then list them here as "client" sections. + # + # Note that for compatibility with RADIUS, you still have to + # list a "secret" for each client, though that secret will not + # be used for anything. + + + # And the REAL contents. This section is just like the + # "post-auth" section of radiusd.conf. In fact, it calls the + # "post-auth" component of the modules that are listed here. + # But it's called "vmps" to highlight that it's for VMPS. + # + vmps { + # + # Some requests may not have a MAC address. Try to + # create one using other attributes. + if (!&VMPS-Mac) { + if (&VMPS-Ethernet-Frame =~ /0x.{12}(..)(..)(..)(..)(..)(..).*/) { + update request { + &VMPS-Mac = "%{1}:%{2}:%{3}:%{4}:%{5}:%{6}" + } + } + else { + update request { + &VMPS-Mac = &VMPS-Cookie + } + } + } + + # Do a simple mapping of MAC to VLAN. + # + # See radiusd.conf for the definition of the "mac2vlan" + # module. + # + #mac2vlan + + # required VMPS reply attributes + update reply { + &VMPS-Packet-Type = VMPS-Join-Response + &VMPS-Cookie = &VMPS-Mac + + &VMPS-VLAN-Name = "please_use_real_vlan_here" + + # + # If you have VLAN's in a database, you can select + # the VLAN name based on the MAC address. + # + #&VMPS-VLAN-Name = "%{sql:select ... where mac='%{VMPS-Mac}'}" + } + + # correct reply packet type for reconfirmation requests + # + if (&VMPS-Packet-Type == VMPS-Reconfirm-Request){ + update reply { + &VMPS-Packet-Type := VMPS-Reconfirm-Response + } + } + } + + # Proxying of VMPS requests is NOT supported. +} |