はじめに
この記事は、rsyslogでのTLS(SSL)によるセキュアな送受信 の関連記事になります。
ここでは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
helpやmanコマンドも可能ですが英語なので、上記をGoogle翻訳した方が手っ取り早いんじゃないかなと思います。
$ certtool --help
$ man certtool
プライベートCAの秘密鍵の作成
サーバー担当のUbuntu端末で、cert というフォルダを作り、そこにプライベートCAの秘密鍵を作成します。
秘密鍵や証明書は重要情報なため、root でしか扱えないよう sudo コマンドで作っていきます。(sudo を付けずに作成して、あとで chown で変更をかけてもいいとは思いますが)
$ sudo certtool --generate-privkey --outfile ca-key.pem
プライベートCAの証明書の作成
次に作成した秘密鍵を使って、証明書を作成していきます。
$ sudo certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca.pem
このコマンドを実行すると、組織名やサーバー名などが要求されます。
本来であれば正式な情報を入力すべきですが、プライベートCAということもあり、こちらのドキュメントを参考に適当に入力していきます。:Setting up the CA
今回、使用した入力値は次の通りです。
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年くらいでいいでしょう。
Extentions. の項目は、[Does the certificate belong to an authority?]だけ y にしてあとは全部デフォルト設定で実施していきます。
「Is the above information ok? (y/N):」と最終確認されるので、y と入力して証明書を生成します。
ca-key.pem と ca.pem が作成されていることを確認します。
#サーバーの秘密鍵、CSR、そして証明書の作成
ここからはサーバーの証明書を作成してきます。手順は次の通りです。
1. 端末上で秘密鍵を作成する
2. 秘密鍵を元に証明書署名要求:CSRを作成し、認証局(CA)に送る
3. 認証局(CA)はCSRから証明書を作成し、端末に送り返す
この検証環境においては、サーバーと認証局(CA)が同じ端末になるので、連続して処理を行っていきます。
##秘密鍵の作成
$ sudo certtool --generate-privkey --outfile server-key.pem
##CSRの作成
秘密鍵を使って、証明書署名要求:CSR(Certificate Signing Request)を作成します。
$ sudo certtool --generate-request --load-privkey server-key.pem --outfile server-request.pem
今回も様々な情報を求められますが、これもこちらのドキュメントを参考にして作成していきます。:Generating the machine certificate
ここで重要なのは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
##証明書の作成
ここからは認証局(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
拡張の箇所は、今回は次の通りにします。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アドレス]
「Is the above information ok? (y/N):」と最終確認されるので、y と入力します。
これでサーバー証明書が作成されます。
#各端末への証明書の送付
認証局(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
クライアント側の設定
送信側(クライアント)に移動した直後のファイルは、移動したアカウントの権限になっているので、これをroot権限に変更してから移動します。
$ 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
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"
)
再起動を行い、問題が発生していないか確認しておきましょう。
$ sudo systemctl restart rsyslog.service
$ sudo systemctl status rsyslog.service
参考までに、問題が発生していると、たとえば次のようなエラーが出ています。
これは40行目の前にエラーがあるよ、という意味です。
クライアント側の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 ←この設定が残っていたならば削除
2020年04月01日追記:
ここで転送の書き方を Basic からAdvanced に変えています。書き方が異なるのはそのためです。
$(ドル)記号で始まって一行で書く設定方法もありますが、それは obsolete legacy ということで非推奨です。
また、Advanced で、ファシリティとシビアリティを指定するには、action の前で指定します。
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 が発生して上手く行きませんでした。
ログを見ると、SELinuxがブロックしている。
$ tail /var/log/messages | grep rsyslogd
はい。オフ。
(本当はちゃんと許可してあげるべきですが検証環境なので…)
サーバー側のエラー発生と是正措置
ここで送信側(クライアント)から syslog 転送を行ってみます。logger で発生させてもいいですし、全ログ転送になっていた場合、少し待てば発生するでしょう。
サーバー側のrsyslogのステータスを確認するとエラーを吐いていました。server-key.pem を読み込めなかった。権限がないとのこと。
今回はSELinuxは邪魔していません。
確かに、server-key.pem には root 以外に読み取り権限はありませんが、
rsyslogってrootで動いているんじゃないの?と確認したところ、Ubuntuでは syslog ユーザーで動いているとのこと。
所有者をsyslog にするか読み取り権限を追加するかのどちらかをする必要がありますが、出来ればよりセキュアな方がいいので、ここでは『最小権限の原則』に従ってsyslogユーザーに変更しておきます。
$ sudo chown syslog:syslog server-key.pem
これで再起動してステータスを確認したところ問題はなくなりました。
Syslogの中身が見れないことの確認
無事に受信できていることが確認できました。
パケットを確認しても中身が確認できないことが分かります。
これでsyslogの転送がよりセキュアになりました。