FreeRADIUS

Installazione

Per l'installazione su sistemi Ubuntu, è possibile ottenere la versione di FreeRADIUS più aggiornata aggiungendo il repository ppa:freeradius/stable-3.0

add-apt-repository ppa:freeradius/stable-3.0
apt-get update
apt-get install freeradius

Configurazione

Nel seguito si mostrerà un template di configurazione per l'integrazione di FreeRADIUS all'interno della federazione eduroam.

La configurazione che viene proposta è relativa alla versione 3 di FreeRADIUS essendo la versione 2 ormai deprecata.

Prima di procedere è necessario prendere nota dei seguenti valori che andranno opportunamente sostituiti nei file di configurazione:

Operator-Name

rappresenta un valore univoco che identifica l'ente che invia le richieste di autenticazione alla federazione eduroam in qualità di Resource Provider. Si prende come riferimento il dominio principale dell'ente preceduto dalla stringa 1 (es. 1uniroma1.it). Nei file di configurazione verrà indicato come ###OPERATOR_NAME###

Secret

è il segreto condiviso scambiato con gli operatori della federazione nazionale. Nei file di configurazione verrà indicato come ###SHARED_SECRET###

Per gli Identity Provider, è necessario procurarsi un certificato server. Nel momento in cui si scrive, i certificati rilasciati da Digicert mediante Terena SSL CA 3 rispettano tutti i requisiti indicati nel relativo paragrafo. Per i certificati self-signed, far riferimento alle istruzioni contenute nel paragrafo eap in quanto i certificati creati automaticamente con l'installazione di freeradius non sono correttamente riconosciuti con alcuni dispositivi che si collegano ad eduroam.

Avvertimento

Attenzione! I seguenti file rappresentano solo delle linee guida per la configurazione di FreeRADIUS e non vanno intesi come sostituti delle attuali configurazioni in essere presso gli enti.

radiusd.conf

Per Identity Provider e Resource Provider

Il file principale per la configurazione di FreeRADIUS è radiusd.conf. Rispetto alla versione di default con cui viene installato, non richiede particolari variazioni, eccetto per le direttive:

reject_delay

0

auth

yes

cleanup_delay

10

prefix = /usr
exec_prefix = /usr
sysconfdir = /etc
localstatedir = /var
sbindir = ${exec_prefix}/sbin
logdir = /var/log/freeradius
raddbdir = /etc/freeradius
radacctdir = ${logdir}/radacct

name = freeradius

confdir = ${raddbdir}
modconfdir = ${confdir}/mods-config
certdir = ${confdir}/certs
cadir   = ${confdir}/certs
run_dir = ${localstatedir}/run/${name}

db_dir = ${raddbdir}

libdir = /usr/lib/freeradius

pidfile = ${run_dir}/${name}.pid

correct_escapes = true


max_request_time = 30

cleanup_delay = 10

max_requests = 16384

hostname_lookups = no

log {
	destination = files

	colourise = yes

	file = ${logdir}/radius.log

	syslog_facility = daemon

	stripped_names = no

	auth = yes

	auth_badpass = no
	auth_goodpass = no


	msg_denied = "You are already logged in - access denied"
}

checkrad = ${sbindir}/checkrad

security {

	user = freerad
	group = freerad

	allow_core_dumps = no

	max_attributes = 200

	reject_delay = 0

	status_server = yes


}

proxy_requests  = yes
$INCLUDE proxy.conf



$INCLUDE clients.conf


thread pool {
	start_servers = 5

	max_servers = 32

	min_spare_servers = 3
	max_spare_servers = 10


	max_requests_per_server = 0


	auto_limit_acct = no
}


modules {

	$INCLUDE mods-enabled/
}

instantiate {

}

policy {
	$INCLUDE policy.d/
}

$INCLUDE sites-enabled/

clients.conf

Per Identity Provider e Resource Provider

Nel file clients.conf vengono configurati tutti gli apparati e/o server che possono inviare richieste di autenticazione al FreeRADIUS.

Nel caso di Resource Provider, gli unici client configurati saranno gli apparati di rete dell'ente (es. Access Point, Wireless LAN Controller).

Nel caso di Identity Provider, invece, i client da configurare sono i server della federazione nazionale radius.garr.net e radius2.garr.net da cui proverranno le richieste di autenticazione dei propri utenti in roaming.

#LOCALHOST
client localhost {
	ipaddr = 127.0.0.1
	proto = *

	# Il secret per il client localhost è di default valorizzato come testing123. 
	# Cambiare il valore con uno di propria scelta.
	# NON UTILIZZARE LO SHARED_SECRET COMUNICATO ALLA FEDERAZIONE NAZIONALE
	secret = testing123

	require_message_authenticator = no

	virtual_server = eduroam

	# L'Operator-Name deve essere preceduto da 1. (es. 1uniroma1.it)
	Operator-Name = ###OPERATOR_NAME###

	add_cui = yes
	
	limit {
		max_connections = 16
		lifetime = 0
		idle_timeout = 30
	}
}

client localhost_ipv6 {
	ipv6addr	= ::1
	
	# Il secret per il client localhost è di default valorizzato come testing123. 
	# Cambiare il valore con uno di propria scelta.
	# NON UTILIZZARE LO SHARED_SECRET COMUNICATO ALLA FEDERAZIONE NAZIONALE
	secret = testing123

}

#
# RESOURCE PROVIDER
#
# Esempio di Wireless LAN Controller
client wlc {
	ipaddr = 192.168.1.1
	shortname = wlc

	# Il secret per il client wlc è uno di propria scelta con cui configurare 
	# l'apparato che effettuerà le richieste di autenticazione.
	# NON UTILIZZARE LO SHARED_SECRET COMUNICATO ALLA FEDERAZIONE NAZIONALE
	secret = secret123

	nas_type = other
	virtual_server = eduroam

	# L'Operator-Name deve essere preceduto da 1. (es. 1uniroma1.it)
	Operator-Name = ###OPERATOR_NAME###

	# Richiede il Chargeable-User-Identity
	add_cui = yes
}


#
# IDENTITY PROVIDER
#
# Sono configurati i server radius della federazione nazionale radius.garr.net e radius2.garr.net
# con il secret condiviso con il personale tecnico.

client radius.garr.net {
	ipaddr = radius.garr.net
	secret = ###SHARED_SECRET###
	nas_type = other
	virtual_server = eduroam
}
client radius2.garr.net {
	ipaddr = radius2.garr.net
	secret = ###SHARED_SECRET###
	nas_type = other
	virtual_server = eduroam
}

proxy.conf

Per Identity Provider e Resource Provider

Il file proxy.conf configura la gestione del realm.

Gli Identity Provider devono gestire il proprio realm localmente.

Gli Resource Provider, invece, dovranno effettuare l'inoltro ai server della federazione nazionale.

proxy server {
	default_fallback = no
}


realm LOCAL {
}

realm NULL {
	virtual_server  = auth-reject
}

#
# RESOURCE PROVIDER
#
# Le autenticazioni per i domini che non sono gestiti dall'ente, 
# dovranno essere inviate alla federazione nazionale eduroam.

home_server radius.garr.net {
	type                    = auth+acct
	ipaddr                  = radius.garr.net
	port                    = 1812
	secret                  = ###SHARED_SECRET###
	status_check            = status-server
}
home_server radius2.garr.net {
	type                    = auth+acct
	ipaddr                  = radius2.garr.net
	port                    = 1812
	secret                  = ###SHARED_SECRET###
	status_check            = status-server
}

home_server_pool EDUROAM-FTLR {
	type                    = fail-over
	home_server             = radius.garr.net
	home_server             = radius2.garr.net
}

realm "~.+$" {
	pool                    = EDUROAM-FTLR
	nostrip
}

#
# IDENTITY PROVIDER
#
# Tutti realm gestiti dall'ente, dovranno essere definiti in questo modo.

realm realm1.it {
}
realm realm2.it {
}
realm realm3.it {
}

Virtual server eduroam

Per Identity Provider e Resource Provider

Il virtual_server eduroam definito nel clients.conf identifica come i pacchetti di autenticazioni devono essere analizzati da FreeRADIUS.

Innanzitutto viene effettuata una verifica sulla sintassi della outer-identity e aggiunto l'attributo Operator-Name. Con la direttiva suffix si verifica se l'autenticazione sia relativa ad un dominio gestito localmente (come definito in proxy.conf) oppure è necessario demandare alla federazione nazionale (aggiungendo gli attributi definiti nel pre-proxy). Nel caso di autenticazioni locali, allora si attiva il modulo eap. Se si tratta invece di autenticazioni remote, si attivano le stanze post-proxy e post-auth.

Creare il file sites-available/eduroam con il seguente contenuto:

server eduroam {

	listen {
		type = "auth"
		ipaddr = *
		port = 0
	}
	listen {
		type = "acct"
		ipaddr = *
		port = 0
	}
	listen {
		type = "auth"
		ipv6addr = ::
		port = 0
	}
	listen {
		type = "acct"
		ipv6addr = ::
		port = 0
	}

	authorize {

		filter_username
		
		# Se almeno Resource Provider, aggiungere
		filter_eduroam_realms
		operator-name
		# #######################################

		cui

		auth_log

		suffix

		# Se almeno Identity Provider, aggiungere
		eap {
			ok = return
			updated = return
		}
		# #######################################

	}

	authenticate {
		# Se almeno Identity Provider, aggiungere
		eap
		# #######################################

	}

	preacct {
		suffix
	}

	accounting {
	}

	post-auth {
		update {
			&reply: += &session-state:
		}

		cui
		reply_log
		eduroam_log
		Post-Auth-Type REJECT {
			attr_filter.access_reject

			eap

			reply_log
			eduroam_log
		}
	}

	pre-proxy {
		operator-name
		cui

		pre_proxy_log
		if("%{Packet-Type}" != "Accounting-Request") {
			attr_filter.pre-proxy
		}
	}

	post-proxy {
		post_proxy_log
		attr_filter.post-proxy
		eap
	}
}

Abilitare il virtual site creando il collegamento simbolico rimuovendo eventualmente il virtual site default

cd /etc/freeradius/sites-enabled
ln -s ../sites-available/eduroam .
rm default

Virtual server eduroam-inner-tunnel

Solo per Identity Provider

Le richieste di autenticazione che sono state analizzate dal virtual server eduroam e che devono essere autenticate localmente poiché si riferiscono ad un realm locale, dopo aver attivato il modulo eap, passano al virtual server eduroam-inner-tunnel nel quale il tunnel TLS viene decifrato per accedere alla inner-identity e alla password dell'utente.

Creare il file sites-available/eduroam-inner-tunnel con il seguente contenuto:

#
# SOLO IDENTITY PROVIDER
#
server eduroam-inner-tunnel {

	authorize {
		filter_username

		if ("%{request:User-Name}" =~ /^(.*)@(.*)/) {
			update request {
				Stripped-User-Name := "%{1}"
				Realm := "%{2}"
			}
		}

		auth_log
		eap

		# Se gli utenti sono memorizzati su file di testo
		files
		
		# Se gli utenti sono memorizzati su un database
		sql

		# Se gli utenti sono memorizzati su LDAP
		ldap
		if ((ok || updated) && User-Password) {
			update {
				control:Auth-Type := ldap
			}
		}



		mschap
		pap
	}

	authenticate {
		Auth-Type PAP {
			pap
		}
		Auth-Type MS-CHAP {
			mschap
		}
		Auth-Type LDAP {
			ldap
		}

		eap
	}

	post-auth {
		cui-inner
		reply_log
		eduroam_inner_log
		Post-Auth-Type REJECT {
			attr_filter.access_reject
			reply_log
			eduroam_inner_log

			update outer.session-state {
				&Module-Failure-Message := &request:Module-Failure-Message
			}
		}
	}

	post-proxy {
		eap
	}
}

Abilitare il virtual site creando il collegamento simbolico

cd /etc/freeradius/sites-enabled
ln -s ../sites-available/eduroam-inner-tunnel .

eap

Solo per Identity Provider

Modificare il file mods-enabled/eap

eap {
	default_eap_type = peap
	timer_expire     = 60
	ignore_unknown_eap_types = no
	cisco_accounting_username_bug = no
	max_sessions = ${max_requests}
	#md5 {
	#}
	#leap {
	#}
	gtc {
		auth_type = PAP
	}
	tls-config tls-common {
		private_key_password = whatever
		private_key_file = ${certdir}/server.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}/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, you have to
        #  run OpenSSL to create the DH file first:
        #
        #   openssl dhparam -out certs/dh 1024
        #
		dh_file = ${certdir}/dh

		ca_path = ${cadir}

		#
        #  This can never exceed the size of a RADIUS
        #  packet (4096 bytes), and is preferably half
        #  that, to accomodate other attributes in
        #  RADIUS packet.  On most APs the MAX packet
        #  length is configured between 1500 - 1600
        #  In these cases, fragment size should be
        #  1024 or less. If your AP drops packets 
		#  towards the client, try reducing this.
        #
        fragment_size = 1024
 
        #  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

		# TLS cipher suites.  The format is listed
        # in "man 1 ciphers".
		cipher_list = "DEFAULT"

		ecdh_curve = "prime256v1"

		#
        #  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.
			#
			#  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 = yes

			#
			#  Lifetime of the cached entries, in hours.
			#  The sessions will be deleted after this
			#  time.
			#
			lifetime = 24 

			#
			#  The maximum number of entries in the
			#  cache.  Set to "0" for "infinite".
			#
			#  This could be set to the number of users
			#  who are logged in... which can be a LOT.
			#
			max_entries = 255
		}
		verify {
		}
		ocsp {
			enable = no
			override_cert_url = yes
			url = "http://127.0.0.1/ocsp/"
		}
	}
	tls {
		tls = tls-common
	}
	ttls {
		tls = tls-common
		default_eap_type = pap
		copy_request_to_tunnel = yes
		use_tunneled_reply = yes
		virtual_server = "eduroam-inner-tunnel"
	}
	peap {
		tls = tls-common
		default_eap_type = mschapv2
		copy_request_to_tunnel = yes
		use_tunneled_reply = yes
		virtual_server = "eduroam-inner-tunnel"
	}
	mschapv2 {
	}
}

Certificati

Solo per Identity Provider

Se si è ottenuto un certificato da Digicert mediante Terena SSL CA 3 è sufficiente creare il file /etc/freeradius/certs/server.pem composto dalla concatenazione del:

  • Certificato server rilasciato da Terena

  • Certificato di TERENA SSL CA 3

  • Certificato di DigiCert Assured ID Root CA

Ad esempio:

-----BEGIN CERTIFICATE-----
*server radius certificate*
------END CERTIFICATE------
-----BEGIN CERTIFICATE-----
MIIE+zCCA+OgAwIBAgIQCHC8xa8/25Wakctq7u/kZTANBgkqhkiG9w0BAQsFADBl
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
b3QgQ0EwHhcNMTQxMTE4MTIwMDAwWhcNMjQxMTE4MTIwMDAwWjBkMQswCQYDVQQG
EwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDESMBAGA1UEBxMJQW1zdGVyZGFt
MQ8wDQYDVQQKEwZURVJFTkExGDAWBgNVBAMTD1RFUkVOQSBTU0wgQ0EgMzCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMV2Dw/ZQyk7bG3RR63eEL8jwnio
Snc18SNb4EweQefCMQC9iDdFdd25AhCAHo/tZCMERaegOTuBTc9jP8JJ/yKeiLDS
lrlcinQfkioq8hLIt2hUtVhBgUBoBhpPhSn7tU08D08/QJYbzqjMXjX/ZJj1dd10
VAWgNhEEEiRVY++Udy538RV27tOkWUUhn6i+0SftCuirOMo/h9Ha8Y+5Cx9E5+Ct
85XCFk3shKM6ktTPxn3mvcsaQE+zVLHzj28NHuO+SaNW5Ae8jafOHbBbV1bRxBz8
mGXRzUYvkZS/RYVJ+G1ShxwCVgEnFqtyLvRx5GG1IKD6JmlqCvGrn223zyUCAwEA
AaOCAaYwggGiMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMHkG
CCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu
Y29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln
aUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRw
Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3Js
MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk
SURSb290Q0EuY3JsMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxo
dHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMB0GA1UdDgQWBBRn/YggFCeYxwnS
JRm76VERY3VQYjAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
hkiG9w0BAQsFAAOCAQEAqSg1esR71tonHqyYzyc2TxEydHTmQN0dzfJodzWvs4xd
xgS/FfQjZ4u5b5cE60adws3J0aSugS7JurHogNAcyTnBVnZZbJx946nw09E02DxJ
WYsamM6/xvLYMDX/6W9doK867mZTrqqMaci+mqege9iCSzMTyAfzd9fzZM2eY/lC
J1OuEDOJcjcV8b73HjWizsMt8tey5gvHacDlH198aZt+ziYaM0TDuncFO7pdP0GJ
+hY77gRuW6xWS++McPJKe1e9GW6LNgdUJi2GCZQfXzer8CM/jyxflp5HcahE3qm5
hS+1NGClXwmgmkMd1L8tRNaN2v11y18WoA5hwnA9Ng==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
-----END CERTIFICATE-----

Il file mods-enabled/eap deve avere come parametri:

private_key:

file della chiave private non cifrata con cui è stata generate la CSR sottomessa a Digicert. Se la chiave è cifrata, allora è necessario valorizzare la direttiva private_key_password

certificate_file:

file server.pem creato come indicato in precedenza

ca_file:

questa direttiva deve essere commentata

Se invece si vuole utilizzare una CA self-signed, è necessario che questa sia generata in modo proprio. Infatti, non solo i certificati generati in automatico al momento dell'installazione di FreeRADIUS sono validi solo per pochi giorni, ma essi non rispettano i requisiti che deve avere un certificato server radius in eduroam. La procedura è la seguente:

  • Eliminare i certificati creati automaticamente

cd /etc/freeradius/certs
rm -f *.pem *.der *.csr *.crt *.key *.p12 serial* index.txt*
  • Modificare le configurazioni della CA: ca.cnf valorizzando gli attributi ###LOCALITA###, ###ORGANIZZAZIONE###, ###EMAIL###

[ ca ]
default_ca		        = CA_default

[ CA_default ]
dir			            = ./
certs			        = $dir
crl_dir			        = $dir/crl
database		        = $dir/index.txt
new_certs_dir	        = $dir
certificate		        = $dir/ca.pem
serial			        = $dir/serial
crl			            = $dir/crl.pem
private_key		        = $dir/ca.key
RANDFILE		        = $dir/.rand
name_opt		        = ca_default
cert_opt		        = ca_default
default_days	        = 3650
default_crl_days        = 30
crl_extensions          = crl_ext
default_md		        = sha256
preserve		        = no
policy			        = policy_match
crlDistributionPoints	= URI:http://www.example.org/example_ca.crl
name_opt                = ca_default
cert_opt                = ca_default


[ policy_match ]
countryName		        = match
stateOrProvinceName	    = match
organizationName	    = match
organizationalUnitName	= optional
commonName		        = supplied
emailAddress		    = optional

[ policy_anything ]
countryName		        = optional
stateOrProvinceName	    = optional
localityName		    = optional
organizationName	    = optional
organizationalUnitName	= optional
commonName		        = supplied
emailAddress		    = optional

[ req ]
prompt			        = no
distinguished_name	    = certificate_authority
default_md              = sha256
default_bits		    = 2048
input_password		    = whatever
output_password		    = whatever
x509_extensions		    = v3_ca

[certificate_authority]
countryName		        = IT
stateOrProvinceName	    = Italy
localityName		    = ###LOCALITA###
organizationName	    = ###ORGANIZZAZIONE###
commonName		        = "Eduroam Root ###ORGANIZZAZIONE###"
emailAddress		    = ###EMAIL###

[v3_ca]
subjectKeyIdentifier	= hash
authorityKeyIdentifier	= keyid:always,issuer:always
basicConstraints	    = critical,CA:true
keyUsage                = critical, digitalSignature, cRLSign, keyCertSign
crlDistributionPoints	= URI:http://www.example.org/example_ca.crl

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier  = keyid:always

  • Modificare la configurazione per la creazione del certificato server server.cnf valorizzando gli attributi ###LOCALITA###, ###ORGANIZZAZIONE###, ###EMAIL### e ###FQDN_RADIUS### facendo particolare attenzione a valorizzare correttamente il valore ###FQDN_RADIUS### nella sezione req_distinguished_name e nella sezione alt_names

[ ca ]
default_ca		        = CA_default

[ CA_default ]
dir			            = ./
certs			        = $dir
crl_dir			        = $dir/crl
database		        = $dir/index.txt
new_certs_dir	        = $dir
certificate		        = $dir/ca.pem
serial			        = $dir/serial
crl			            = $dir/crl.pem
private_key		        = $dir/ca.key
RANDFILE		        = $dir/.rand
name_opt		        = ca_default
cert_opt		        = ca_default
default_days		    = 3600
default_crl_days	    = 30
crl_extensions          = crl_ext
default_md		        = sha256
preserve		        = no
policy			        = policy_match
crlDistributionPoints	= URI:http://www.example.org/example_ca.crl
name_opt                = ca_default
cert_opt                = ca_default


[ policy_match ]
countryName		        = match
stateOrProvinceName	    = match
organizationName	    = match
organizationalUnitName	= optional
commonName		        = supplied
emailAddress		    = optional

[ policy_anything ]
countryName		        = optional
stateOrProvinceName	    = optional
localityName		    = optional
organizationName	    = optional
organizationalUnitName	= optional
commonName		        = supplied
emailAddress		    = optional

[ req ]
prompt                  = no
input_password          = whatever
output_password         = whatever
default_bits            = 2048
distinguished_name      = req_distinguished_name
req_extensions          = req_ext
x509_extensions         = req_ext

[ req_distinguished_name ]
countryName             = IT
stateOrProvinceName     = Italy
localityName		    = ###LOCALITA###
organizationName	    = ###ORGANIZZAZIONE###
commonName		        = ###FQDN_RADIUS###
emailAddress		    = ###EMAIL###

[ req_ext ]
subjectKeyIdentifier    = hash
subjectAltName          = @alt_names
basicConstraints        = critical,CA:false
keyUsage                = critical,digitalSignature,keyEncipherment
extendedKeyUsage        = serverAuth
crlDistributionPoints   = URI:http://www.example.com/example_ca.crl

[ alt_names ]
DNS.1                   = ###FQDN_RADIUS###

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier  = keyid:always
  • Modificare il file Makefile come di seguito indicato:

######################################################################
#
#	Make file to be installed in /etc/raddb/certs to enable
#	the easy creation of certificates.
#
#	See the README file in this directory for more information.
#
#	$Id: ef243c9b3719af58690bf48bcbb532eaa96099dd $
#
######################################################################

DH_KEY_SIZE	= 2048
OPENSSL		= openssl

#
#  Set the passwords
#
-include passwords.mk

######################################################################
#
#  Make the necessary files, but not client certificates.
#
######################################################################
.PHONY: all
all: index.txt serial dh server ca client

.PHONY: client
client: client.pem

.PHONY: ca
ca: ca.der

.PHONY: server
server: server.pem server.vrfy

.PHONY: verify
verify: server.vrfy client.vrfy

passwords.mk: server.cnf ca.cnf client.cnf
	@echo "PASSWORD_SERVER	= '$(shell grep output_password server.cnf | sed 's/.*=//;s/^ *//')'"		> $@
	@echo "PASSWORD_CA	= '$(shell grep output_password ca.cnf | sed 's/.*=//;s/^ *//')'"		>> $@
	@echo "PASSWORD_CLIENT	= '$(shell grep output_password client.cnf | sed 's/.*=//;s/^ *//')'"		>> $@
	@echo "USER_NAME	= '$(shell grep emailAddress client.cnf | grep '@' | sed 's/.*=//;s/^ *//')'"	>> $@
	@echo "CA_DEFAULT_DAYS  = '$(shell grep default_days ca.cnf | sed 's/.*=//;s/^ *//')'"			>> $@

######################################################################
#
#  Diffie-Hellman parameters
#
######################################################################
dh:
	$(OPENSSL) dhparam -out dh -2 $(DH_KEY_SIZE)

######################################################################
#
#  Create a new self-signed CA certificate
#
######################################################################
ca.key ca.pem: ca.cnf
	@[ -f index.txt ] || $(MAKE) index.txt
	@[ -f serial ] || $(MAKE) serial
	$(OPENSSL) req -new -x509 -keyout ca.key -out ca.pem \
		-days $(CA_DEFAULT_DAYS) -config ./ca.cnf
	chmod g+r ca.key

ca.der: ca.pem
	$(OPENSSL) x509 -inform PEM -outform DER -in ca.pem -out ca.der

######################################################################
#
#  Create a new server certificate, signed by the above CA.
#
######################################################################
server.csr server.key: server.cnf
	$(OPENSSL) req -new  -out server.csr -keyout server.key -config ./server.cnf
	chmod g+r server.key

server.crt: server.csr ca.key ca.pem
	$(OPENSSL) ca -batch -keyfile ca.key -cert ca.pem -in server.csr  -key $(PASSWORD_CA) -out server.crt -extensions req_ext -config ./server.cnf

server.p12: server.crt
	$(OPENSSL) pkcs12 -export -in server.crt -inkey server.key -out server.p12  -passin pass:$(PASSWORD_SERVER) -passout pass:$(PASSWORD_SERVER)
	chmod g+r server.p12

server.pem: server.p12
	$(OPENSSL) pkcs12 -in server.p12 -out server.pem -passin pass:$(PASSWORD_SERVER) -passout pass:$(PASSWORD_SERVER)
	chmod g+r server.pem

.PHONY: server.vrfy
server.vrfy: ca.pem
	@$(OPENSSL) verify -CAfile ca.pem server.pem

######################################################################
#
#  Create a new client certificate, signed by the the above server
#  certificate.
#
######################################################################
client.csr client.key: client.cnf
	$(OPENSSL) req -new  -out client.csr -keyout client.key -config ./client.cnf
	chmod g+r client.key

client.crt: client.csr ca.pem ca.key
	$(OPENSSL) ca -batch -keyfile ca.key -cert ca.pem -in client.csr  -key $(PASSWORD_CA) -out client.crt -extensions xpclient_ext -extfile xpextensions -config ./client.cnf

client.p12: client.crt
	$(OPENSSL) pkcs12 -export -in client.crt -inkey client.key -out client.p12  -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT)
	chmod g+r client.p12

client.pem: client.p12
	$(OPENSSL) pkcs12 -in client.p12 -out client.pem -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT)
	chmod g+r client.pem
	cp client.pem $(USER_NAME).pem

.PHONY: client.vrfy
client.vrfy: ca.pem client.pem
	c_rehash .
	$(OPENSSL) verify -CApath . client.pem

######################################################################
#
#  Miscellaneous rules.
#
######################################################################
index.txt:
	@touch index.txt

serial:
	@echo '01' > serial

print:
	$(OPENSSL) x509 -text -in server.crt

printca:
	$(OPENSSL) x509 -text -in ca.pem

clean:
	@rm -f *~ *old client.csr client.key client.crt client.p12 client.pem

#
#	Make a target that people won't run too often.
#
destroycerts:
	rm -f *~ dh *.csr *.crt *.p12 *.der *.pem *.key index.txt* \
			serial*  *\.0 *\.1
  • Ricreare i certificati

make ca.pem
make server.pem

cui

Per Identity Provider e Resource Provider

Modificare il file policy.d/cui che gestisce la richiesta e la generazione dell'attributo Chargeable-User-Identity.

cui_hash_key = "###CHANGEME###"


cui_require_operator_name = "yes"
cui.authorize {
	if ("%{client:add_cui}" == 'yes') {
		update request {
			&Chargeable-User-Identity := 0x00
		}
	}
}
cui.pre-proxy {
	if (("%{request:Packet-Type}" == 'Access-Request') && ("%{client:add_cui}" == 'yes')) {
		update proxy-request {
			&Chargeable-User-Identity = 0x00
		}
	}
}
cui.post-auth {
	if (!&control:Proxy-To-Realm && &Chargeable-User-Identity && !&reply:Chargeable-User-Identity && \
		(&Operator-Name || ('${policy.cui_require_operator_name}' != 'yes')) ) {
		update reply {
			&Chargeable-User-Identity = "%{sha1:${policy.cui_hash_key}%{tolower:%{Stripped-User-Name}%{%{Operator-Name}:-}}}"
		}
	}
	#if (&reply:Chargeable-User-Identity) {
	#	update {
	#		&reply:User-Name := &request:User-Name
	#	}
	#	cuisql
	#}
}
cui-inner.post-auth {
	if (&outer.request:Chargeable-User-Identity && \
		(&outer.request:Operator-Name || ('${policy.cui_require_operator_name}' != 'yes'))) {
		update reply {
			&Chargeable-User-Identity := "%{sha1:${policy.cui_hash_key}%{tolower:%{Stripped-User-Name}%{%{outer.request:Operator-Name}:-}}}"
		}
	}
}
cui.accounting {
	if (!&Chargeable-User-Identity) {
		update request {
			&Chargeable-User-Identity := "%{cuisql:\
			SELECT cui FROM cui \
			WHERE clientipaddress = '%{%{Packet-Src-IPv6-Address}:-%{Packet-Src-IP-Address}}' \
			AND callingstationid = '%{Calling-Station-Id}' \
			AND username = '%{User-Name}'}"
		}
	}
	if (&Chargeable-User-Identity && (&Chargeable-User-Identity != '')) {
		cuisql
	}
}

Filtri

Solo Resource Provider

Al fine di prevenire autenticazioni che de facto sono errate e quindi non ha senso che transitino sulla federazione eduroam, creare il seguente filtro policy.d/eduroam-realm-checks

filter_eduroam_realms {
	if (&User-Name) {

		#*********************************************************#
		# Prima Parte
		# ~~~~~~~~~~~
		#
		# In questa sezione sono elencati i realm che non sono validi
		#
		#*********************************************************#

		# Richiesta di autenticazione senza dominio, ma con sola User-Name
		if(!(&User-Name =~ /@/)){
			update reply {
				Reply-Message := "Your User-Name is invalid (no realm)"
			}
			reject
		}

		# Richiesta di autenticazione nel formato username@, cioè senza 
		# un dominio valido
		if(&User-Name =~ /@$/){
			update reply {
				Reply-Message := "Your realm is invalid (it is blank)"
			}
			reject
		}

		# Presenza di più domini (più @)
		if(&User-Name =~ /@.+?@/){
			update reply {
				Reply-Message := "Your realm is invalid (more than one @)"
			}
			reject
		}

		# Dominio con caratteri non consentiti
		if(&User-Name =~ /@.+?[^[:alnum:]\.-]/){
			update reply {
				Reply-Message := "Your realm is invalid (contains not alphanumeric, hyphen or period)"
			}
			reject
		}

		# Dominio che inizia con un punto o un trattino
		if(&User-Name =~ /@[\.-]/){
			update reply {
				Reply-Message := "Your realm is invalid (begins with a period or hyphen)"
			}
			reject
		}

		# Dominio che finisce con un punto o trattivo
		if(&User-Name =~ /@.+?[\.-]$/){
			update reply {
				Reply-Message := "Your realm is invalid (ends with a period or hyphen)"
			}
			reject
		}

		# Dominio in cui non è presente almeno un punto
		if(&User-Name =~ /@[^\.]+$/){
			update reply {
				Reply-Message := "Your realm is invalid (does not contain a period)"
			}
			reject
		}

		# Dominio che ha più punti in sequenza
		if(&User-Name =~ /@.+?\.\./){
			update reply {
				Reply-Message := "Your realm is invalid (contains sequential periods)"
			}
			reject
		}


		#*********************************************************#
		# Seconda parte
		# ~~~~~~~~~~~~~
		#
		# Domini che, seppur sintatticamente validi,
		# non sono validi all'interno della federazione eduroam
		#
		#*********************************************************#

		# myabc.com tipicamente utilizzato dai supplicant Intel
		if(&User-Name =~ /@myabc\.com$/i){
			update reply {
				Reply-Message := "Your realm is invalid (it is myabc.com)"
			}
			reject
		}

		# 3gppnetwork.org, another common default realm
		if(&User-Name =~ /@wlan\.[[:alnum:]]+\.[[:alnum:]]+\.3gppnetwork\.org$/i){
			update reply {
				Reply-Message := "Your realm is invalid (it matches a wlan. subrealm of 3gppnetwork.org)"
			}
			reject
		}

		# gmail.com e gmail.co.??
		if (&User-Name =~ /@gmail\.co(m|\.[[:alnum:]][[:alnum:]])$/i){
			update reply {
				Reply-Message := "Your realm is invalid (looks like a Gmail domain)"
			}
			reject
		}

		# yahoo.com e yahoo.co.??
		if (&User-Name =~ /@yahoo\.co(m|\.[[:alnum:]][[:alnum:]])$/i){
			update reply {
				Reply-Message := "Your realm is invalid (looks like a Yahoo domain)"
			}
			reject
		}

		# hotmail.com e hotmail.co.??
		if (&User-Name =~ /@hotmail\.co(m|\.[[:alnum:]][[:alnum:]])$/i){
			update reply {
				Reply-Message := "Your realm is invalid (looks like a Hotmail domain)"
			}
			reject
		}

	}
}

Logging

Per Identity Provider e Resource Provider

Per configurare FreeRADIUS affinché le autenticazioni siano loggate su una sola riga invece che su più righe come avviene di default, creare il modulo mods-available/eduroam_logging.

linelog eduroam_log { 
	filename = ${logdir}/eduroam-log 
	format = "" 
	reference = "eduroam_log.%{%{reply:Packet-Type}:-format}" 
	eduroam_log { 
		Access-Accept = "%S eduroam-auth USER=%{User-Name} ORG=%{request:Realm} CSI=%{%{Calling-Station-Id}:-Unknown Caller Id} NAS=%{%{Called-Station-Id}:-Unknown Access Point} CUI=%{%{reply:Chargeable-User-Identity}:-Unknown} MSG=%{%{EAP-Message}:-No EAP Message} RESULT=OK" 
		Access-Reject = "%S eduroam-auth USER=%{User-Name} ORG=%{request:Realm} CSI=%{%{Calling-Station-Id}:-Unknown Caller Id} NAS=%{%{Called-Station-Id}:-Unknown Access Point} CUI=%{%{reply:Chargeable-User-Identity}:-Unknown} MSG=%{%{reply:Reply-Message}:-No Failure Reason} RESULT=FAIL" 
	} 
}

# 
# SOLO IDENTITY PROVIDER
#
linelog eduroam_inner_log { 
	filename = ${logdir}/eduroam-log-inner 
	format = "" 
	reference = "inner_auth_log.%{%{reply:Packet-Type}:-format}" 
	inner_auth_log { 
		Access-Accept = "%S user-auth USER=%{User-Name} VISINST=%{request:Operator-Name} CSI=%{%{Calling-Station-Id}:-Unknown Caller Id} NAS=%{%{Called-Station-Id}:-Unknown Access Point} CUI=%{%{%{reply:Chargeable-User-Identity}:-%{outer.reply:Chargeable-User-Identity}}:-Local User} RESULT=OK" 
		Access-Reject = "%S user-auth USER=%{User-Name} VISINST=%{request:Operator-Name} CSI=%{%{Calling-Station-Id}:-Unknown Caller Id} NAS=%{%{Called-Station-Id}:-Unknown Access Point} CUI=%{%{%{reply:Chargeable-User-Identity}:-%{outer.reply:Chargeable-User-Identity}}:-Local User} RESULT=FAIL" 
	} 
}

ed abilitarlo creando un link in mods-enabled.

cd /etc/freeradius/mods-enabled
ln -s ../mods-available/eduroam_logging .

Proxy degli attributi

Per Identity Provider e Resource Provider

Affinché FreeRADIUS invii alla federazione eduroam tutti gli attributi obbligatori, è necessario modificare i file pre-proxy e post-proxy

Pre-proxy

Modificare il file mods-config/attr_filter/pre-proxy con il seguente contenuto:

DEFAULT
	User-Name =* ANY,
	EAP-Message =* ANY,
	Message-Authenticator =* ANY,
	NAS-IP-Address =* ANY,
	NAS-Identifier =* ANY,
	NAS-Port-Type =* ANY,
	State =* ANY,
	Proxy-State =* ANY,
	Operator-Name =* ANY,
	Class =* ANY,
	Calling-Station-Id =* ANY,
	Called-Station-Id =* ANY,
	Chargeable-User-Identity =* ANY

Post-proxy

Modificare il file mods-config/attr_filter/post-proxy con il seguente contenuto:

DEFAULT
	Reply-Message =* ANY,
	Proxy-State =* ANY,
	EAP-Message =* ANY,
	Message-Authenticator =* ANY,
	MS-MPPE-Recv-Key =* ANY,
	MS-MPPE-Send-Key =* ANY,
	State =* ANY,
	Calling-Station-Id =* ANY,
	Operator-Name =* ANY,
	User-Name =* ANY,
	Class =* ANY,
	Chargeable-User-Identity =* ANY