Return Access-Accept/-Reject depending on other active sessions during post-authentication
Hello together, my NAS supports used-based authentication, this means it is possible to have multiple sessions on the same ethernet port (same user multiple times and/or different users). Each attached supplicant must authenticate itsself. The switch prohibits a supplicant to use piggy-backing on top of some other already authenticated supplicant. Moreover I use RADIUS-assigned VLANs. If the same user or different users that are assigned to the same VLAN are authenticated on the same port, everything is fine. The trouble starts, if an additional user with a different VLAN than the VLAN that is already assigned to the port is sucessfully authenticated. In the past an additional user was denied access by the switch, if such a VLAN mismatch occured. This means is was impossible to have serveral different untagged VLANs on the same port. But my current NAS also grants access to the addtional user and assignes this user's VLAN to the port, too. This means there are more than one untagged VLAN on the same port at the same time and the result is some kind of "short-circuit fault" between the affected VLANs. Now, I would like to write some kind of RADIUS policy to prevent this behaviour. This policy is supposed to do the following during the post-authentication phase: 1) If there is no active session on the NAS port, just return Access-Accept 2) If there is at least one active session on the NAS port and the 'Tunnel-Private-Group-ID' of that session equals the 'Tunnel-Private-Group-ID' of the new request, return Access-Accept. 3) If there is at least one active session on the NAS port and the 'Tunnel-Private-Group-ID' of that session DOES NOT equal the 'Tunnel-Private-Group-ID' of the new request, return Access-Reject. Is this possible to do? I have the accounting information in a SQL database, hence I know, if there are active sessions on some port. But I do not know, which would be the correct RADIUS configuration section and I do not know if "unlang" or some other configuration directive can perform such a check. Best regards, Matthias ---------------------------------------------------------------------- Matthias Nagel Willy-Andreas-Allee 1, Zimmer 506 76131 Karlsruhe Telefon: +49-721-8695-1506 Mobil: +49-151-15998774 e-Mail: matthias.h.nagel@gmail.com ICQ: 499797758 Skype: nagmat84
Matthias Nagel wrote:
Now, I would like to write some kind of RADIUS policy to prevent this behaviour.
(a) store information in a database (b) use "unlang" to query the database
This policy is supposed to do the following during the post-authentication phase:
1) If there is no active session on the NAS port, just return Access-Accept
You may need to create a new table which stores active sessions. INSERT data into it on authentication / accounting start. DELETE data on accounting stop.
2) If there is at least one active session on the NAS port and the 'Tunnel-Private-Group-ID' of that session equals the 'Tunnel-Private-Group-ID' of the new request, return Access-Accept.
Store the Tunnel-Private-Group-ID of a session on INSERT. Query it on the next session authentication.
3) If there is at least one active session on the NAS port and the 'Tunnel-Private-Group-ID' of that session DOES NOT equal the 'Tunnel-Private-Group-ID' of the new request, return Access-Reject.
Query the DB. If it doesn't match, reject.
Is this possible to do? I have the accounting information in a SQL database, hence I know, if there are active sessions on some port. But I do not know, which would be the correct RADIUS configuration section and I do not know if "unlang" or some other configuration directive can perform such a check.
"unlang" is just a way to write policies. It does NOT store data. SQL databases store data. The two together can solve this problem. Alan DeKok.
Hello, problem solved. I post this message for the sake of completeness and in case, if anyone will ever need to solve a similar problem. Of course, any comments on how my solution can be improved are welcomed. 1) At the SQL side I created a view (active_users) with three columns (nasipaddress, nasport and vlan) that always shows the active sessions. Basically it selects all entries from the accounting table (radacct) where the stop time is NULL and then the result is joined with the user attribute table (radreply) in order to append the vlan to each record. Of course, the join is done by the user name. 2) In the RADIUS config the following expression is added to the post-auth section of the default server. # Prevent multiple untagged VLANs on the same port at the same time. # Otherwise there would be short-curcuit fault between the affected VLANs if ( "%{sql:SELECT COUNT(*) FROM active_users WHERE nasipaddress = '%{NAS-IP-Address}' AND nasport = %{NAS-Port} AND vlan <> '%{reply:Tunnel-Private-Group-ID}' }" != 0 ) { reject } The SQL statement counts all (active) sessions on the same NAS on the same NAS port with a different VLAN assignment than the VLAN the current user is going to be assigned to. If the number does not equal zero, there is at least one session on the same port with a different VLAN. In that case the user is rejected. 3) Prevent stalled-session Accouning-Stop messages can be lost. In that case a session will falsely remain active and thus likely block out any other user. I use an interim update intervall with five minutes. If three updates were missed, i.e. the last update time is less then the current system time minus 15 minutes, the session is considered to be stalled and the stop time is set to the last update time. This way a stalled session is closed 15 minutes after the last update. Yours, Matthias Am Sonntag 16 Dezember 2012, 17:07:53 schrieb Alan DeKok:
Matthias Nagel wrote:
Now, I would like to write some kind of RADIUS policy to prevent this behaviour.
(a) store information in a database (b) use "unlang" to query the database
This policy is supposed to do the following during the post-authentication phase:
1) If there is no active session on the NAS port, just return Access-Accept
You may need to create a new table which stores active sessions. INSERT data into it on authentication / accounting start. DELETE data on accounting stop.
2) If there is at least one active session on the NAS port and the 'Tunnel-Private-Group-ID' of that session equals the 'Tunnel-Private-Group-ID' of the new request, return Access-Accept.
Store the Tunnel-Private-Group-ID of a session on INSERT. Query it on the next session authentication.
3) If there is at least one active session on the NAS port and the 'Tunnel-Private-Group-ID' of that session DOES NOT equal the 'Tunnel-Private-Group-ID' of the new request, return Access-Reject.
Query the DB. If it doesn't match, reject.
Is this possible to do? I have the accounting information in a SQL database, hence I know, if there are active sessions on some port. But I do not know, which would be the correct RADIUS configuration section and I do not know if "unlang" or some other configuration directive can perform such a check.
"unlang" is just a way to write policies. It does NOT store data. SQL databases store data.
The two together can solve this problem.
Alan DeKok. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Matthias Nagel Willy-Andreas-Allee 1, Zimmer 506 76131 Karlsruhe Telefon: +49-721-8695-1506 Mobil: +49-151-15998774 e-Mail: matthias.h.nagel@gmail.com ICQ: 499797758 Skype: nagmat84
participants (2)
-
Alan DeKok -
Matthias Nagel