rsyslogでのTLS(SSL)によるセキュアな送受信（暗号化かつ認証あり）

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

　前回、[rsyslogでのTLS(SSL)によるセキュアな送受信（暗号化のみ）](https://qiita.com/saeki4n/items/198407c8710d769dfa55)にて、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-key.pem
    - ca.pem
- サーバーの秘密鍵と証明書
    - server-key.pem
    - server-cert.pem

#クライアントの秘密鍵、CSR、そして証明書の作成
　端末認証にはクライアントの証明書が必要になりますので、これらを作っていきます。
　サーバーの時と同様、手順は次の通りです。

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

##秘密鍵の作成
　秘密鍵をクライアント端末で作るかサーバー端末で作るか迷ったのですが[^1]、自分の秘密鍵は自分で作るべきだよね、ということでクライアント端末で作りました。

[^1]: たとえば、参考にした書籍『鶴長 鎮一(著) rsyslog 実践 ログ管理入門』では、サーバー端末でクライアントの秘密鍵と証明書を作成して、それをクライアントに転送している

```
$ sudo certtool --generate-privkey --outfile client-key.pem
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/05ea8814-1e1b-fa66-85b9-e91f42b205d7.png)

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

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

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

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

```
Common name: client.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/6550d185-76d0-4957-c902-6c38fc740210.png)

##証明書の作成

　前項にて作成したCSRをCA担当の端末に転送します。
　転送の際、読み取り権限が必要な場合は追加してあげます。

```
$ sudo chmod +r client-request.pem
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/b9bf5010-c60f-230d-9e3f-145699724526.png)

　ここからは認証局(CA)の作業パートです。
　転送したクライアントのCSRを使って、クライアント証明書を作成していきます。
　実行前に次のファイルが揃っていることを確認してください。

- client-request.pem
- ca.pem
- ca-key.pem

```
$ sudo certtool --generate-certificate --load-request client-request.pem --outfile client-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/a6833a9b-9ce2-7ec1-6eba-7c8af8756bd5.png)

　拡張の箇所は、今回は次の通りにします。サーバーの場合と違って、クライアントの場合は名前もIPも変わる可能性が高いので設定は行わないようにしました。

```
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

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/18726323-a23f-c1b6-ffc5-32dbadd1c974.png)

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/d9bb38b9-4de1-293c-3613-791d20662287.png)

　client-cert.pemが存在していたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/5766925a-4460-c365-7faf-3cb1696defb6.png)

　作成したclient-cert.pemをクライアント端末に転送します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/1c624d49-229d-930f-3016-3ab647c526f8.png)


##鍵と証明書の権限と配置
　転送したファイルは、移動時のアカウント権限になっているので、これをroot権限に変更して、前回作成したフォルダに移動させます。

```
$ sudo chown root:root client-cert.pem
$ sudo chmod 644 client-cert.pem
$ sudo mv client-cert.pem /etc/rsyslog.d/tls
$ sudo mv client-key.pem /etc/rsyslog.d/tls
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/2228d17d-cb35-cf78-4088-36ec2de01bbd.png)

　権限の確認を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/73a7304c-6a38-d31b-b2e2-b7c6d66dbfb4.png)

# rsyslogの設定
## サーバー側のrsyslogの設定
　クライアント認証を行うべく、Authmode="x509/name"と変更し、PermittedPeer=["client.example.jp"]を追加します。

```
module(
 load="imtcp"
 StreamDriver.Name="gtls"
 StreamDriver.Mode="1"
 StreamDriver.Authmode="x509/name"
 PermittedPeer=["client.example.jp"]
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/c3d10cd1-c80e-d7b7-a7c9-83e7d15a0557.png)

再起動を行い、ステータスを確認します。

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

　すると クライアント側で認証エラーが発生しているのが分かります。端末認証を有効にしたためです。実際、この状態ではログ転送ができません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/cce81962-be08-4524-4527-c714113bddad.png)

## クライアント側のrsyslogの設定
　それでは再びログ転送ができるようにクライアント側のrsyslogの設定を行っていきます。
　サーバー側の設定と同じように、各証明書ファイルの設定を行い、AuthmodeとPermittedPeersを設定します。[^2]

```
global(
 DefaultNetstreamDriver="gtls"
 DefaultNetstreamDriverCAFile="/etc/rsyslog.d/tls/ca.pem"
 DefaultNetstreamDriverCertFile="/etc/rsyslog.d/tls/client-cert.pem"
 DefaultNetstreamDriverKeyFile="/etc/rsyslog.d/tls/client-key.pem"
)

module(
 load="imtcp"
 StreamDriver.Name="gtls"
 StreamDriver.Mode="1"
 StreamDriver.Authmode="x509/name"
 StreamDriverPermittedPeers="server.example.jp"
)
```
[^2]: このドキュメント [Setting up a client](https://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_client.html)を参考にしたのですが、認証ファイルの設定さえすれば、Authmodeは"anon"のままで、PermittedPeersの設定は無くても転送できました。サーバー側で設定しておけば自動で切り替わるのでしょうか。分かりません…。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/491bdef3-a15a-3534-7347-577a2ef04046.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/77c388aa-aa3e-de3d-8b35-8d9f6d957a9d.png)

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

```:クライアント側
$ sudo systemctl restart rsyslog.service
$ sudo systemctl status rsyslog.service
```

# ログ転送と成りすましが出来ないことの確認

　クライアント側からログ転送が行われるか確認を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/8c54f7d8-ff74-dbe0-212f-0f545fed56c3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/3b95424d-137f-d75c-9f91-39341bf12393.png)

　再びログ転送ができていることが確認できます。

　それでは本当に「成りすまし」が出来ないのか。
　別のクライアント端末を用意して、認証できるか確認してみます。

　別のクライアント端末自身を認証局(CA)にしてオレオレ証明書を作成し、同じ設定のクライアント証明書を作成、その証明書で認証設定を行います。rsyslog.conf は正規のクライアント端末からのコピーしてきます。
　ログを見ると、開始直後(start)から"unexpected gnutls error" が発生していることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430322/628312e2-990f-5415-1d87-68fde10af321.png)

　サーバー側のca.pemとca-key.pemを無いと認証できないことが確認できました。
　ca.pemは配布用で何とか入手できるかもしれないので、ca-key.pemの重要性がよく分かります。
　これで許可された端末以外の接続はできず、成りすましの防止ができました。

# 参考
- [Generating the machine certificate](https://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_machine.html)
- [RSyslog Documentation　Setting up a client](https://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_client.html)