summaryrefslogtreecommitdiffstats
path: root/raddb/sites-available
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--raddb/sites-available/README333
-rw-r--r--raddb/sites-available/abfab-tls118
-rw-r--r--raddb/sites-available/abfab-tr-idp198
-rw-r--r--raddb/sites-available/aws-nlb46
-rw-r--r--raddb/sites-available/buffered-sql161
-rw-r--r--raddb/sites-available/challenge123
-rw-r--r--raddb/sites-available/channel_bindings17
-rw-r--r--raddb/sites-available/check-eap-tls135
-rw-r--r--raddb/sites-available/coa49
-rw-r--r--raddb/sites-available/coa-relay331
-rw-r--r--raddb/sites-available/control-socket92
-rw-r--r--raddb/sites-available/copy-acct-to-home-server202
-rw-r--r--raddb/sites-available/decoupled-accounting139
-rw-r--r--raddb/sites-available/default1153
-rw-r--r--raddb/sites-available/dhcp584
-rw-r--r--raddb/sites-available/dhcp.relay44
-rw-r--r--raddb/sites-available/dynamic-clients222
-rw-r--r--raddb/sites-available/example122
-rw-r--r--raddb/sites-available/google-ldap-auth225
-rw-r--r--raddb/sites-available/inner-tunnel438
-rw-r--r--raddb/sites-available/originate-coa185
-rw-r--r--raddb/sites-available/proxy-inner-tunnel47
-rw-r--r--raddb/sites-available/resource-check140
-rw-r--r--raddb/sites-available/robust-proxy-accounting167
-rw-r--r--raddb/sites-available/soh34
-rw-r--r--raddb/sites-available/status127
-rw-r--r--raddb/sites-available/tls696
-rw-r--r--raddb/sites-available/tls-cache144
-rw-r--r--raddb/sites-available/totp85
-rw-r--r--raddb/sites-available/virtual.example.com32
-rw-r--r--raddb/sites-available/vmps98
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.
+}