diff options
Diffstat (limited to '')
-rw-r--r-- | raddb/sites-available/coa-relay | 331 |
1 files changed, 331 insertions, 0 deletions
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 +} |