私的サーバー構築日誌：rsyslogとlogrotateとlogger

# 能書き

[私的サーバー構築日誌：仕切り直し](https://qiita.com/katz_engineer/items/1f21de2bd9072c260ae6)からの自宅サーバー構築の続きです。

[以前](https://qiita.com/katz_engineer/items/72c4018f960c9c2c0491)も同じネタを記事にしましたが、今回はちょっと記述の順番などを変えたり、実験用クライアントマシンをLXDコンテナにしたりしてます。

---

ログの蓄積や出力は```journald```を利用するのがsystemdの流儀なのでしょう。私も[以前少し調べてみた事があります](https://qiita.com/katz_engineer/items/7b3f490749272663db7c)。利便性を目指して開発が進み、長所も幾つかあるようです。

でもさぁ、これは明らかな欠陥だよねぇ。大量だからってログを捨てる仕様なんてさぁ！

[短時間に大量のログが送付されると破棄する](https://qiita.com/thaim/items/5d0cc595fce4ac0858e4#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E5%87%BA%E5%8A%9B%E3%83%AC%E3%83%BC%E3%83%88%E3%81%AE%E5%88%B6%E9%99%90)そうです。困るでしょう。短時間に大量のログが発生する状況というのは、異常事態が起きている可能性が非常に高い。そんな時のログは丁寧に追跡したいのが管理者の心情。それが不可能になります。

Ubuntuの中の人も同じ事を考えたかどうかは知りませんが、Ubuntuでは```rsyslog```と```logrotate```と、更に```logger```もデフォルトでインストールされていて、```journald```と並行して動いている由。

恥ずかしながら```rsyslog```と```logrotate```と```logger```は、私、今まで利用した事がありませんでした。今回その使い方や設定を調べたので、纏めておきます。

# 目標

- クライアントマシンからrsyslogサーバへの送信において、通信路を暗号化する
    - 家庭内 LAN での使用を前提として、成りすましは考慮しない
    - クライアントマシンとしてはLXDコンテナを利用する

この作業自体も（クライアントマシンとしてLXDコンテナを使う以外は）[前述の参考文献](https://qiita.com/saeki4n/items/b30e619d9371f7808657)に纏まっていたので、それをUbuntu22.04LTSで設定します。

各コマンドの詳しい使い方は、参考文献群を見ていただいた方が良いでしょう。枯れた技術ですし、私などがここで繰り返す意味は無さそうです。

# 参考文献

- [自宅サーバー構築譚：rsyslog と logrotate と logger - Qiita](https://qiita.com/katz_engineer/items/72c4018f960c9c2c0491)

## rsyslog

- [第19回　ログを収集する（rsyslogの設定） - シェルスクリプトマガジン](https://shell-mag.com/19st_linuxoperations/)
- [rsyslog.confの文法 - Qiita](https://qiita.com/11ohina017/items/087b1b7c4411c3b3195a)
- [【ログ出力設定】rsyslogとloggerコマンド。 - Qiita](https://qiita.com/NAKASHOU06/items/835795ee1cb3c1a87caa)
- [rsyslogでのTLS(SSL)によるセキュアな送受信 - Qiita](https://qiita.com/saeki4n/items/b30e619d9371f7808657)

```rsyslog```は非常に高機能だそうです。その一端が下記の参考文献で紹介されています。

- [「rsyslog」のデータベース出力機能やテンプレート機能、スクリプティング機能を活用する - さくらのナレッジ](https://knowledge.sakura.ad.jp/8975/)

## logrotate

今回は操作しません。記事が複雑になり過ぎるので。下記の参考文献が非常に分かり易くなっていましたのでそちらをどうぞ。

- [logrotate入門 - Qiita](https://qiita.com/zom/items/c72c7bac63462225971b)
- [Ubuntu20.04でLogrotateを使用してログファイルを管理する方法 - 開発者ドキュメント](https://ja.getdocs.org/how-to-manage-logfiles-with-logrotate-on-ubuntu-2-4)

## logger

```logger```についてはmanを読むのが一番良さそうです。

- [LOGGER - JM Project](https://linuxjm.osdn.jp/html/util-linux/man1/logger.1.html)

# サーバー設定

まずはサーバー側を設定します。

## スナップショット

今回も新しいモジュールのインストールがありますので、[スナップショットを撮っておきます](https://qiita.com/katz_engineer/items/f3bd2f7af2ba49db156c#%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)。

```console:サーバー
sudo zfs snapshot tank/root/ubuntu@$(date +%Y%m%d_%H%M%S)_before_rsyslog_tls
```

## rsyslog・lmnsd_gtls モジュールのインストール

rsyslogのTLS転送を行う為には拡張モジュールlmnsd_gtlsが必要だそうです。

```console:サーバー
sudo apt install rsyslog-gnutls
```

```/etc```を確認。何も変化はありませんでした。

```console:サーバー
sudo svn st /etc
```

## サーバーの鍵の配置

秘密鍵と公開鍵は、既に作ってあるという事にします。作り方は以前の記事を参照して下さい。

- [私的サーバー構築日誌：オレオレ認証局 - Qiita](https://qiita.com/katz_engineer/items/ff07466662131b72c14c)
- [私的サーバー構築日誌：オレオレ認証局が認証する証明書 - Qiita](https://qiita.com/katz_engineer/items/fe954644fa570093ca3a)

認証局：

- 秘密鍵 ```/home/cert/demoCA/pki/private/ca.key```
- 公開鍵 ```/home/cert/demoCA/pki/ca.crt```

サーバーマシンprimary.homeの証明書：

- 秘密鍵 ```/home/cert/demoCA/pki/private/primary.home.key```
- 公開鍵 ```/home/cert/demoCA/pki/issued/primary.home.crt```

サーバー側の rsyslog が参照する鍵は下記3点。

- 認証局の公開鍵 ```ca.crt```
- 証明書の公開鍵 ```primary.home.crt```
- 証明書の秘密鍵 ```primary.home.key```

ディレクトリ ```/etc/rsyslog.d/tls``` を作って、そこにこの3点を格納します。

```console:サーバー
sudo mkdir /etc/rsyslog.d/tls
```

```console:サーバー
sudo -u cert cp -p /home/cert/demoCA/pki/ca.crt /tmp/demoCA.crt
```

```console:サーバー
sudo -u cert cp -p /home/cert/demoCA/pki/issued/primary.home.crt /tmp
```

```console:サーバー
sudo -u cert cp -p /home/cert/demoCA/pki/private/primary.home.key /tmp
```

cp コマンドに```-p```オプションを付けると、権限や更新日時などを元ファイルと同一にしてくれます。逆に指定しない場合は、コピーした日時が更新日時になってしまいます。大抵は問題無いと思いますけども。私は気になるので。

```console:サーバー
sudo chown syslog: /tmp/demoCA.crt /tmp/primary.home.crt /tmp/primary.home.key
```

```console:サーバー
sudo mv /tmp/demoCA.crt /tmp/primary.home.crt /tmp/primary.home.key /etc/rsyslog.d/tls
```

念の為に権限を確認。

```console:サーバー
ls -l /etc/rsyslog.d/tls
```

結果はこうなります。

```console:サーバー
$ ls -l /etc/rsyslog.d/tls
total 15
-rw------- 1 syslog syslog  729 Aug 27 20:01 demoCA.crt
-rw------- 1 syslog syslog 2928 Oct 25 17:10 primary.home.crt
-rw------- 1 syslog syslog  306 Oct 25 17:09 primary.home.key
```

## rsyslog設定

ポート番号は、一般的な 514 番ポートにします。

```console:サーバー
cd /etc/rsyslog.d
cat | sudo tee 80-rsyslog.conf >/dev/null <<___
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/demoCA.crt"
 DefaultNetstreamDriverCertFile="/etc/rsyslog.d/tls/primary.home.crt"
 DefaultNetstreamDriverKeyFile="/etc/rsyslog.d/tls/primary.home.key"
)
___
```

再起動します。

```console:サーバー
sudo systemctl restart rsyslog
```

エラーが発生していない事を確認します。

```console:サーバー
sudo systemctl status rsyslog
```

## クライアントへ送付する鍵の用意

クライアントへ送付する鍵は```ca.crt```（認証局の公開鍵）のみになります。これを送信用ディレクトリ```/srv/transport```内の、クライアントから操作できるサブディレクトリに置きます。ついでにファイル名を調整。

```console:サーバー
sudo -u cert cp -p /home/cert/demoCA/pki/ca.crt /tmp/demoCA.crt
```

```console:サーバー
sudo chown transporter: /tmp/demoCA.crt
```

```console:サーバー
sudo -u transporter mv /tmp/demoCA.crt /srv/transport/publickey
```

```/tmp```ディレクトリ内では、ファイルの所有者とroot以外はそのファイルを削除できません。その為に```/tmp/ca.crt```の所有者を変更してから```mv```コマンドを実行します。

権限を確認。

```console:サーバー
ls -l /srv/transport/publickey
```

こんな風になっている筈です。

```console:サーバー
$ ls -l /srv/transport/publickey
total 5
-rw------- 1 transporter transporter 729 Aug 27 20:01 demoCA.crt
```

# クライアント設定

今度はクライアント側です。

## LXDコンテナ

今回は[LXDコンテナ](https://qiita.com/katz_engineer/items/4a3856b27d13ebcd1890)を使用します。

```console:サーバー
lxc launch images:ubuntu/jammy rsyslog-test --device eth0,ipv4.address=192.168.0.2
```

LXDコンテナが稼働したら、中に入ります。

```console:サーバー
lxc shell rsyslog-test
```

## rsyslog・lmnsd_gtls モジュールのインストール

クライアント側にも拡張モジュール lmnsd_gtls が必要だそうです。

```console:LXDコンテナ内
apt install rsyslog-gnutls
```

## 鍵の配置

[公開鍵送付専用ユーザーを使用してサーバー上の鍵を持ってきます](https://qiita.com/katz_engineer/items/fc02e92d1315d6a51a7c)。

sftp で```publickey/demoCA.crt```を取得します。取得したら、クライアント側の責任で削除します。

```console:LXDコンテナ内
sftp transporter@primary.home
```

```console:LXDコンテナ内：sftp操作
cd publickey
get demoCA.crt
rm demoCA.crt
exit
```

ファイルの権限を一般的な```/etc```内ファイルの権限に変えておきます。

```console:LXDコンテナ内
chmod 644 demoCA.crt
```

確認。

```console:LXDコンテナ内
ls -l demoCA.crt
```

結果はこうなります。

```console:LXDコンテナ内
# ls -l demoCA.crt
-rw-r--r-- 1 root root 729 Oct 25 09:13 demoCA.crt
```

調整した公開鍵を移動します。

```console:LXDコンテナ内
mkdir /etc/rsyslog.d/tls
mv demoCA.crt /etc/rsyslog.d/tls/
```

## rsyslog設定

サーバー側の設定と合わせるように、ポート番号やクライアント認証の設定を行います。
下記の設定の場合はファシリティ```local0```だけがサーバー（というかコンテナホスト）192.168.0.1に送信されます。

```console:LXDコンテナ内
cat >/etc/rsyslog.d/80-local0.conf <<___
global(DefaultNetstreamDriverCAFile="/etc/rsyslog.d/tls/demoCA.crt")

local0.* action(type="omfwd" protocol="tcp" port="514"
    Target="192.168.0.1"
    StreamDriver="gtls"
    StreamDriverMode="1"
    StreamDriverAuthMode="anon")
___
```

但し、認証局の公開鍵は、指定しなくても動作するように見えます。この1行目（```global```の行）は、不要かも知れません。rsyslogに詳しい方からのコメントをお待ちしてます。

再起動して、エラーが発生していない事を確認します。

```console:LXDコンテナ内
systemctl restart rsyslog
systemctl status rsyslog
```

# 動作確認

```logger```コマンドを実行してみます。

```console:LXDコンテナ内
hostname
whoami
logger -p local0.info hello,world
tail -n1 /var/log/syslog
```

クライアント（```logger```コマンドを実行した環境）側でもログが残ります。最初の実行では、証明書の公開鍵と秘密鍵が指定されていない事に対する警告も出てしまいますが。従って実行結果は、例えば下記のようになります。

```console:LXDコンテナ内：実行結果例
# hostname
rsyslog-test
# whoami
root
# logger -p local0.info hello,world
# tail -n3 /var/log/syslog
Oct 25 12:27:23 rsyslog-test root: hello,world
Oct 25 12:27:23 rsyslog-test rsyslogd: warning: certificate file is not set [v8.2112.0 try https://www.rsyslog.com/e/2330 ]
Oct 25 12:27:23 rsyslog-test rsyslogd: warning: key file is not set [v8.2112.0 try https://www.rsyslog.com/e/2331 ]
```

サーバーにログが転送されているか、確認しましょう。

```console:LXDコンテナ内
exit
```

```console:サーバー
tail -n1 /var/log/syslog
```

```logger```コマンドで指定した内容が表示されれば成功です。

```console:サーバー：実行結果例
$ tail -n1 /var/log/syslog
Oct 25 12:27:23 rsyslog-test root: hello,world
```

# 仕舞い

成功したら```/etc```の内容を確認しましょう。

```console:サーバー
sudo svn st /etc
```

今回は、ここまでで追加した内容になります。

```console:サーバー
$ sudo svn st /etc
?       /etc/rsyslog.d/80-rsyslog.conf
?       /etc/rsyslog.d/tls
```

Subversion追加。

```console:サーバー
sudo svn add /etc/rsyslog.d/*
```

コミットしましょう。

```console:サーバー
sudo svn ci /etc -m"rsyslog over tls"
```

実験に使ったLXDコンテナも削除しておきましょう。

```console:サーバー
lxc stop rsyslog-test
lxc delete rsyslog-test
```

これでrsyslogとlogger（とlogrotate）を家庭内LANで使う為の最低限の環境が整いました。