Linux Install Memo

サーバー管理者によるLinux関連ソフトのインストールメモ

Home » □FreeRADIUSでradutmpベース(というか、NASを参照しない)での同時接続制限(Simultaneous-Use := 1)

□FreeRADIUSでradutmpベース(というか、NASを参照しない)での同時接続制限(Simultaneous-Use := 1)

タイトルは長いが、まぁやりたいことを書くとこういう事。

FreeRADIUSで「同時接続制限(Simultaneous-Use := 1)」(のテスト)をしようとすると
checkrad(Perlのスクリプト)が呼び出されて、その結果によりOK/NGを返すわけだが、
当然実機がないと(もしくは実機にアクセスできないと)、テストができない。

で、処理の流れ的にclient.confにnas_typeをいろいろ書かないと、そもそも同時接続
制限はできないということになっている。

radiusd -Xで起動して、処理の流れを見ると判るが、

--------------------------------
	:
(0) # Executing section session from file /etc/raddb/sites-enabled/default
(0)   session {
(0)  radutmp : EXPAND /var/log/radius/radutmp
(0)  radutmp :    --> /var/log/radius/radutmp
(0)  radutmp : EXPAND %{User-Name}
(0)  radutmp :    --> USER-ID
checkrad: No NAS type, or type "other" not checking
(0)   [radutmp] = fail
(0)  } #  session = fail
	:
--------------------------------

ということで、NASタイプが設定されていないか、otherになっていると、チェックを
しない。

まぁ確かにradutmpの情報が正しいかどうかは疑わしいところだし、RADIUSを複数台
動かしておく場合には接続情報をどこで保持するのか、ということになるのであれだ
けどね。

まぁその辺「テストがしたい」と割り切るのであれば、checkradを適当にいじればいい。

checkradの最後の方を見ると、

--------------------------------
	:
} elsif ($ARGV[0] eq 'dot1x'){
        $ret = &dot1x_snmp;
} elsif ($ARGV[0] eq 'other') {
        $ret = 1;
} else {
        print LOG "  checkrad: unknown NAS type $ARGV[0]\n" if ($debug);
        print STDERR "checkrad: unknown NAS type $ARGV[0]\n";
        $ret = 2;
}
	:
--------------------------------

というように、第一引数($ARGV[0])によりいろいろ処理しているが、otherの場合は
1を返すようになっているのに、そもそもfreeRADIUS自体の方でotherなら同時接続の
チェックをしないようになっているのだからなぁ…

というわけで、ここに

--------------------------------
	:
} elsif ($ARGV[0] eq 'dot1x'){
        $ret = &dot1x_snmp;
} elsif ($ARGV[0] eq 'other') {
        $ret = 1;
} elsif ($ARGV[0] eq 'simltest') {
        $ret = 1;
} else {
        print LOG "  checkrad: unknown NAS type $ARGV[0]\n" if ($debug);
        print STDERR "checkrad: unknown NAS type $ARGV[0]\n";
        $ret = 2;
}
	:
--------------------------------

とか追加してみる。もちろんclient.confにも

--------------------------------
client localhost {
        ipaddr = 127.0.0.1
        secret = gotorun
        nas_type = simltest
}
--------------------------------

としてみる。

これで、誰かが接続している状態を作り出して、

cat > /test_login

--------------------------------
Acct-Status-Type = Start
Acct-Session-Id = 1111111111
User-Name = USER-ID
NAS-Port = 1
Framed-IP-Address = 1.1.1.1
Caller-Id = 1111111111
--------------------------------

radclient -x -f ./test_login localhost acct gotorun

radlastで

--------------------------------
USER-ID 001:localhos 1.1.1.1          Tue Jun  7 11:41   still logged in
--------------------------------

接続中である状態になっていることを確認したら、別途radtestで

radtest USER-ID PASSWORD localhost 1 gotorun

としてみると…

--------------------------------
	:
(1) # Executing section session from file /etc/raddb/sites-enabled/default
(1)   session {
(1)  radutmp : EXPAND /var/log/radius/radutmp
(1)  radutmp :    --> /var/log/radius/radutmp
(1)  radutmp : EXPAND %{User-Name}
(1)  radutmp :    --> USER-ID
(1)   [radutmp] = fail
(1)  } #  session = fail
(1) Login OK: [USER-ID/PASSWORD] (from client localhost port 1)
	:
--------------------------------

と、radutmp(session)としてはfailなのに、Login OKとなってしまう。

これにはからくりがあり、中の人が

http://freeradius.1045715.n5.nabble.com/Trying-to-restrict-simultaneous-use-td5739700.html

で、「Because it’s fail-safe.」とか言ってしまっている。

いやね、fail-safeにする必要ないのだけど(同時接続制限の動作確認したいから)、
そのための設定とか作ってくれよ。

というのも、該当部分のソースを確認すると、

/usr/src/freeradius-server-3.0.4/src/main/modules.c

--------------------------------
	:
#ifdef WITH_SESSION_MGMT
/*
 *      See if a user is already logged in.
 *
 *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
 */
int process_checksimul(int sess_type, REQUEST *request, int maxsimul)
{
        rlm_rcode_t rcode;

        if(!request->username)
                return 0;

        request->simul_count = 0;
        request->simul_max = maxsimul;
        request->simul_mpp = 1;

        rcode = indexed_modcall(RLM_COMPONENT_SESS, sess_type, request);

        if (rcode != RLM_MODULE_OK) {
                /* FIXME: Good spot for a *rate-limited* warning to the log */
                return 0;
        }

        return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
}
#endif
	:
--------------------------------

で、indexed_modcall()でいろいろな(radutmp意外にもsqlとかでも)、とにかく
RLM_MODULE_OK(=2)以外が返ってきたとしても「return 0;」、つまりOKを返して
しまっている。

※ちなみにradutmpで同時接続が確認されたときのrcodeは1で、RLM_MODULE_OK(=2)
とは明らかに異なっている。

これはなぁ…。

ちなみにこれを調査しているときの最新?のVer.3.0.11のソースを見てみると、

/usr/src/freeradius-server-3.0.11/src/main/modules.c

--------------------------------
	:
#ifdef WITH_SESSION_MGMT
/*
 *      See if a user is already logged in.
 *
 *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
 */
int process_checksimul(int sess_type, REQUEST *request, int maxsimul)
{
        rlm_rcode_t rcode;

        if(!request->username)
                return 0;

        request->simul_count = 0;
        request->simul_max = maxsimul;
        request->simul_mpp = 1;

        rcode = indexed_modcall(MOD_SESSION, sess_type, request);

        if (rcode != RLM_MODULE_OK) {
                /* FIXME: Good spot for a *rate-limited* warning to the log */
                return 0;
        }

        return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
}
#endif
	:
--------------------------------

同じかよ!!

というわけで、「modules.c」の問題のところを

--------------------------------
	:
#ifdef WITH_SESSION_MGMT
/*
 *      See if a user is already logged in.
 *
 *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
 */
int process_checksimul(int sess_type, REQUEST *request, int maxsimul)
{
        rlm_rcode_t rcode;

        if(!request->username)
                return 0;

        request->simul_count = 0;
        request->simul_max = maxsimul;
        request->simul_mpp = 1;

        rcode = indexed_modcall(RLM_COMPONENT_SESS, sess_type, request);

///        if (rcode != RLM_MODULE_OK) {
///                /* FIXME: Good spot for a *rate-limited* warning to the log */
///                return 0;
///        }

        return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
}
#endif
	:
-------------------------------- 

とコメントアウトしてradiusdを作り直せば、ちゃんと同時接続制限が効く。

皆さん、できないできないっていうけどオープンソースなのでソース見てくださいねー。

(っていうか、fail-safeのON/OFFをするパラメータを用意してくれ、Alan DeKokさん…あー疲れた)

Name of author

Name: admin

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です