Freeradius3 Simultaneous-Use not working for concurrent connections

Hello,

I've come a long way setting up my WIFI-Public network with 802.1X, following (among others) this article:
[[OpenWrt Wiki] FreeRADIUS]

But I can't seem to get Simultaneous-Use working, how hard I try.
What I think might be the problem, is that the Simultaneous-Use attribute is not passed on to the responsible service, because I don't see it show up in the radiusd -X logging.

I do see the connecting user show up in the /var/log/radutmp file.
If I connect on different devices, more instances of that user shown up in the file.

I'll include parts from my config that I believe might be important.
Any help would be much appreciated :sweat_smile:

/etc/freeradius3/radiusd.conf

prefix = /usr
exec_prefix = /usr
sysconfdir = /etc
localstatedir = /var
sbindir = /usr/sbin
logdir = /var/log
raddbdir = /etc/freeradius3
radacctdir = /var/db/radacct

#  Location of config and logfiles.
confdir = ${raddbdir}
modconfdir = ${confdir}/mods-config
certdir = ${confdir}/certs
cadir   = ${confdir}/certs
run_dir = ${localstatedir}/run/${name}

# Should likely be ${localstatedir}/lib/radiusd
db_dir = ${raddbdir}

log {	
	file = ${logdir}/radius.log
	stripped_names = no

	#  Log all (accept and reject) authentication results to the log file.
	auth = no

	#  The message when the user exceeds the Simultaneous-Use limit.
	#
	msg_denied = "You are already logged in - access denied"
}

$INCLUDE clients.conf

$INCLUDE sites-enabled/

/etc/freeradius3/clients.conf

client localhost {
	ipaddr = 127.0.0.1
	proto = *
	secret = somesecret
	require_message_authenticator = no

	# The nas_type tells 'checkrad.pl' which NAS-specific method to
	#  use to query the NAS for simultaneous use.
	#	other		# for all other types
	nas_type	 = other	# localhost isn't usually a NAS...

	#  The following two configurations are for future use.
	#  The 'naspasswd' file is currently used to store the NAS
	#  login name and password, which is used by checkrad.pl
	#  when querying the NAS for simultaneous use.
#	login	   = !root
#	password	= someadminpas

# IPv6 Client
client localhost_ipv6 {
	ipv6addr	= ::1
	secret		= somesecret
}

/etc/freeradius3/mods-enabled/radutmp

radutmp {
	filename = ${logdir}/radutmp
	username = %{User-Name}
	case_sensitive = yes
	check_with_nas = yes
	permissions = 0600
	caller_id = "yes"
}

/etc/freeradius3/sites-enabled/default

listen {
	type = auth
	ipaddr = 127.0.0.1
	port = 0
}

listen {
	ipaddr = 127.0.0.1
#	ipv6addr = ::
	port = 0
	type = acct
}

listen {
	type = auth
	ipv6addr = ::1 #== localhost
	port = 0
	limit {
	      max_connections = 16
	      lifetime = 0
	      idle_timeout = 30
	}
}

#  Any changes made here should also be made to the "inner-tunnel"
#  virtual server.
authorize {
	filter_username
	preprocess
#	auth_log
	suffix
	eap {
		ok = return
	}
	#  Read the 'users' file.  In v3, this is located in
	#  raddb/mods-config/files/authorize
	files
#	-sql
	expiration
	logintime
}

authenticate {
	Auth-Type PAP {
		pap
	}
	Auth-Type CHAP {
		chap
	}
	Auth-Type MS-CHAP {
		mschap
	}
	mschap
	eap
}

preacct {
	preprocess
	acct_unique
	suffix
	files
}

accounting {
	unix

	#  For Simultaneous-Use tracking.
	radutmp
#	-sql
	exec

	#  Filter attributes from the accounting response.
	attr_filter.accounting_response
}

#  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

#	sql
}

post-auth {
	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:
	}

	exec
	remove_reply_message_if_eap

	Post-Auth-Type REJECT {
		# log failed authentications in SQL, too.
#		-sql
		attr_filter.access_reject
		eap
	Post-Auth-Type Challenge {
	}
}

/etc/freeradius3/sites-enabled/inner-tunnel

server inner-tunnel {
listen {
       ipaddr = 127.0.0.1
       port = 18120
       type = auth
}

authorize {
	filter_username
	chap
	mschap
	suffix
	update control {
		&Proxy-To-Realm := LOCAL
	}

	inner-eap {
		ok = return
	}

	files
#	-sql
	expiration
	logintime
	pap
}

authenticate {
	Auth-Type PAP {
		pap
	}
	Auth-Type CHAP {
		chap
	}
	Auth-Type MS-CHAP {
		mschap
	}
	mschap
	inner-eap
}

#  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
#	sql
}

/etc/freeradius3/mods-config/files/authorize

$INCLUDE /root/users.1.txt

# Tried this, but it does not work:
DEFAULT   Service-Type == Framed-User
	Simultaneous-Use = 1

/root/users.1.txt

user.1	Cleartext-Password := "password", Simultaneous-Use := 1

radiusd -X

(9) Received Access-Request Id 22 from 127.0.0.1:45389 to 127.0.0.1:1812 length 270
(9)   User-Name = "user.1"
(9)   Called-Station-Id = "AA-BB-CC-DD-EE-FF:WIFI-Public"
(9)   NAS-Port-Type = Wireless-802.11
(9)   Service-Type = Framed-User
(9)   NAS-Port = 1
(9)   Calling-Station-Id = "BB-CC-DD-EE-FF-GG"
(9)   Connect-Info = "CONNECT 54Mbps 802.11g"
(9)   Acct-Session-Id = "0F185A5D56CD3336"
(9)   Attr-186 = 0x000fac04
(9)   Attr-187 = 0x000fac04
(9)   Attr-188 = 0x000fac01
(9)   Framed-MTU = 1400
(9)   EAP-Message = ****
(9)   State = ****
(9)   Message-Authenticator = ****
(9) Restoring &session-state
(9)   &session-state:TLS-Session-Cipher-Suite = "ECDHE-RSA-AES128-GCM-SHA256"
(9)   &session-state:TLS-Session-Version = "TLS 1.2"
(9) # Executing section authorize from file /etc/freeradius3/sites-enabled/default
(9)   authorize {
(9)     policy filter_username {
(9)       if (&User-Name) {
(9)       if (&User-Name)  -> TRUE
(9)       if (&User-Name)  {
(9)         if (&User-Name =~ / /) {
(9)         if (&User-Name =~ / /)  -> FALSE
(9)         if (&User-Name =~ /@[^@]*@/ ) {
(9)         if (&User-Name =~ /@[^@]*@/ )  -> FALSE
(9)         if (&User-Name =~ /\.\./ ) {
(9)         if (&User-Name =~ /\.\./ )  -> FALSE
(9)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))  {
(9)         if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/))   -> FALSE
(9)         if (&User-Name =~ /\.$/)  {
(9)         if (&User-Name =~ /\.$/)   -> FALSE
(9)         if (&User-Name =~ /@\./)  {
(9)         if (&User-Name =~ /@\./)   -> FALSE
(9)       } # if (&User-Name)  = notfound
(9)     } # policy filter_username = notfound
(9)     [preprocess] = ok
(9) suffix: Checking for suffix after "@"
(9) suffix: No '@' in User-Name = "user.1", looking up realm NULL
(9) suffix: No such realm "NULL"
(9)     [suffix] = noop
(9) eap: Peer sent EAP Response (code 2) ID 10 length 46
(9) eap: Continuing tunnel setup
(9)     [eap] = ok
(9)   } # authorize = ok
(9) Found Auth-Type = eap
(9) # Executing group from file /etc/freeradius3/sites-enabled/default
(9)   authenticate {
(9) eap: Expiring EAP session with state ****
(9) eap: Finished EAP session with state ****
(9) eap: Previous EAP request found for state ****, released from the list
(9) eap: Peer sent packet with method EAP PEAP (25)
(9) eap: Calling submodule eap_peap to process data
(9) eap_peap: Continuing EAP-TLS
(9) eap_peap: [eaptls verify] = ok
(9) eap_peap: Done initial handshake
(9) eap_peap: [eaptls process] = ok
(9) eap_peap: Session established.  Decoding tunneled attributes
(9) eap_peap: PEAP state send tlv success
(9) eap_peap: Received EAP-TLV response
(9) eap_peap: Success
(9) eap: Sending EAP Success (code 3) ID 10 length 4
(9) eap: Freeing handler
(9)     [eap] = ok
(9)   } # authenticate = ok
(9) # Executing section post-auth from file /etc/freeradius3/sites-enabled/default
(9)   post-auth {
(9)     if (session-state:User-Name && reply:User-Name && request:User-Name && (reply:User-Name == request:User-Name)) {
(9)     if (session-state:User-Name && reply:User-Name && request:User-Name && (reply:User-Name == request:User-Name))  -> FALSE
(9)     update {
(9)       &reply::TLS-Session-Cipher-Suite += &session-state:TLS-Session-Cipher-Suite[*] -> 'ECDHE-RSA-AES128-GCM-SHA256'
(9)       &reply::TLS-Session-Version += &session-state:TLS-Session-Version[*] -> 'TLS 1.2'
(9)     } # update = noop
(9)     [exec] = noop
(9)     policy remove_reply_message_if_eap {
(9)       if (&reply:EAP-Message && &reply:Reply-Message) {
(9)       if (&reply:EAP-Message && &reply:Reply-Message)  -> FALSE
(9)       else {
(9)         [noop] = noop
(9)       } # else = noop
(9)     } # policy remove_reply_message_if_eap = noop
(9)   } # post-auth = noop
(9) Sent Access-Accept Id 22 from 127.0.0.1:1812 to 127.0.0.1:45389 length 0
(9)   MS-MPPE-Recv-Key = ****
(9)   MS-MPPE-Send-Key = ****
(9)   EAP-Message = 0x030a0004
(9)   Message-Authenticator = 0x00000000000000000000000000000000
(9)   User-Name = "user.1"
(9) Finished request
Waking up in 4.5 seconds.
(10) Received Accounting-Request Id 23 from 127.0.0.1:42959 to 127.0.0.1:1813 length 204
(10)   Acct-Status-Type = Start
(10)   Acct-Authentic = RADIUS
(10)   User-Name = "user.1"
(10)   Called-Station-Id = "AA-BB-CC-DD-EE-FF:WIFI-Public"
(10)   NAS-Port-Type = Wireless-802.11
(10)   Service-Type = Framed-User
(10)   NAS-Port = 1
(10)   Calling-Station-Id = "BB-CC-DD-EE-FF-GG"
(10)   Connect-Info = "CONNECT 54Mbps 802.11g"
(10)   Acct-Session-Id = "0F185A5D56CD3336"
(10)   Attr-186 = 0x000fac04
(10)   Attr-187 = 0x000fac04
(10)   Attr-188 = 0x000fac01
(10)   Event-Timestamp = "Jan 28 2023 12:31:00 CET"
(10)   Acct-Delay-Time = 0
(10) # Executing section preacct from file /etc/freeradius3/sites-enabled/default
(10)   preacct {
(10)     [preprocess] = ok
(10)     policy acct_unique {
(10)       update request {
(10)         &Tmp-String-9 := "ai:"
(10)       } # update request = noop
(10)       if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) &&      ("%{string:&Class}" =~ /^ai:([0-9a-f]{32})/i)) {
(10)       EXPAND %{hex:&Class}
(10)          -->
(10)       EXPAND ^%{hex:&Tmp-String-9}
(10)          --> ^61693a
(10)       if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) &&      ("%{string:&Class}" =~ /^ai:([0-9a-f]{32})/i))  -> FALSE
(10)       else {
(10)         update request {
(10)           EXPAND %{md5:%{User-Name},%{Acct-Session-ID},%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port}}
(10)              --> ****
(10)           &Acct-Unique-Session-Id := ****
(10)         } # update request = noop
(10)       } # else = noop
(10)     } # policy acct_unique = noop
(10) suffix: Checking for suffix after "@"
(10) suffix: No '@' in User-Name = "user.1", looking up realm NULL
(10) suffix: No such realm "NULL"
(10)     [suffix] = noop
(10)     [files] = noop
(10)   } # preacct = ok
(10) # Executing section accounting from file /etc/freeradius3/sites-enabled/default
(10)   accounting {
(10)     [unix] = ok
(10) radutmp: EXPAND /var/log/radutmp
(10) radutmp:    --> /var/log/radutmp
(10) radutmp: EXPAND %{User-Name}
(10) radutmp:    --> user.1
(10)     [radutmp] = ok
(10)     [exec] = noop
(10) attr_filter.accounting_response: EXPAND %{User-Name}
(10) attr_filter.accounting_response:    --> user.1
(10) attr_filter.accounting_response: Matched entry DEFAULT at line 12
(10)     [attr_filter.accounting_response] = updated
(10)   } # accounting = updated
(10) Sent Accounting-Response Id 23 from 127.0.0.1:1813 to 127.0.0.1:42959 length 0
(10) Finished request
(10) Cleaning up request packet ID 23 with timestamp +47

This part tells checkrad.pl is used for Simultaneous-Use checking, but there's no such package available to be installed...

I'm actually a bit surprised that no one has posted an answer to this question.
Am I asking for something too difficult?
Is the question in the wrong section?
Should I be more patient?
My previous post was solved in a day, so I had my hopes up...

Freeradius by itself doesn't track user state. Enforcing simultaneous use requires some sort of back end database to track whether the user account is already logged in somewhere else.

Accourding to the documentation it should be tracked by consulting either mysql or the radutmp file.
The radutmp file sounds the most simple, so that's what I want to go for.
But indeed as you mention, there should be a process checking that file. If it's not freeradius and not checkrad.pl, then what should it be? And why is there no non-incomplete documentation to be found on the subject?

Simultaneous-Use .... I used it on a backend server, for management of hotspots. But then freeradius3 required mysql-plugin, to track all users and their quotas, like session-time, traffic etc. Complete doc about config of freeradius is not really part of openwrt. In case of 'advanced' config of freeradius, like in your case, refere to standard LINUX docs of freeradius, and then port it to openwrt.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.