rsyslogでのTLS(SSL)によるセキュアな送受信（暗号化のみ）

# はじめに
　この記事は、[rsyslogでのTLS(SSL)によるセキュアな送受信](https://qiita.com/saeki4n/items/b30e619d9371f7808657) の関連記事になります。

　ここではsyslog通信の暗号化のみをしていきたいと思います。端末の認証はしません。そのため盗聴防止は出来るものの、成りすましは防げないという状態になります。

　検証環境は引き続き CentOS8 と Ubuntu(18.04)です。
　syslog送信側（クライアント）：CentOS(rsyslog version 8.37.0), IP=192.168.0.15
　syslog受信側（サーバー）：Ubuntu(rsyslog version 8.32.0), IP=192.168.0.13

#プライベートCA(認証局)の証明書の作成
　本来ならば正規のCAから発行された証明書を使用すべきですが、検証環境であることと、syslog転送という特定のホストから通信しか利用しないということから、プライベート認証局(CA)の証明書を利用することとします。いわゆるオレオレ証明書です。サーバー担当のUbuntuが認証局(CA)を兼ねる構成です。

　今回は、certtoolを使って証明書を作成していくためインストールします。
###Ubuntuの場合

```
$ sudo apt-get install gnutls-utils
```

###CentOSの場合

```
$ sudo yum install gnutls-utils
```

　certtoolのドキュメントはこちらになります。：[4.2.6 Invoking certtool](https://www.gnutls.org/manual/html_node/certtool-Invocation.html)
　helpやmanコマンドも可能ですが英語なので、上記をGoogle翻訳した方が手っ取り早いんじゃないかなと思います。

```
$ certtool --help
$ man certtool
```

## プライベートCAの秘密鍵の作成
　サーバー担当のUbuntu端末で、cert というフォルダを作り、そこにプライベートCAの秘密鍵を作成します。
　秘密鍵や証明書は重要情報なため、root でしか扱えないよう sudo コマンドで作っていきます。（sudo を付けずに作成して、あとで chown で変更をかけてもいいとは思いますが）

```
$ sudo certtool --generate-privkey --outfile ca-key.pem
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/662786d5-c796-4cb6-6e28-3b4ef5e84d6a.png)

## プライベートCAの証明書の作成
　次に作成した秘密鍵を使って、証明書を作成していきます。

```
$ sudo certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca.pem
```

　このコマンドを実行すると、組織名やサーバー名などが要求されます。
　本来であれば正式な情報を入力すべきですが、プライベートCAということもあり、こちらのドキュメントを参考に適当に入力していきます。：[Setting up the CA](https://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_ca.html)

　今回、使用した入力値は次の通りです。

```
Common name: SomeName
Organization unit name: SomeOU
Organization name: SomeOrg
Locality name: Chiyoda-ku
State or province name: Tokyo
Country name(2 chars): JP
   # 途中は全て未入力Enterで進めていく
The certificate will expire in(days): 3650
   # 有効期限はおよそ10年くらいでいいでしょう。
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/1f7bb2da-0293-f642-d664-d752e4b1998e.png)

　Extentions. の項目は、[Does the certificate belong to an authority?]だけ y にしてあとは全部デフォルト設定で実施していきます。
![ca-pemEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/37eceac6-a8a4-5304-d4c4-19e29878cf24.png)

　「Is the above information ok? (y/N):」と最終確認されるので、y と入力して証明書を生成します。
![ca-pemOK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/b3e47f3b-520e-97bb-72f7-2ffc1af5be34.png)

　ca-key.pem と ca.pem が作成されていることを確認します。
![ca-files.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/97c9c7d5-d07e-4d7f-3930-f6263276b380.png)

#サーバーの秘密鍵、CSR、そして証明書の作成
　ここからはサーバーの証明書を作成してきます。手順は次の通りです。

1.　端末上で秘密鍵を作成する
2.　秘密鍵を元に証明書署名要求:CSRを作成し、認証局(CA)に送る
3.　認証局(CA)はCSRから証明書を作成し、端末に送り返す

　この検証環境においては、サーバーと認証局(CA)が同じ端末になるので、連続して処理を行っていきます。

##秘密鍵の作成
```
$ sudo certtool --generate-privkey --outfile server-key.pem
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/27e36e9e-b6ce-3756-8fbc-4b00c6a0284a.png)

##CSRの作成
　秘密鍵を使って、証明書署名要求:CSR（Certificate Signing Request）を作成します。

```
$ sudo certtool --generate-request --load-privkey server-key.pem --outfile server-request.pem
```

　今回も様々な情報を求められますが、これもこちらのドキュメントを参考にして作成していきます。：[Generating the machine certificate](https://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_machine.html)

　ここで重要なのはCommon name です。ホストがDNS登録されている場合はそちらを使用します。使用していない場合でも FQDN形式のホスト名を使用する必要があるようです。

```
Common name: server.example.jp
Organization unit name: SomeOU
Organization name: SomeOrg
Locality name: Chiyoda-ku
State or province name: Tokyo
Country name(2 chars): JP
   # 途中はすべてデフォルト値
Is this a TLS web client certificate? (y/N): y
Is this also a TLS web server certificate? (y/N): y
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/a6005c78-7daa-e920-8594-d4348fdb98f2.png)


##証明書の作成
　ここからは認証局(CA)のパートです。
　CSRが出来たので（本来ならば送られてくるものだが）、サーバーの証明書を作成していきます。
　実行前に、次のファイルが揃っていることを確認してください。

- server-request.pem
- ca.pem
- ca-key.pem

```
$ sudo certtool --generate-certificate --load-request server-request.pem --outfile server-cert.pem --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem
```
期限を聞かれるので3600日としておきます。
（CAの期限を3650日としたので、それより少ない日が良かろうという意味）

```
The certificate will expire in (days): 3600
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/d018621a-1c28-e8e4-4ce3-d0dc4d76c841.png)


　拡張の箇所は、今回は次の通りにします。DNS Nameの設定には、サーバーのCSRの作成時のCommon name で使用したのと同じ値を入力します。検証環境にはDNSはないので自分のIPアドレスも設定しておきました。（参考にしたドキュメントにはここは設定されていませんが、正確な情報はあった方がいいかなと思って） 今回の検証環境の場合は 192.168.0.13 です。

```
Does the certificate belong to an authority?(y/N): n
Is this a TLS web client certificate? (y/N): y
(略)
Is this a TLS web server certificate? (y/N): y
Enter the dnsName of the subject of the certificate: server.example.jp
Enter the IP address of the subject of the certificate: [自身のIPアドレス]

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/f7732042-36d2-4d7e-f545-585b9c7650e1.png)

　「Is the above information ok? (y/N):」と最終確認されるので、y と入力します。
　これでサーバー証明書が作成されます。

![server-certOK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/d23fa811-0700-e32d-572e-9bb3145797d7.png)

　server-cert.pemが存在していたら成功です。
![server-files.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/deb4aa75-673b-163c-cde7-cd39d1dbedc9.png)

#各端末への証明書の送付
　認証局(CA)で作成した証明書は、各端末に送らなければなりません。
　ただ今回はサーバーと認証局は同じ端末ですので、クライアント端末のみへの送付になります。
　送付するファイルはca.pemだけです。

- 受信側（サーバー）＆認証局(CA)の方:Ubuntu
 - ca-key.pem
 - ca.pem
 - server-cert.pem
 - server-key.pem

- 送信側（クライアント）の方:CentOS
 - ca.pem

# 鍵と証明書用のディレクトリ作成と移動
　サーバー側、クライアント側の両方で、root権限にてrsyslog.dの配下に tls というフォルダを作成して、そこに鍵と証明書を移動させます。

## サーバー側の設定
```:受信側（サーバー）
$ sudo mkdir /etc/rsyslog.d/tls

$ sudo mv ca.pem /etc/rsyslog.d/tls
$ sudo mv server-cert.pem /etc/rsyslog.d/tls
$ sudo mv server-key.pem /etc/rsyslog.d/tls
```
　権限の確認を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/f902fc2a-03d0-3779-759f-9cc84d301bf3.png)

## クライアント側の設定
　送信側（クライアント）に移動した直後のファイルは、移動したアカウントの権限になっているので、これをroot権限に変更してから移動します。

移動したばかりの ca.pemの権限：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/6163251c-48f9-40b9-8e49-9ac6f3828e08.png)

```:送信側（クライアント）
$ sudo chown root:root ca.pem
$ sudo chmod 644 ca.pem
$ sudo mkdir /etc/rsyslog.d/tls
$ sudo mv ca.pem /etc/rsyslog.d/tls
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/112422bd-0009-a594-25fc-5f871a41ed4f.png)

　権限の確認を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/0298577f-4536-923d-ed33-e8d2ca1ad532.png)

# lmnsd_gtlsモジュールのインストール
　rsyslogのTLS転送を行うためには、拡張モジュールlmnsd_gtls が必要になりますので、双方の端末でインストールします。
###Ubuntuの場合

```
$ sudo apt-get install rsyslog-gnutls
```

###CentOSの場合

```
$ sudo yum install rsyslog-gnutls
```
# rsyslogの設定
## サーバー側のrsyslogの設定
　imtcpのmodule についてTLS化を使用するための設定を追加します。
　前項で移動させた鍵や証明書を参照できるようにしておきます。ここではAuthmode="anon"として、クライアント認証を行わないモードとします。

```
module(
 load="imtcp"
 StreamDriver.Name="gtls"
 StreamDriver.Mode="1"
 StreamDriver.Authmode="anon"
)

input(type="imtcp" port="514")

global(
 DefaultNetstreamDriver="gtls"
 DefaultNetstreamDriverCAFile="/etc/rsyslog.d/tls/ca.pem"
 DefaultNetstreamDriverCertFile="/etc/rsyslog.d/tls/server-cert.pem"
 DefaultNetstreamDriverKeyFile="/etc/rsyslog.d/tls/server-key.pem"
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/c5956c22-e8b4-1ae2-378e-3d26d2df52bd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/9ed96158-5f52-0745-81c9-ac33d243a295.png)

　再起動を行い、問題が発生していないか確認しておきましょう。

```
$ sudo systemctl restart rsyslog.service
$ sudo systemctl status rsyslog.service
```
　参考までに、問題が発生していると、たとえば次のようなエラーが出ています。
　これは40行目の前にエラーがあるよ、という意味です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/2edb69df-2278-3d0a-27aa-797b423e1e22.png)



## クライアント側のrsyslogの設定
　クライアント側についても設定変更していきます。サーバー側の設定と合わせるように、Port番号やクライアント認証の設定を行います。
　変更箇所は認証ファイルの設定と転送設定です。前回の転送設定が残っていたらば削除しておきましょう。

```

global(DefaultNetstreamDriverCAFile="/etc/rsyslog.d/tls/ca.pem")

action(type="omfwd" protocol="tcp" port="514"
       Target="192.168.0.13"
       StreamDriver="gtls"
       StreamDriverMode="1"
       StreamDriverAuthMode="anon")

# *.*    @@192.168.0.13　←この設定が残っていたならば削除
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/17f576b2-3f59-291f-9c40-3d21a17bd6c1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/27f08659-6026-3943-f050-823a8cd7147b.png)

**2020年04月01日追記**：
　ここで転送の書き方を Basic からAdvanced に変えています。書き方が異なるのはそのためです。
　$(ドル)記号で始まって一行で書く設定方法もありますが、それは obsolete legacy ということで非推奨です。
　また、Advanced で、ファシリティとシビアリティを指定するには、action の前で指定します。

```:ファシリティがmail、.シビアリティは全ての指定の場合
mail.* action(type="omfwd" protocol="tcp" port="514"
       Target="192.168.0.13"
       StreamDriver="gtls"
       StreamDriverMode="1"
       StreamDriverAuthMode="anon")
```

 詳しくはこちらをご覧ください。
 Configuration Formats
 https://www.rsyslog.com/doc/v8-stable/configuration/conf_formats.html

---

　再起動を行い、問題が発生していないか確認しておきましょう。

```
$ sudo systemctl restart rsyslog.service
$ sudo systemctl status rsyslog.service
```

## 送信側のエラー発生と是正措置

　これで問題ないはずなのですが、私の検証環境では ca.pemに対しての Permission denied が発生して上手く行きませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/135ecb5c-dd3c-8a13-ff72-b76c925374f5.png)

　権限も問題ないはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/bb139306-00b8-bb17-bb90-0b5038a8b484.png)

　ログを見ると、SELinuxがブロックしている。

```
$ tail /var/log/messages | grep rsyslogd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/18845208-b4b1-efec-561a-48b77370ce5f.png)

　はい。オフ。
（本当はちゃんと許可してあげるべきですが検証環境なので…）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/ba17118e-5e35-3690-5c44-05d4fd0f4ffd.png)


## サーバー側のエラー発生と是正措置
　ここで送信側（クライアント）から syslog 転送を行ってみます。logger で発生させてもいいですし、全ログ転送になっていた場合、少し待てば発生するでしょう。
　サーバー側のrsyslogのステータスを確認するとエラーを吐いていました。server-key.pem を読み込めなかった。権限がないとのこと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/cd10381f-3e4f-c712-f983-87b8151e9ddb.png)

　今回はSELinuxは邪魔していません。
　確かに、server-key.pem には root 以外に読み取り権限はありませんが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/e0b7de88-a1f1-cdd5-2afe-312f271cc2ed.png)

　rsyslogってrootで動いているんじゃないの？と確認したところ、Ubuntuでは syslog ユーザーで動いているとのこと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/faed27ab-3e64-6a11-a1cb-e07bba391693.png)
　所有者をsyslog にするか読み取り権限を追加するかのどちらかをする必要がありますが、出来ればよりセキュアな方がいいので、ここでは『最小権限の原則』に従ってsyslogユーザーに変更しておきます。

```
$ sudo chown syslog:syslog server-key.pem
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/6e69ca62-8b35-74a6-4106-57f49c174171.png)

　これで再起動してステータスを確認したところ問題はなくなりました。

# Syslogの中身が見れないことの確認

　クライアント側からデータを送ってみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/f94a37ab-980b-f503-5a4f-4465fd3157fc.png)

　無事に受信できていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/62269e3d-cb2c-3d7e-a12c-624d092145c5.png)
　
　パケットを確認しても中身が確認できないことが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/20c63bea-f456-5e42-9bbc-462f6b38fd02.png)

　これでsyslogの転送がよりセキュアになりました。

# 参考
- [imtcp: TCP Syslog Input Module](https://www.rsyslog.com/doc/v8-stable/configuration/modules/imtcp.html)
- [SELinuxを無効にするには](http://park1.wakwak.com/~ima/centos4_selinux0001.html)
- [Configuration Formats](https://www.rsyslog.com/doc/v8-stable/configuration/conf_formats.html)