Issue with dynamic home server and duplicate server ipaddr on 3.2.8
I've come across an issue with dynamic home_servers for supporting OpenRoaming connections. In `authorize`, we use the following code to check if it's our home domain, if the 'home_server' already exists, or if we need to dynamically query which radsec server to proxy to: -------------------------------- openroaming_lookup { if (&control:Proxy-To-Realm || &control:Home-Server-Name) { return } if (&User-Name && &User-Name =~ /home.domain/) { return } elsif (&User-Name && &User-Name =~ /@(.*)$/) { switch "%{home_server_dynamic:%{1}}" { case "1" { # Proxy to this one particular home server update control { &Home-Server-Name := "%{1}" } } case "0" { # Proxy with home server pool, failover, etc. update control { &Proxy-To-Realm := "%{1}" } } case { # no home server exists, ask DNS update control { &Temp-Home-Server-String := `%{config:confdir}/mods-config/realm/freeradius-naptr-to-home-server.sh -d %{config:confdir} %{1} aaa+auth:radius> } if (&control:Temp-Home-Server-String == "" ) { reject } else { update control { &Home-Server-Name := "%{1}" } } } } } } -------------------------------- This generally works well. For a new (unknown home server), we call the below mods-config/realm/freeradius-naptr-to-home-server.sh script to perform the dynamic discovery: -------------------------------- #!/bin/sh usage() { echo "Usage: ${0} [OPTIONS] <realm> <optional NAPTR tag>" echo " -d RADIUS_DIR Set radius directory" echo " -t test (skip running radmin)" exit 1 } test -n "${1}" || usage RADDB=/usr/local/etc/raddb RADMIN=y while [ `echo "$1" | cut -c 1` = "-" ] do case "$1" in -d) RADDB=$2 shift;shift ;; -t) RADMIN= shift ;; *) usage ;; esac done test -n "${2}" && NAPTRTAG="${2}" || NAPTRTAG="x-eduroam:radius.tls" DIGCMD=$(command -v dig) HOSTCMD=$(command -v host) PRINTCMD=$(command -v printf) validate_host() { echo ${@} | tr -d '\n\t\r' | grep -E '^[_0-9a-zA-Z][-._0-9a-zA-Z]*$' } validate_port() { echo ${@} | tr -d '\n\t\r' | grep -E '^[0-9]+$' } dig_it_srv() { ${DIGCMD} +short srv $SRV_HOST | sort -n -k1 | while read line; do set $line PORT=$(validate_port $3) HOST=$(validate_host $4) if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then $PRINTCMD "\tipaddr = ${HOST%.}\n\tport = ${PORT}\n" fi done } dig_it_naptr() { ${DIGCMD} +short naptr "${REALM}" | grep $NAPTRTAG | sort -n -k1 | while read line; do set $line TYPE=$3 HOST=$(validate_host $6) if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then SRV_HOST=${HOST%.} dig_it_srv fi done } host_it_srv() { ${HOSTCMD} -t srv $SRV_HOST | sort -n -k5 | while read line; do set $line PORT=$(validate_port $7) HOST=$(validate_host $8) if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then $PRINTCMD "\tipaddr ${HOST%.}:${PORT}\n" fi done } host_it_naptr() { ${HOSTCMD} -t naptr "${REALM}" | grep $NAPTRTAG | sort -n -k5 | while read line; do set $line TYPE=$7 HOST=$(validate_host ${10}) if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then SRV_HOST=${HOST%.} host_it_srv fi done } REALM=$(validate_host ${1}) if [ -z "${REALM}" ]; then echo "realm \"${1}\" failed validation" >&2 usage fi if [ -x "${DIGCMD}" ]; then SERVERS=$(dig_it_naptr) elif [ -x "${HOSTCMD}" ]; then SERVERS=$(host_it_naptr) else echo "${0} requires either \"dig\" or \"host\" command." >&2 exit 1 fi if [ ! -n "${SERVERS}" ]; then echo "No servers found" >&2 exit 1 fi if [ -z "${RADMIN}" ]; then $PRINTCMD "home_server ${REALM} {\n${SERVERS}\n\t\$INCLUDE tls.conf\n}\n" exit 0 fi HOME_SERVER_FILE="$RADDB/home_servers/$1" if [ -f "$HOME_SERVER_FILE" ]; then echo "Home server file $HOME_SERVER_FILE already exists. Skipping creation and radmin command." >&2 else echo "Creating new home server file $HOME_SERVER_FILE." >&2 $PRINTCMD "home_server ${REALM} {\n${SERVERS}\n\t\$INCLUDE tls.conf\n}\n" > "$HOME_SERVER_FILE" /usr/local/sbin/radmin -e "add home_server file $HOME_SERVER_FILE" fi echo $1 -------------------------------- Again, this works well. It creates a new file in the home_servers folder, and radmin adds it to the server to use immediately. The problem arises if we have an authentication request from a new realm but the "server" is one that we already have a reference to, from a previously added dynamic home server definition. For example, an authentication request comes in with a realm of davidlloyd.openroaming.net and the script generates the following home server config: # cat home_servers/davidlloyd.openroaming.net home_server davidlloyd.openroaming.net { ipaddr = idpeu.openroaming.net port = 2083 $INCLUDE tls.conf } This new home server was then added via radmin, and everything was ok. The request is proxied to that new server. So far, so good. Later, another authentication request comes in with a realm of eu-sdk.openroaming.net, and the script generates the following home server config: # cat home_servers/eu-sdk.openroaming.net home_server eu-sdk.openroaming.net { ipaddr = idpeu.openroaming.net port = 2083 $INCLUDE tls.conf } However, this failed to add via radmin, because the "ipaddr" is the same as a previously defined dynamic home server, and the authentication fails as it doesn't proxy the request. ipaddr = idpeu.openroaming.net <<<< this The error thrown by radmin is: # radmin -e "add home_server file /usr/local/etc/raddb/home_servers/ davidlloyd.openroaming.net" ERROR: Unable to add home server - Failed adding home_server to the internal data structures This doesn't just happen for "openroaming" hosted realms either. Take cityroam in Japan for example. They have multiple realms too, but the same servers: # cat home_servers/*city* home_servers/jwa.bemap.cityroam.jp: home_server jwa.bemap.cityroam.jp { ipaddr = jpgw4.cityroam.jp port = 2083 ipaddr = jpgw.cityroam.jp port = 2083 $INCLUDE tls.conf } home_servers/w-jp1.wi2.cityroam.jp: home_server w-jp1.wi2.cityroam.jp { ipaddr = jpgw4.cityroam.jp port = 2083 ipaddr = jpgw.cityroam.jp port = 2083 $INCLUDE tls.conf } It's like we need a way to set servers and then map multiple realms to the same server (as traditionally done in proxy.conf)? How can we best solve this issue? Is there another method for doing this besides the one above? We can't statically define these servers (as the whole point of openroaming is to dynamic proxy to the resolved servers, which may change), and we'll never know what user realm may hit us next will be, and they will probably share servers. Thanks, James -- Visit purple.ai <https://purple.ai/> Purple on LinkedIn <https://uk.linkedin.com/company/purple-wifi> Email disclaimer <http://www.purple.ai/email-disclaimer/>
On Mar 16, 2026, at 4:29 PM, James Wood via Freeradius-Users <freeradius-users@lists.freeradius.org> wrote:
... However, this failed to add via radmin, because the "ipaddr" is the same as a previously defined dynamic home server, and the authentication fails as it doesn't proxy the request.
The existing scripts are set up to tie one domain to one home server. As you've seen, they need updating to work with more complex situations.
It's like we need a way to set servers and then map multiple realms to the same server (as traditionally done in proxy.conf)?
How can we best solve this issue? Is there another method for doing this besides the one above?
Off of the top of my head, you'll have to define home servers by IP address, and not domain name. i.e. do the IP address lookup in the shell script, and then write out home server name / ipaddr which the actual IPv4 address. Then separately, have a mapping of realms to IP addresses. That mapping can go into a database, for example. Alan DeKok.
Thanks Alan. I have been working on this and think I've come up with a solution, at least for now. I've modified both the authorize code and the lookup script. The way it now works is as follows: When a new auth request comes in and we perform the DNS lookup, instead of creating the home server with the realm name, I am creating it with the returned hostname. I then write the realm name and the associated home server to a cache file. When another request arrives from an unknown realm, if the returned DNS hostname matches an existing server hostname/ip, we map that realm to the previous home server. We regularly update the home servers and associated DNS/IPs of the home servers too (in general). Would it be possible to add support in radmin to dynamically create realms/pools as well as home servers? That way, we can create a single server and assign multiple realms to it etc. Thanks, James -- Visit purple.ai <https://purple.ai/> Purple on LinkedIn <https://uk.linkedin.com/company/purple-wifi> Email disclaimer <http://www.purple.ai/email-disclaimer/>
participants (2)
-
Alan DeKok -
James Wood