Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
vendors:cisco:routers:radius [2026/09/17 14:10] gerardorourkevendors:cisco:routers:radius [2026/09/21 10:27] (current) – [File: /etc/raddb/clients.conf] gerardorourke
Line 1: Line 1:
 ====== Radius Start Stop Events for VoIP Calls ======= ====== Radius Start Stop Events for VoIP Calls =======
 +
 +===== Cisco CUBE Config =====
  
 <code> <code>
Line 15: Line 17:
 gw-accounting aaa gw-accounting aaa
  method CUBE-CDR  method CUBE-CDR
 + acct-template callhistory-detail ! This sends ALL VoIP records to the Radius Server
 ! !
 +voice class aaa 1000
 + accounting suppress 
 + ! note this is used in the below dial-peer 200 - so this does NOT produce an accounting record - so we don't get one per leg.
 +!
 +dial-peer voice 100 voip
 + description Inbound/Outbound Webex Calling
 + max-conn 250
 + destination-pattern BAD.BAD
 + session protocol sipv2
 + session target sip-server
 + destination dpg 200
 + incoming uri request 100
 + voice-class codec 100
 + voice-class stun-usage 100
 + no voice-class sip localhost
 + voice-class sip tenant 100
 + dtmf-relay rtp-nte
 + srtp
 + no vad
 +!
 +dial-peer voice 200 voip
 + description Inbound/Outbound IP PSTN trunk
 + destination-pattern BAD.BAD
 + session protocol sipv2
 + session target ipv4:192.168.80.13
 + destination dpg 100
 + incoming uri via 200
 + voice-class aaa 1000
 + voice-class codec 100
 + voice-class sip asserted-id pai
 + voice-class sip bind control source-interface GigabitEthernet1
 + voice-class sip bind media source-interface GigabitEthernet1
 + dtmf-relay rtp-nte
 + no vad
 +!
 +
 </code> </code>
  
  
 +===== Radius Config =====
 +
 +====File: /etc/raddb/clients.conf====
 +
 +<code>
 +client cisco-router {
 +        ipaddr          = 10.55.1.60/24
 +        secret          = mySuperSecret555!
 +}
 +</code>
 +
 +
 +====File: /etc/raddb/sites-available/default - Accounting Section====
 +
 +<code>
 +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
 +
 +        # If h323-setup-time exists THEN perform the regex etc (GOR)
 +
 +        if (&h323-setup-time && &h323-setup-time =~ /^h323-setup-time=(.*)$/) {
 +                update request {
 +                        &Tmp-String-0 := "%{1}"
 +                }
 +        }
 +
 +        if (&h323-connect-time && &h323-connect-time =~ /^h323-connect-time=(.*)$/) {
 +                update request {
 +                        &Tmp-String-1 := "%{1}"
 +                }
 +        }
 +
 +        if (&h323-call-origin && &h323-call-origin =~ /^h323-call-origin=(.*)$/) {
 +                update request {
 +                        &Tmp-String-2 := "%{1}"
 +                }
 +        }
 +
 +        if (&h323-disconnect-time && &h323-disconnect-time =~ /^h323-disconnect-time=(.*)$/) {
 +                update request {
 +                        &Tmp-String-3 := "%{1}"
 +                }
 +        }
 +
 +        if (&h323-disconnect-cause && &h323-disconnect-cause =~ /^h323-disconnect-cause=(.*)$/) {
 +                update request {
 +                        &Tmp-String-4 := "%{1}"
 +                }
 +        }
 +
 +        if (&h323-conf-id && &h323-conf-id =~ /^h323-conf-id=([A-Fa-f0-9]+) ([A-Fa-f0-9]+) ([A-Fa-f0-9]+) ([A-Fa-f0-9]+)$/) {
 +                update request {
 +                        &Tmp-String-5 := "%{1}-%{2}-%{3}-%{4}"
 +                }
 +        }
 +
 + # REST enabled (GOR)
 +        rest
 +
 +#       daily
 +
 +        #  Update the wtmp file
 +        #
 +        #  If you don't use "radlast" (becoming obsolete and no longer
 +        #  available on all systems), 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 {
 +#
 +#       }
 +}
 +</code>
 +
 +
 +==== /etc/raddb/mods-available/rest ====
 +
 +<code>
 +rest {
 +        #
 +        #  This subsection configures the tls related items
 +        #  that control how FreeRADIUS connects to a HTTPS
 +        #  server.
 +        #
 +        tls {
 +                #  Certificate Authorities:
 +                #  "ca_file" (libcurl option CURLOPT_ISSUERCERT).
 +                #    File containing a single CA, which is the issuer of the server
 +                #    certificate.
 +                #  "ca_info_file" (libcurl option CURLOPT_CAINFO).
 +                #    File containing a bundle of certificates, which allow to handle
 +                #    certificate chain validation.
 +                #  "ca_path" (libcurl option CURLOPT_CAPATH).
 +                #    Directory holding CA certificates to verify the peer with.
 +#               ca_file = ${certdir}/cacert.pem
 +#               ca_info_file = ${certdir}/cacert_bundle.pem
 +#               ca_path = ${certdir}
 +
 +#               certificate_file        = /path/to/radius.crt
 +#               private_key_file        = /path/to/radius.key
 +#               private_key_password    = "supersecret"
 +#               random_file             = /dev/urandom
 +
 +                #  Server certificate verification requirements.  Can be:
 +                #    "no"  (don't even bother trying)
 +                #    "yes" (verify the cert was issued by one of the
 +                #          trusted CAs)
 +                #
 +                #  The default is "yes"
 +#               check_cert = yes
 +
 +                #  Server certificate CN verification requirements.  Can be:
 +                #    "no"  (don't even bother trying)
 +                #    "yes" (verify the CN in the certificate matches the host
 +                #          in the URI)
 +                #
 +                #  The default is "yes"
 +#               check_cert_cn = yes
 +        }
 +
 +        # rlm_rest will open a connection to the server specified in connect_uri
 +        # to populate the connection cache, ready for the first request.
 +        # The server will not start if the server specified is unreachable.
 +        #
 +        # If you wish to disable this pre-caching and reachability check,
 +        # comment out the configuration item below.
 +        #
 +        # connect_uri = "http://127.0.0.1"
 +        connect_uri = "http://10.55.1.51"
 +
 +        #
 +        # When set, connects to the server over a UNIX socket which may be
 +        # helpful for those with (pseudo)security constraints that make it
 +        # easier to use an UNIX socket than explain to an auditor the use of
 +        # non-TLS HTTP localhost connections.
 +        #
 +        # NOTE: This is not allowed to be an xlat as it can lead to security issues.
 +        #
 +#       connect_uri_socket = "/run/myprogram.sock"
 +
 +        #
 +        # When set, connect_uri_socket is an abstract UNIX socket
 +        #
 +#       connect_uri_socket_abstract = "no"
 +
 +        #
 +        #  How long before new connection attempts timeout, defaults to 4.0 seconds.
 +        #
 +#       connect_timeout = 4.0
 +
 +        #
 +        # Specify HTTP protocol version to use. one of '1.0', '1.1', '2.0', '2.0+auto',
 +        # '2.0+tls' or 'default'. (libcurl option CURLOPT_HTTP_VERSION)
 +        #
 +#       http_negotiation = 1.1
 +
 +        #
 +        #  The following config items can be used in each of the sections.
 +        #  The sections themselves reflect the sections in the server.
 +        #  For example if you list rest in the authorize section of a virtual server,
 +        #  the settings from the authorize section here will be used.
 +        #
 +        #  The following config items may be listed in any of the sections:
 +        #    uri          - to send the request to.
 +        #    method       - HTTP method to use, one of 'get', 'post', 'put', 'patch',
 +        #                   'delete' or any custom HTTP method.
 +        #    body         - The format of the HTTP body sent to the remote server.
 +        #                   May be 'none', 'post' or 'json', defaults to 'none'.
 +        #    attr_num     - If true, the attribute number is supplied for each attribute.
 +        #                   Defaults to false.
 +        #    raw_value    - If true, enumerated attribute values are provided as numeric
 +        #                   values. Defaults to false.
 +        #    data         - Send custom freeform data in the HTTP body. Content-type
 +        #                   may be specified with 'body'. Will be expanded.
 +        #                   Values from expansion will not be escaped, this should be
 +        #                   done using the appropriate xlat method e.g. %{urlencode:<attr>}.
 +        #    force_to     - Force the response to be decoded with this decoder.
 +        #                   May be 'plain' (creates reply:REST-HTTP-Body), 'post'
 +        #                   or 'json'.
 +        #    tls          - TLS settings for HTTPS.
 +        #    auth         - HTTP auth method to use, one of 'none', 'srp', 'basic',
 +        #                   'digest', 'digest-ie', 'gss-negotiate', 'ntlm',
 +        #                   'ntlm-winbind', 'any', 'safe'. defaults to 'none'.
 +        #    username     - User to authenticate as, will be expanded.
 +        #    password     - Password to use for authentication, will be expanded.
 +        #    require_auth - Require HTTP authentication.
 +        #    timeout      - HTTP request timeout in seconds, defaults to 4.0.
 +        #    chunk        - Chunk size to use. If set, HTTP chunked encoding is used to
 +        #                   send data to the REST server. Make sure that this is large
 +        #                   enough to fit your largest attribute value's text
 +        #                   representation.
 +        #                   A number like 8192 is good.
 +        #
 +        #  Additional HTTP headers may be specified with control:REST-HTTP-Header.
 +        #  The values of those attributes should be in the format:
 +        #
 +        #       control:REST-HTTP-Header := "<HTTP attribute>: <value>"
 +        #
 +        #  You should set this attribute before calling the rest module,
 +        #  via something like the following example.  Note that you MUST
 +        #  update the HTTP attribute and key value to whatever is needed on
 +        #  your local system.  The values given in this example are likely
 +        #  to not work for your system.
 +        #
 +        #       update control {
 +        #               &REST-HTTP-Header := "x-api-key: abcdefsupersecret"
 +        #       }
 +        #       rest
 +        #
 +        #  The control:REST-HTTP-Header attributes will be consumed
 +        #  (i.e. deleted) after each call to the rest module, and each
 +        #  %{rest:} expansion.  This is so that headers from one REST
 +        #  call do not affect headers from a different REST call.
 +        #
 +        #  Body encodings are the same for requests and responses
 +        #
 +        #  POST - All attributes and values are urlencoded
 +        #  [outer.][<list>:]<attribute0>=<value0>&[outer.][<list>:]<attributeN>=<valueN>
 +        #
 +        #  JSON - All attributes and values are escaped according to the JSON specification
 +        #  - attribute  Name of the attribute.
 +        #  - attr_num   Number of the attribute. Only available if the configuration item
 +        #               'attr_num' is enabled.
 +        #  - type       Type of the attribute (e.g. "integer", "string", "ipaddr", "octets", ...).
 +        #  - value      Attribute value, for enumerated attributes the human readable value is
 +        #               provided and not the numeric value (Depends on the 'raw_value' config item).
 +        #  {
 +        #      "<attribute0>":{
 +        #          "attr_num":<attr_num0>,
 +        #          "type":"<type0>",
 +        #          "value":[<value0>,<value1>,<valueN>]
 +        #      },
 +        #      "<attribute1>":{
 +        #          "attr_num":<attr_num1>,
 +        #          "type":"<type1>",
 +        #          "value":[...]
 +        #      },
 +        #      "<attributeN>":{
 +        #          "attr_num":<attr_numN>,
 +        #          "type":"<typeN>",
 +        #          "value":[...]
 +        #      },
 +        #  }
 +        #
 +        #  The response format adds three optional fields:
 +        #  - do_xlat    If true, any values will be xlat expanded. Defaults to true.
 +        #  - is_json    If true, any nested JSON data will be copied to the attribute
 +        #               in string form. Defaults to true.
 +        #  - op         Controls how the attribute is inserted into the target list.
 +        #               Defaults to ':='. To create multiple attributes from multiple
 +        #               values, this should be set to '+=', otherwise only the last
 +        #               value will be used, and it will be assigned to a single
 +        #               attribute.
 +        #  {
 +        #      "<attribute0>":{
 +        #          "is_json":<bool>,
 +        #          "do_xlat":<bool>,
 +        #          "op":"<operator>",
 +        #          "value":[<value0>,<value1>,<valueN>]
 +        #      },
 +        #      "<attribute1>":"value",
 +        #      "<attributeN>":{
 +        #          "value":[<value0>,<value1>,<valueN>],
 +        #          "op":"+="
 +        #      }
 +        #  }
 +
 +        #
 +        #  Module return codes are determined by HTTP response codes. These vary depending on the
 +        #  section.
 +        #
 +        #  If the body is processed and found to be malformed or unsupported fail will be returned.
 +        #  If the body is processed and found to contain attribute updated will be returned,
 +        #  except in the case of a 401 code.
 +        #
 +
 +        #  Authorize/Authenticate
 +        #
 +        #  Code   Meaning       Process body  Module code
 +        #  404    not found     no            notfound
 +        #  410    gone          no            notfound
 +        #  403    forbidden     no            userlock
 +        #  401    unauthorized  yes           reject
 +        #  204    no content    no            ok
 +        #  2xx    successful    yes           ok/updated
 +        #  5xx    server error  no            fail
 +        #  xxx    -             no            invalid
 +        #
 +        #  The status code is held in %{reply:REST-HTTP-Status-Code}.
 +        #
 +        authorize {
 +                uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=authorize"
 +                method = 'get'
 +                tls = ${..tls}
 +        }
 +        authenticate {
 +                uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=authenticate"
 +                method = 'get'
 +                tls = ${..tls}
 +
 +                #
 +                #  Note that you CANNOT set 'username' or 'password'
 +                #  here.  When doing user authentication, the module
 +                #  uses the User-Name and User-Password.
 +                #
 +        }
 +
 +        #  Preacct/Accounting/Post-auth/Pre-Proxy/Post-Proxy
 +        #
 +        #  Code   Meaning       Process body  Module code
 +        #  204    no content    no            ok
 +        #  2xx    successful    yes           ok/updated
 +        #  5xx    server error  no            fail
 +        #  xxx    -             no            invalid
 +
 +        # GOR - this was the default setting for uri in accounting before I edited it.
 +        # uri = "${..connect_uri}/user/%{User-Name}/sessions/%{Acct-Unique-Session-ID}?action=accounting"
 +
 +        # initial data line config below - but then updated to use the tmp / cleaned up versions
 +        # data = '{"Acct-Status-Type": "%{Acct-Status-Type}","Called-Station-Id": "%{Called-Station-Id}","h323-setup-time": "%{h323-setup-time}","h323-connect-time": "%{h323-connect-time}","h323-call-origin": "%{h323-call-orig
 +in}","h323-disconnect-time": "%{h323-disconnect-time}","h323-disconnect-cause": "%{h323-disconnect-cause}"}'
 +
 +        preacct {
 +                uri = "${..connect_uri}/user/%{User-Name}/sessions/%{Acct-Unique-Session-ID}?action=preacct"
 +                method = 'post'
 +                tls = ${..tls}
 +        }
 +        accounting {
 +                uri = "${..connect_uri}/api/test/always204.php"
 +                method = 'post'
 +                body = 'json'
 +                data = '{"status":"%{Acct-Status-Type}","session_id":"%{Acct-Session-Id}","conf_id":"%{Tmp-String-5}","called_number":"%{Called-Station-Id}","setup_time":"%{Tmp-String-0}","connect_time":"%{Tmp-String-1}","call
 +_origin":"%{Tmp-String-2}","disconnect_time":"%{Tmp-String-3}","disconnect_cause":"%{Tmp-String-4}"}'
 +                tls = ${..tls}
 +        }
 +        post-auth {
 +                uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=post-auth"
 +                method = 'post'
 +                tls = ${..tls}
 +        }
 +        pre-proxy {
 +                uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=pre-proxy"
 +                method = 'post'
 +                tls = ${..tls}
 +        }
 +        post-proxy {
 +                uri = "${..connect_uri}/user/%{User-Name}/mac/%{Called-Station-ID}?action=post-proxy"
 +                method = 'post'
 +                tls = ${..tls}
 +        }
 +
 +        #  Options for calling rest xlats
 +        #  uri and method will be derived from the string provided to the xlat
 +        xlat {
 +                #
 +                #  The whole string passed to a REST xlat is URI encoded.
 +                #  With body_uri_encode = yes, any body data will remain encoded.
 +                #  With body_uri_encode = no, the body data will be decoded and sent as provided.
 +                #
 +                body_uri_encode = yes
 +                tls = ${..tls}
 +        }
 +
 +        #
 +        #  The connection pool is used to pool outgoing connections.
 +        #
 +        pool {
 +                #  Connections to create during module instantiation.
 +                #  If the server cannot create specified number of
 +                #  connections during instantiation it will exit.
 +                #  Set to 0 to allow the server to start without the
 +                #  web service being available.
 +                start = ${thread[pool].start_servers}
 +
 +                #  Minimum number of connections to keep open
 +                min = ${thread[pool].min_spare_servers}
 +
 +                #  Maximum number of connections
 +                #
 +                #  If these connections are all in use and a new one
 +                #  is requested, the request will NOT get a connection.
 +                #
 +                #  Setting 'max' to LESS than the number of threads means
 +                #  that some threads may starve, and you will see errors
 +                #  like 'No connections available and at max connection limit'
 +                #
 +                #  Setting 'max' to MORE than the number of threads means
 +                #  that there are more connections than necessary.
 +                max = ${thread[pool].max_servers}
 +
 +                #  Spare connections to be left idle
 +                #
 +                #  NOTE: Idle connections WILL be closed if "idle_timeout"
 +                #  is set.  This should be less than or equal to "max" above.
 +                spare = ${thread[pool].max_spare_servers}
 +
 +                #  Number of uses before the connection is closed
 +                #
 +                # 0 means "infinite"
 +                uses = 0
 +
 +                #  The number of seconds to wait after the server tries
 +                #  to open a connection, and fails.  During this time,
 +                #  no new connections will be opened.
 +                retry_delay = 30
 +
 +                #  The lifetime (in seconds) of the connection
 +                lifetime = 0
 +
 +                #  idle timeout (in seconds).  A connection which is
 +                #  unused for this length of time will be closed.
 +                idle_timeout = 60
 +
 +                #  NOTE: All configuration settings are enforced.  If a
 +                #  connection is closed because of "idle_timeout",
 +                #  "uses", or "lifetime", then the total number of
 +                #  connections MAY fall below "min" When that
 +                #  happens, it will open a new connection.  It will
 +                #  also log a WARNING message.
 +                #
 +                #  The solution is to either lower the "min" connections,
 +                #  or increase lifetime/idle_timeout.
 +        }
 +}
 +</code>
 +
 +==== Example of How to make Rest Requests conditional ====
 +<code>
 +if (&Called-Station-Id =~ /^\+3531/) {
 +        rest
 +}
 +else {
 +        noop
 +}
 +</code>
 +
 +
 +
 +
 +===== Useful Commands =====
 +
 +<code>
 +# Check config (before restarting) 
 +sudo radiusd -XC
 +
 +#Restart
 +systemctl restart radiusd
 +</code>
 +
 +===== Lock it down =====
 +By default we have the default and inner-tunnel symlinks in the /etc/raddb/sites-enabled/inner-tunnel
 +
 +But the default should be replaced with a dedicated simple config 
 +
 +Remove the two default symlink configs from the enabled sites directory
 +<code>
 +sudo rm /etc/raddb/sites-enabled/inner-tunnel
 +sudo rm /etc/raddb/sites-enabled/default
 +</code>
 +
 +  * Create your dedicated config just for Cisco CUBEs - /etc/raddb/sites-available/cube-accounting
 +
 +Example:
 +<code>
 +server cube-accounting {
 +        listen {
 +                type = acct
 +                ipaddr = *
 +                port = 1813
 +                proto = udp
 +        }
 +
 +        recv Accounting-Request {
 +                accounting
 +        }
 +
 +        accounting {
 +                detail
 +
 +                # Your existing cleanup blocks...
 +
 +                if (&h323-conf-id && &h323-conf-id =~ /^h323-conf-id=([A-Fa-f0-9]+) ([A-Fa-f0-9]+) ([A-Fa-f0-9]+) ([A-Fa-f0-9]+)$/) {
 +                        update request {
 +                                &Tmp-String-5 := "%{1}-%{2}-%{3}-%{4}"
 +                        }
 +                }
 +
 +                if (&Called-Station-Id =~ /^\+3531/) {
 +                        rest
 +                }
 +        }
 +}
 +</code>
 +
 +  * Create your symlink
 +      * <code>sudo ln -s /etc/raddb/sites-available/cube-accounting /etc/raddb/sites-enabled/cube-accounting</code>
  
  • vendors/cisco/routers/radius.1789650647.txt.gz
  • Last modified: 2026/09/17 14:10
  • by gerardorourke