SELinux のトラブルシュート

今日は昨日までの内容とは突然に趣向が変わってセキュリティとそのトラブルシュートの話です。

## 安全性とトレードオフ

少し前に、[貴重なデータの保全のために堅牢で安全な計算機環境を用意し
その上で分析をする話](http://qiita.com/ynakayama/items/24acb6eaa11b869eaa3e)を説明しました。

セキュリティの強固な環境では、まれに自分たちが設定したセキュリティ設定が意図して働かないといった事態を招くことがあります。特にセキュア OS の代表格である [SELinux](http://www.nsa.gov/research/selinux/) は設定がやや難解であったり良質な日本語情報が少なめであることから敬遠されがちです。ブログや入門サイト等の情報によってはいきなり無効化せよ等と書いてあることも散見されるほどです。

しかしインタプリタ言語とライブラリを利用してデータ分析をするにあたりセキュア OS を無効化する理由はほとんどありませんし、こういった習慣は根絶していくべきだと言えるでしょう。

## 障害の原因とその対応方法

RHEL 6 系およびそのクローンで筆者がよく見かける障害は外部から ssh 接続ができないといった類のものです。このようなときは、通常の GNU/Linux の鍵認証の設定等を見直すことはもちろんですが、それらに問題が無ければ SELinux のログも同時に確認します。

### SELinux のログを確認する

まずは ausearch で avc denied なメッセージを確認します。

```bash
$ sudo ausearch -m avc | tail -10

----
time->Fri May 30 10:54:15 2014
type=SYSCALL msg=audit(1401414855.954:3360): arch=XXXXXX syscall=1 success=no exit=-13 a0=4 a1=XXXXXX a2=2a a3=XXXXXX items=0 ppid=28482 pid=28485 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=445 comm="sshd" exe="/usr/sbin/sshd" subj=unconfined_u:system_r:initrc_t:s0 key=(null)
type=AVC msg=audit(1401414855.954:3360): avc:  denied  { dyntransition } for  pid=28485 comm="sshd" scontext=unconfined_u:system_r:initrc_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0 tclass=process
```

上のメッセージをよく確認してください。 /usr/bin/sshd が何らかの設定ミスで unconfined_u:system_r:initrc_t:s0 というラベルで起動していることがわかります。正しくは system_u:system_r でなくてはいけません。

### ファイルのコンテキストを確認する

よくある例としてはホームディレクトリの .ssh ディレクトリを他のホストから単純にコピーしてきてしまうといった理由で SELinux のコンテキストが不正になっているというパターンです。これは初心者にありがちなよくあるミスですのでまずこれを確認しておくと良いでしょう。 ls コマンドに -Z オプションを付与して確認します。

```bash
$ ls -laZ ~/.ssh/
drwx------. your_name your_grp system_u:object_r:ssh_home_t:s0  .
drwxr-x---. your_name your_grp system_u:object_r:user_home_dir_t:s0 ..
-rw-------. your_name your_grp system_u:object_r:ssh_home_t:s0  authorized_keys
-rw-r--r--. your_name your_grp system_u:object_r:ssh_home_t:s0  config
-rw-------. your_name your_grp system_u:object_r:ssh_home_t:s0  id_rsa
-rw-r--r--. your_name your_grp system_u:object_r:ssh_home_t:s0  id_rsa.pub
-rw-r--r--. your_name your_grp system_u:object_r:ssh_home_t:s0  known_hosts
```

上記のように system_u のコンテキストが付与されているのが正しい状態です。これが unconfined_u:object_r:user_home_t:s0 のように通常のファイルのような扱いになっていると、いくら authorized_keys などが正しく設定されていても外部から鍵認証でログインできません。 restorecon で正しくコンテキストを再設定しましょう。

```bash
$ sudo restorecon -RFv /home/your_name/.ssh/authorized_keys
restorecon reset /home/your_name/.ssh/authorized_keys context unconfined_u:object_r:ssh_home_t:s0->system_u:object_r:ssh_home_t:s0
```

大抵はこれで解決するはずですが、場合によっては SELinux ポリシーがそもそも誤っているなどより深刻な障害の可能性もあります。

### プロセスのコンテキストを確認する

たとえば sshd がそもそも正しいコンテキストで動作していないという可能性があります。 ps コマンドに -Z オプションを付与して確認します。

```bash
$ ps -H auxZwww | grep ssh

system_u:system_r:sshd_t:s0-s0:c0.c1023 root 1611 0.0  0.0 66608  600 ?        Ss   May27   0:00   /usr/sbin/sshd
system_u:system_r:sshd_t:s0-s0:c0.c1023 root 24945 0.0  0.1 98284 2004 ?       Ss   10:04   0:00     sshd: admin [priv]
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 admin 24951 0.0  0.0 98284 1544 ? S 10:04   0:00       sshd: admin@pts/0
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 root 25644 0.0  0.0 107460 904 pts/2 S+ 11:06   0:00                   grep ssh
```

正しくは上記の通り system_u:system_r:sshd_t で sshd が稼働しているはずです。が、これが unconfined_u:unconfined_r:unconfined_t になっているなら SELinux の設定ミスですから修正する必要があります。

### ポリシーファイルを修正する

SELinux の規定値では targeted ポリシーとなっています。

```bash
$ sudo cat /etc/selinux/config 

SELINUX=enforcing
SELINUXTYPE=targeted 
```

システムの SELinux ポリシーを確認した上で、それに相当するファイルを確認しましょう。既定の targeted ポリシーであれば /etc/selinux/targeted/contexts/files/file_contexts.homedirs を開きます。これは restorecon したときに基となる設定が記述されているファイルです。

```bash
/home/[^/]*/\.ssh(/.*)? system_u:object_r:ssh_home_t:s0
/home/[^/]*/\.ssh       system_u:object_r:ssh_home_t:s0
/[^/]*/\.ssh(/.*)?      system_u:object_r:ssh_home_t:s0
/[^/]*/\.ssh    system_u:object_r:ssh_home_t:s0
/usr/sbin/sshd  system_u:object_r:ssh_exec_t:s0
```

この状態で restorecon -RFv すれば正しいコンテキストが設定されますので sshd を再起動すれば今度は正しいコンテキストでプロセスが起動していることが確認できるはずです。

## まとめ

SELinux の設定はやや難しく日本語の情報が少ないといった状態ではありますが、正しく理解して利用することで安全な計算機環境を実現し、大切なデータの保全を図ることができます。

## 参考

第5章 SELinux を使った作業
https://access.redhat.com/site/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Security-Enhanced_Linux/chap-Security-Enhanced_Linux-Working_with_SELinux.html