▼FreeRADIUS 3.0で、EAP-TTLS のトンネル内部のユーザ名をログに残す▼

$Id: freeradius-log-inner.html,v 1.4 2021-05-10 22:11:46+09 kabe Exp $

RADIUS認証で EAP-TTLS を使う場合、ユーザ名は EAPトンネルの「外側」と「内側」に指定できて、

#
#   eapol_test -c ttls-eap-mschapv2.conf -s testing123
#
network={
	ssid="example"
	key_mgmt=WPA-EAP
	eap=TTLS
	identity="vega01"			##「内側」
	anonymous_identity="anonymous"		##「外側」
	password="Passw0rd"
	phase2="autheap=MSCHAPV2"
}
実際の認証には「内側」のユーザ名が使われます。 「外側」のユーザ名は、通常のRADIUSクライアントでは内側と同じものが 設定されますが、認証に使われているわけではなく、平文で流れるので、 anonymous@example.com のように 匿名IDを指定 できる場合もあります。

radiusd.confauth = yes に設定して ログを残すようにしてEAP-TTLS 認証をすると、 以下のように2行に分かれた Login OK が残ります。
Mon May 10 18:41:03 2021 : Auth: (8)   Login OK: [vega01] (from client localhost port 0 via TLS tunnel)
Mon May 10 18:41:03 2021 : Auth: (8) Login OK: [anonymous] (from client localhost port 0 cli 02-00-00-00-00-01)

FreeRADIUS のWiki には、 Recording the inner User-Name という項があって、この設定 (コメントアウトされた形で sites-enabled/inner-tunnel にも入っています) をすれば EAP-TTLS の中の本当のユーザ名をログに残せるとあるのですが、

server inner-tunnel {
    post-auth {
        ...
        update outer.session-state {
            &User-Name := &User-Name
        }
        ...
}

MACアドレスと実ユーザ名との対応を正確にとりたい等、 2行目のユーザ名項にも EAP-TTLS 内の実ユーザ名を残すには、 さらに細工が必要です。


▼session-state リストに実ユーザ名を記録する

sites-available/inner-tunnel には以下のような、 EAP-TTLSトンネルの内側 (inner) の User-Name を保存したいなら コメントを外せ、みたいな箇所がありますが、
#  Post-Authentication
...
post-auth {
	...
	#
	#  If you want the Access-Accept to contain the inner
	#  User-Name, uncomment the following lines.
	#
#	update outer.session-state {
#	       User-Name := &User-Name
#	}
	...
}
まずこの部分を以下のように変えます。
post-auth {
	...
	if (outer.session-state:) {
		update outer.session-state {
		       User-Name := &request:User-Name
		}
	}
	...
}
if (outer.session-state:) は、EAP内部の単体テスト用の radtest user-name password localhost:18120 0 testing123 を動かすために必要です。 この if がないとエラーで止まってしまう。

▼defaultサーバで session-state:User-Name を拾う

sites-available/default に、以下のように reply リストの User-Name を細工している部分があるので、
#  Post-Authentication
#  Once we KNOW that the user has been authenticated, there are
#  additional steps we can take.
post-auth {
	...
	#  If both session-state and reply contain a User-Name attribute, remove
	#  the one in the reply if it is just a copy of the one in the request, so
	#  we don't end up with two User-Name attributes.

	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:
	}
	...
}

この下あたりに、以下を追加します。 sites-available/inner-tunnel でセットした session-state:User-Namerequest:User-Nameに 移し替えます。

ログに残る Login OK:[username] は reply ではなく常に request リストの物が使われるので、それを細工する処理です。

	## Update &request:User-Name to inner-tunnel one.
	## The username logged by auth=yes is the request:User-Name,
	## not reply:User-Name, so update request
	if (session-state:User-Name) {
		update request {
			User-Name := &session-state:User-Name
		}
	}

▼Login OKの2行目にも実ユーザ名が残る

この細工を実施すれば、2行目の Login OK にも実ユーザ名が残るようになります。 (EAPの外側に設定した anonymous@example.com といったユーザ名については ログに残らなくなりますが、普通は不要でしょう)

Mon May 10 19:29:47 2021 : Auth: (8)   Login OK: [vega01] (from client localhost port 0 via TLS tunnel)
Mon May 10 19:29:47 2021 : Auth: (8) Login OK: [vega01] (from client localhost port 0 cli 02-00-00-00-00-01)

かべ@sra-tohoku.co.jp