######################################################################
#
#  RADIUS over TLS (radsec) with TLS-PSK
#
#  This is a minimal virtual site config to get TLS-PSK working in 
#  FreeRADIUS 3.2.x. It is based on the stock sites-available/tls 
#  virtual site, with all but the unnecessary configuration stripped out.
#  USE AT YOUR OWN RISK.
#
#  This config is pre-configured for the South African eduroam NRO
#
#  Note it is possible to distinguish between connections which have
#  TLS enables, and ones which do not.  The expansion:
#
#       %{listen:tls}
#
#  Will return "yes" if the connection has TLS enabled.  It will
#  return "no" if TLS is not enabled for a particular listen section.
#
######################################################################

listen {
	ipaddr = *
	port = 2083
	type = auth+acct
	proto = tcp
	virtual_server = eduroam
	#  We have clients specifically for TLS-PSK.
	clients = radsec-psk
	nonblock = yes

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

	tls {
		##
		## This authorises inbound TLS-PSK connections. Contrary to what the
		## sample sites-available/tls suggests, using psk_identity & psk_hexphrase
		## here doesn't seem to work (it is ignored). You must use psk_query to
		## dynamically look up a PSK key per connection. You can use any lookup
		## you like, but it must return a hex encoded version of the PSK key.
		##
		## Per draft-ietf-radext-tls-psk, the PSK identity should be in the form
		## of a network access identifier. The local part should be opaque and
		## the realm should reflect this RADIUS server. i.e:
		##  some-opaque-client-id@radius.example.ac.za
		## The actual PSK key should be at least 16 bytes (preferably longer) 
		## and should be a random string. See suggested way of generating below.
		##
		## To make the psqk_query example below work, you need to create and
		## enable mods-available/psksql like this:
		##
		##  sql psksql {
		##  	driver = "rlm_sql_sqlite"
		##  	sqlite {
		##  		filename = "${raddbdir}/psksql.db"
		##  }
		##
		## and then create the SQLite database:
		##
		##  PSK_KEY=$(dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64)
		##  PSK_ID_LOCAL=$(uuidgen)
		##  PSK_ID_REALM=$(hostname -f)
		##  ( \
		##    echo 'CREATE TABLE IF NOT EXISTS "psk_keys" (keyid TEXT UNIQUE, key TEXT);'; \
		##    printf 'INSERT INTO "psk_keys" VALUES("%s@%s", "%s");\n' "$PSK_ID_LOCAL" "$PSK_ID_REALM" "$PSK_KEY" \
		##  ) | sqlite3 /path/to/psksql.db
		##
		psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}"

		fragment_size = 8192
		cipher_list = "DEFAULT"
		# draft-ietf-radext-tls-psk suggests you should only use one TLS version
		tls_min_version = "1.3"
		tls_max_version = "1.3"
		require_client_cert = no

		# These must be defined or FreeRADIUS terminates with an error. However,
		# they're not actually used for TLS-PSK ;-). So use the defaults.
		private_key_password = whatever
		private_key_file = ${certdir}/server.pem
		certificate_file = ${certdir}/server.pem
		ca_file = ${cadir}/ca.pem
	}
}

##
## The radsec-psk clients section applies IP limits to the clients we'll
## accept PSK authentication from, separate from clients.conf. This is best
## practice, as it limits brute force attempts against your RADIUS. You can
## add your own TLS-PSK capable NAS devices.
##
clients radsec-psk {
	client 127.0.0.1 {
		ipaddr = 127.0.0.1
		proto = tls
		secret = radsec
	}
	#client antarctica-access-point-1 {
	#	ipaddr = 172.25.1.55
	#	proto = tls
	#	secret = radsec
	#}

	##
	## These are the eduroam FLR servers for South Africa
	##
	client flr-cpt.eduroam.ac.za {
		ipaddr = 155.232.195.20
		proto = tls
		secret = radsec
		shortname = za-flr-cpt
	}
	client flr-jnb.eduroam.ac.za {
		ipaddr = 155.232.195.21
		proto = tls
		secret = radsec
		shortname = za-flr-jnb
	}
}

##
## Now we need to handle outbound connections that we proxy to other
## servers. This works like the home_server config in proxy.conf
##
home_server za-flr-cpt-tlspsk {
	ipaddr = 155.232.195.20
	port = 2083
	type = auth+acct
	proto = tcp
	secret = radsec
	nonblock = yes

	tls {
		##
		## Set this to match the PSK identity and key you got from the NRO
		##
		## You can generate the required psk_hexphrase from your cleartext key:
		##   echo -n 'testing1234567890' | xxd -p
		##
		psk_identity = "54d29ac6-3e8a-43e1-a50c-856873cbe629@flrs.eduroam.ac.za"
		psk_hexphrase = "74657374696E6731323334353637383930"
		fragment_size = 8192
		cipher_list = "DEFAULT"
		tls_min_version = "1.3"
		tls_max_version = "1.3"
		connect_timeout = 30
	}
}

home_server za-flr-jnb-tlspsk {
	ipaddr = 155.232.195.21
	port = 2083
	type = auth+acct
	proto = tcp
	secret = radsec
	nonblock = yes


	tls {
		## Set this to match the PSK identity and key you got from the NRO
		psk_identity = "54d29ac6-3e8a-43e1-a50c-856873cbe629@flrs.eduroam.ac.za"
		psk_hexphrase = "74657374696E6731323334353637383930"
		fragment_size = 8192
		cipher_list = "DEFAULT"
		tls_min_version = "1.3"
		tls_max_version = "1.3"
		connect_timeout = 30
	}
}

home_server_pool eduroam-tlspks {
	type = fail-over
	#
	# The order of the home_server entries in the pool is important.
	# In South Africa, you should put the one that's geographically
	# closest to you (i.e. has the lowest ping time/latency) at the
	# top of the list so you try it first.
	#
	home_server = za-flr-cpt-tlspsk
	home_server = za-flr-jnb-tlspsk
}

#  You should define you local realms in proxy.conf
#
#  realm example.ac.za {
#  }
#
#  realm "~.+\\.example\\.ac\\.za$" {
#  }

# The default destination for unknown realms - forward to the upstream FLR servers
# The regex version is required for f_ticks to log properly
realm "~.+$" {
	auth_pool = eduroam-tlspks
	nostrip
}
