DockerのFreeRADIUSでCiscoのログイン認証＋MAC認証+ダイナミックVLANした（CentOS8）

## はじめに
自前で運用しているFreeRADIUSをDockerに乗せ換えるべく、Dockerに初チャレンジです。
なお、本文で「MAC認証」の記載揺れがありますが、すべて「MACアドレスバイパス（MacAddressBypass）」の意味で用いています。
（MACアドレスを利用して「認証」するわけではない、という理解です）


### 修正
* rsyslogでリモートホストにログを転送する設定を追加しました。
* イメージビルド時に設定ファイルを準備するようにしました。（すみません、そんなことも知らなくて。。。）
* Cisco機器のログイン時に自動でenableになるアトリビュートを変更しました。


## 対象機器および環境

### 検証環境
* CentOS8(8.1.1911)
* Docker(19.03.5)
* FreeRADIUS(3.0.17)
* Cisco841M(15.5(3)M5)

### 初期状態で認証可能なもの

初期状態では以下の２ユーザとenableパスワードが利用できるようになります。

|ユーザ名|パスワード|備考|
|:-:|:-:|:-:|
|foo|bar|通常ユーザでのログイン|
|hoge|fuga|ログインすると自動で特権に昇格|
|\$enab15\$|fuga|enableコマンドで遷移する際のパスワード|


MACアドレス＋ダイナミックVLANは以下のもので登録された状態です。

|MACアドレス|VLAN文字列|
|:-:|:-:|
|055dc061bf92|default_seg|


### syslogのリモート転送

以下の２ホストへログを転送しています。

|転送先|facility|severity|syslogtag|
|:-:|:-:|:-:|:-:|:-:|
|10.254.10.104:514/udp|local0|notice|pseudolog_radius_log|
|10.254.10.112:514/udp|local0|notice|pseudolog_radius_log|


## 作業内容

### firewallでmasqueradeを設定

```
firewall-cmd --add-masquerade --zone=public --permanent
firewall-cmd --reload
```

### Dockerイメージの準備

再利用できるようにイメージをつくっておきます。
Dockerfileと設定ファイルを置くための適当なディレクトリを作成しておきます

```
mkdir -p /opt/docker/radius
cd /opt/docker/radius
```

#### Dockerfileを作成

```/opt/docker/radius/radius.df
FROM centos:centos8
ENV TZ='Asia/Tokyo'
RUN dnf -y update ; dnf install -y freeradius freeradius-ldap rsyslog ; \
sed -i -e "s/auth = no/auth = yes/" /etc/raddb/radiusd.conf ;  \
mkdir /etc/raddb/mods-config/files/userlist
COPY clients.conf /etc/raddb/clients.conf
COPY authorize /etc/raddb/mods-config/files/authorize
COPY users.login /etc/raddb/mods-config/files/userlist/users.login
COPY mabs /etc/raddb/mods-config/files/userlist/mabs
COPY rsyslog.conf /etc/rsyslog.conf
RUN  ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime ; systemctl enable radiusd 
CMD [ "/usr/sbin/init" ]
```


#### radiusシークレットの修正

~~bridge経由になっているため、コンテナはホスト（172.17.0.1/32）からのみ受け付けとしています~~
同一のDockerネットワークからのリクエストにもこたえられるように、172.16.0.0/12 に修正しました。
以下の `secret = RADIUS_SECRET` 行を、自身の環境にあわせてください。

```/opt/docker/radius/clients.conf
client radius_clients {
    ipaddr  = 172.16.0.0
    netmask = 12
    secret  = RADIUS_SECRET
}
```

#### ユーザファイルの読み込み

ログイン用のユーザとMAB用のMACアドレスリストを読み込む定義ファイルを作成

```:/opt/docker/radius/authorize
$INCLUDE /etc/raddb/mods-config/files/userlist/mabs
$INCLUDE /etc/raddb/mods-config/files/userlist/users.login
```


#### ログインユーザの登録

MD5-Passwordは echo -n PASSWORD | openssl md5 で生成できます。
Ciscoのenableは \$enab15\$ というユーザ名で試行されます。
ログイン時に自動でenableになるには、パスワードの下の行に ~~Service-TypeとCisco-AVPairを設定します。
（priv-lvl=1が通常ユーザ、priv-lvl=15が特権ユーザ、のことです）~~ 
`Service-Type = Administrative-User` を追加してリプライアイテムに含めます。
（Cisco WLC ログイン時に都合が悪かったので、修正しました。IOSにログインする際もenableになれます）

```/opt/docker/radius/users.login
DEFAULT Auth-Type == PAP
        Fall-Through = Yes

foo       Cleartext-Password := "bar"
$enab15$  MD5-Password := "c32ec965db3295bad074d2afa907b1c3"
hoge      MD5-Password := "c32ec965db3295bad074d2afa907b1c3"
          Service-Type = Administrative-User
```


#### MACアドレスバイパスの登録

ユーザ名とパスワードにMACアドレスを記載します。（ハイフンやコロンは削除します）
NAS-Port-Typeのアトリビュートをつけないと、機器へログインする際にUID/PWDをMACアドレスにしてログインできてしまいます。注意。

```:/opt/docker/radius/mabs
DEFAULT Auth-Type == PAP , NAS-Port-Type == Ethernet
        Tunnel-Type = 13 , Tunnel-Medium-Type = 6 , Tunnel-Private-Group-Id = "default_seg",
        Fall-Through = Yes

055dc061bf92 Cleartext-Password := "055dc061bf92"
```



#### syslog転送用の設定

ローカルのログファイルの変更を検知するモジュール `imfile` を利用して、リモートへsyslogを転送します。
`syslog` という名前で引けるサーバあてにUDP/514で転送します。

```:/opt/docker/radius/rsyslog.conf
module(load="imfile")
input(type="imfile"
      file="/var/log/radius/radius.log"
      tag="pseudolog_radius_log"
      facility="local0"
      severity="notice")
:syslogtag, isequal, "pseudolog_radius_log" @syslog:514
```

### Dockerfileからイメージをビルドしてコンテナ作成

Dockerfileが作成できたら、ビルドします。
`--privileges` はなんか評判悪そう（？）なので、推奨されてるぽい方法でコンテナ生成します。

```
# docker build --force-rm -t infraserv:radius . -f ./radius.df && \
  docker run --cap-add sys_admin --security-opt seccomp:unconfined \
    -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
    -it -d --name radius --hostname radius \
    -p 1812:1812/udp infraserv:radius
```

### 接続テスト

Dockerホストと別ホストから接続テストしておきます。
`radtest` は freeradius-utils に含まれています。
`yum -y install freeradius-utils` などでインストールしてください。

```
# radtest  hoge fuga 10.254.10.251 123 RADIUS_SECRET
Sent Access-Request Id 41 from 0.0.0.0:36748 to 10.254.10.251:1812 length 74
        User-Name = "hoge"
        User-Password = "fuga"
        NAS-IP-Address = 10.254.10.101
        NAS-Port = 123
        Message-Authenticator = 0x00
        Cleartext-Password = "fuga"
Received Access-Accept Id 41 from 10.254.10.251:1812 to 0.0.0.0:0 length 51
        Service-Type = NAS-Prompt-User
        Cisco-AVPair = "shell:priv-lvl=15"
```

OKですね。




## Cisco機器の設定

enableになって、`conf t`してから以下の設定をいれていきます。
ログイン認証とMACアドレスバイパスの設定を同時に実施します。

```
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!  共通設定
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!aaaの採用
aaa new-model
aaa session-id common

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!  ログイン認証の設定
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!radiusサーバグループの作成とログイン認証を実施
aaa group server radius ForLogin
 server-private 10.254.10.251 auth-port 1812 acct-port 1813 timeout 1 retransmit 1 key RADIUS_SECRET

!ログイン認証、イネーブル認証、権限アトリビュートを利用する設定
aaa authentication login default group ForLogin local-case
aaa authentication enable default group ForLogin enable
aaa authorization  exec default group ForLogin if-authenticated

!ローカルアカウントはradiusサーバと疎通が取れない場合に利用される
enable secret ENABLE_PASSWORD
username LOCAL_UID password LOCAL_PWD

!ログイン時にRADIUSを利用するための設定
line vty 0 4
 login authentication ForLogin


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!  MACアドレスバイパスの設定
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!ダイナミックVLANのアトリビュートで飛んでくる文字列
vlan 2022
 name default_seg

!radiusサーバグループの作成と802.1X認証を実施
aaa group server radius ForDot1X
 server-private 10.254.10.251 auth-port 1812 acct-port 1813 timeout 1 retransmit 1 key RADIUS_SECRET

!MACアドレスバイパス、ダイナミックVLAN用のアトリビュートを有効化
dot1x system-auth-control
aaa authentication dot1x default group ForDot1X
aaa authorization network default group ForDot1X if-authenticated

!interfaceへのMAB適用
interface Giga0/3
 description ## AuthPort : mac address bypass ##
 switchport mode access
 authentication order mab
 authentication priority mab
 authentication port-control auto
 mab
 dot1x pae authenticator
 spanning-tree portfast

end
```

念のため、ログインしたセッションは維持しつつ、別ターミナルでログインします。
ログイン出来たら、動作チェック。

radiusdのログ
各ユーザでのログインOKのログ、MACアドレスでのログインOK（＝MABがOK）が記録されています。

```
Sat Feb  8 15:48:24 2020 : Auth: (0) Login OK: [hoge] (from client radius_clients port 35)
Sat Feb  8 15:48:53 2020 : Auth: (1) Login OK: [foo] (from client radius_clients port 35)
Sat Feb  8 15:48:56 2020 : Auth: (2) Login OK: [$enab15$] (from client radius_clients port 35 cli 10.254.10.101)
Sat Feb  8 15:49:04 2020 : Auth: (3) Login OK: [hoge] (from client radius_clients port 35)
Sat Feb  8 15:49:49 2020 : Auth: (4) Login OK: [9cb6541e0363] (from client radius_clients port 50003 cli 9C-B6-54-1E-03-63)
```



Ciscoのログ（MAB）
設定したGi0/3で、当該MACアドレスによるMABのSUCCESS、VLAN2022の割り当てがされています。
（ログからは読み取れませんが、アトリビュート文字列の `default_seg` がvlan nameの文字列とマッチして2022が割り当てられています）

```
Feb  9 00:49:48: %LINK-3-UPDOWN: Interface GigabitEthernet0/3, changed state to up
Feb  9 00:49:49: %AUTHMGR-5-START: Starting 'mab' for client (9cb6.541e.0363) on Interface Gi0/3 AuditSessionID 000000000000000520203B8C
Feb  9 00:49:49: %MAB-5-SUCCESS: Authentication successful for client (9cb6.541e.0363) on Interface Gi0/3 AuditSessionID 000000000000000520203B8C
Feb  9 00:49:49: %AUTHMGR-7-RESULT: Authentication result 'success' from 'mab' for client (9cb6.541e.0363) on Interface Gi0/3 AuditSessionID 000000000000000520203B8C
Feb  9 00:49:49: %AUTHMGR-5-VLANASSIGN: VLAN 2022 assigned to Interface Gi0/3 AuditSessionID 000000000000000520203B8C
Feb  9 00:49:50: %AUTHMGR-5-SUCCESS: Authorization succeeded for client (9cb6.541e.0363) on Interface Gi0/3 AuditSessionID 000000000000000520203B8C
Feb  9 00:49:51: %LINEPROTO-5-UPDOWN: Line protocol on Interface Vlan2022, changed state to up
Feb  9 00:49:51: %LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/3, changed state to up
```

Ciscoのログ（AAA）

```
#sh aaa servers
（～～省略～～）
RADIUS: id 3, priority 0, host 10.254.10.251, auth-port 1812, acct-port 1813
     State: current UP, duration 1177s, previous duration 0s
     Dead: total time 0s, count 0
     Quarantined: No
     Authen: request 7, timeouts 1, failover 0, retransmission 1
             Response: accept 4, reject 2, challenge 0
             Response: unexpected 1, server error 0, incorrect 0, time 467ms
             Transaction: success 6, failure 0
             Throttled: transaction 0, timeout 0, failure 0
（～～省略～～）
```

OKですね。


ちなみに、dockerコンテナでログをみたくて、tailfしようとしたらコマンドがなかったので、watchしました。
`-d`は変化のあった箇所を白黒反転させる。`-n 1`は１秒おきに表示を更新させる。です。

```
# watch -d -n 1 'tail /var/log/radius/radius.log'
Every 1.0s: tail /var/log/radius/radius.log                                                      25dda9131ea4: Sat Feb  8 15:21:53 2020

Sat Feb  8 14:06:01 2020 : Warning: Ignoring "sql" (see raddb/mods-available/README.rst)
Sat Feb  8 14:06:01 2020 : Warning: Ignoring "ldap" (see raddb/mods-available/README.rst)
Sat Feb  8 14:06:01 2020 : Info: Loaded virtual server default
Sat Feb  8 14:06:01 2020 : Info:  # Skipping contents of 'if' as it is always 'false' -- /etc/raddb/sites-enabled/inner-tunnel:331
Sat Feb  8 14:06:01 2020 : Info: Loaded virtual server inner-tunnel
Sat Feb  8 14:06:01 2020 : Info: Ready to process requests
Sat Feb  8 14:06:11 2020 : Auth: (0) Login OK: [hoge] (from client radius_clients port 123)
Sat Feb  8 15:14:31 2020 : Auth: (1) Login OK: [hoge] (from client radius_clients port 123)
Sat Feb  8 15:21:38 2020 : Auth: (2) Login OK: [hoge] (from client radius_clients port 123)
Sat Feb  8 15:21:40 2020 : Auth: (3) Login OK: [hoge] (from client radius_clients port 123)
```


# 802.1X EAP-TLS 認証
無線LANのEAP-TLSは[Cisco WLC と FreeRADIUS を利用した EAP-TLS認証](https://qiita.com/bashaway/items/a9cf4a9168f325e65513)で記載しています。


# さいごに
実は、 `--privileges` で起動したあと `systemctl start radius` で権限がなんちゃら～、でサービスが起動せずにハマっていました。


# 出典
[FreeRADIUSとCisco機器を利用したログイン認証](http://www.prosper2.org/devwiki/index.php?FreeRADIUS%E3%81%A8Cisco%E6%A9%9F%E5%99%A8%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E8%AA%8D%E8%A8%BC)
http://docs.docker.jp/engine/articles/dockerfile_best-practice.html
https://hub.docker.com/r/centos/systemd/
https://unix.stackexchange.com/questions/452249/docker-container-with-centos-7-and-systemd
https://stackoverflow.com/questions/33439230/how-to-write-commands-with-multiple-lines-in-dockerfile-while-preserving-the-new