L or R?

概要

新卒社員であるあなたは先輩社員のお手伝いをすることになりました。先輩社員は次のようなネットワークを作りたいと考えているそうです。

  • 無線接続のユーザと同じように、有線接続のユーザも認証するために802.1X認証をしたい
  • routerの上には、RadiusサーバとLDAPサーバが動いている
  • LDAPサーバでユーザを一元管理しているため、RadiusサーバはLDAPサーバに登録されているユーザ情報を基に通信を認可を行いたい

ある程度先輩社員は設定を行ったそうなのですが、通信が上手くできないそうです。助けてあげてください。

先輩のメモ

  • client1, client2には必要な設定ファイルを用意しておいた
  • switchの設定は上手くいっているはずだから気にしなくていい
  • freeradiusのログには有用なことが書いてあるらしい

client1, client2

これらの機器は、802.1X認証をする機器です。/home/user/wpa_supplicant.confに接続に必要な情報が書かれています。以下のコマンドでサプリカントを起動することができます。/dataに起動時に実行されるインターフェース設定などが書かれたファイルが置かれています。

$ wpa_supplicant -B -D wired -i eth1 -c ./wpa_supplicant.conf
  • /data/setup-interfaces.sh: インターフェース設定を行うためのスクリプト
  • /data/teardown-interfaces.sh: インターフェース設定を消すためのスクリプト
  • /data/setup-interfaces.service: インターフェースを起動時に設定するためのsystemdのサービスファイル

switch

この機器は、802.1X認証を受ける機器です。/dataに起動時に実行されるインターフェース設定などが書かれたファイルやオーセンティケーターを起動するためのコマンドなどが書かれています。

client1, client2はwpa_supplicantを利用することで、switchの認証を行うことができます。wpa_supplicantを停止しても3分程度は接続がつながりますが、しばらく待つと認証が切れて切断されます。

  • /data/setup-interfaces.sh: インターフェース設定を行うためのスクリプト
  • /data/teardown-interfaces.sh: インターフェース設定を消すためのスクリプト
  • /data/setup-interfaces.service: インターフェースを起動時に設定するためのsystemdのサービスファイル
  • /data/hostapd_cli@.service: hostapdが認証を許可した時に8021x_handler.pyを呼ぶためのデーモン用のsystemdのサービスファイル
  • /data/8021x_handler.py: ebtablesを操作し、802.1Xの認証結果をファイアウォールに反映させるスクリプト

router

この機器は、認証用のデーモンが動いている機器です。freeradius, openldapが動作しています。

  • /data/setup-interfaces.sh: インターフェース設定を行うためのスクリプト
  • /data/teardown-interfaces.sh: インターフェース設定を消すためのスクリプト
  • /data/setup-interfaces.service: インターフェースを起動時に設定するためのsystemdのサービスファイル
  • freeradius
    • 認証情報:
      • 172.31.1.253から通信を受けられるように設定されている
      • パスワード: ictsc2021
    • ユーザなどを取得するためにLDAPサーバに問い合わせを行っている
  • openldap
    • 認証情報:
      • admin DN: cn=admin,dc=2021-summer,dc=ictsc,dc=net
      • admin PW: ictsc2021

前提条件

  • client1, client2, switchの設定を変更したり加えたりしてはいけない
    • これらの機器は先輩社員さんがちゃんと設定を行っています
    • 設定変更を加えることなく問題を解くことができます

初期状態

  • client1, client2から172.31.0.254にpingを打っても返ってこない

終了状態

  • client1, client2から172.31.0.254にpingを打つと返ってくる

解説

今回の問題は、LDAPに保存されているパスワードのハッシュアルゴリズムとMS-CHAPv2で利用できるハッシュアルゴリズムが異なっていることによって、認証が行えていないというのが問題でした。

そのため、LDAPにMS-CHAPv2で利用できるような形式でハッシュ化した属性を追加すればOKです。

  1. sambaのobjectClassの定義をロードする(sambaNTPassword属性を利用するため)
sudo apt install samba
sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /usr/share/doc/samba/examples/LDAP/samba.ldif
  1. ユーザ用のLDIFファイルをロードする

sambaSIDはsambaSamAccount objectClassを利用するのに必須な属性です。なので、適当に生成する必要があります。sambaSIDは以下のようなスクリプトで生成することができます。

import binascii
import hashlib
import random

def nt_hash(password):
password = password.encode("UTF-16LE")
hashed = hashlib.new("MD4", password).digest()
return binascii.hexlify(hashed).decode().upper()

def generate*samba_sid():
p1, p2, p3 = [random.randint(0, 4294967295) for * in range(3)]
return f"S-1-5-21-{p1}-{p2}-{p3}"

password = input("password: ")
print(nt_hash(password))
print(generate_samba_sid())

スクリプトでSIDとNTハッシュ化されたパスワードを生成したら、ユーザのパスワードを追加するLDIFファイルを作成してロードします。

dn: uid=adam,ou=Users,dc=2021-summer,dc=ictsc,dc=net
changetype: modify
add: objectClass
objectClass: sambaSamAccount
-
add: sambaSID
sambaSID: S-1-5-21-401484083-650785073-894160332
-
add: sambaNTPassword
sambaNTPassword: 1574D4A36AE4DE77D91A42E12B5F30B3
dn: uid=eve,ou=Users,dc=2021-summer,dc=ictsc,dc=net
changetype: modify
add: objectClass
objectClass: sambaSamAccount
-
add: sambaSID
sambaSID: S-1-5-21-883903360-3810299002-3370863084
-
add: sambaNTPassword
sambaNTPassword: 27B0A3ACE19B518DEDADBC9D9EF50BF6
sudo ldapmodify -h localhost -D cn=admin,dc=2021-summer,dc=ictsc,dc=net -W -f ./adam.ldif
sudo ldapmodify -h localhost -D cn=admin,dc=2021-summer,dc=ictsc,dc=net -W -f ./eve.ldif
  1. /etc/freeradius/3.0/mods-enabled/ldapを編集する

追加した属性をfreeradiusの方から利用できるようにするために、/etc/freeradius/3.0/mods-enabled/ldapを編集して、NT-Passwordが格納されている属性のマッピングを追加します。これによって、freeradiusでNTハッシュ化したパスワードを利用することができます。

        #  attribute ref.
        update {
                control:Password-With-Header    += 'userPassword'
                control:NT-Password             := 'sambaNTPassword'
#               reply:Reply-Message             := 'radiusReplyMessage'

部分点

想定解の部分点は、パスワードをロードできた時点で200点、freeradiusの設定をするのを含めて300点になる予定でしたが、想定外解法(平文でパスワードを保存する解法)がほとんどでした。こちらの場合、終了条件に抵触しているわけではないので、こちらの場合でも同様に満点で採点しています。