chrootユーザーのSFTP操作ログ取得設定
はじめに
「chrootユーザーのSFTP操作ログを取得する」設定が意外と難しかったので、ここにまとめておきます。
OSはCentOS 7を対象としますが、CentOS 6における設定についても書きます。
各コマンドはrootユーザーで実行することを想定しています。
要件
ログ取得の要件は次のとおりとします。
- chrootユーザーもchrootではないユーザーも、SFTP操作ログを /var/log/sftp.log に記録する。
- SFTP操作ログを /var/log/messages や /var/log/secure など他のログファイルに記録しない。
- SFTPではない通常のSSH接続時のログをSFTP操作ログファイル /var/log/sftp.log に記録しない。
設定
上記の要件を満たす設定手順としては、以下を参考にしました。
・Logging sFTP activity for chrooted users – THE ART OF WEB
https://www.the-art-of-web.com/system/sftp-logging-chroot/
・Logging sftp commands – Redhat Customer Portal
https://access.redhat.com/articles/1374633
ログ書き出しには、rsyslogを使用します。
chrootディレクトリにソケットを作成して、それを介してSFTP操作専用のログファイル /var/log/sftp.log に出力させるのがポイントです。
1. chrootユーザーの作成
2. OpenSSHの設定
3. rsyslogの有効化
4. rsyslogの設定
5. ログローテート設定
1. chrootユーザーの作成
chrootユーザーについては、ここでは次のとおりとします。
- chrootユーザーはSFTPのみ可能とする。通常のSSH接続はできない。
- chrootユーザーはuser1, user2、グループはgroup1とする。
- chrootユーザーのホームディレクトリは、/home/<user> とする。
chrootディレクトリを他のユーザーと共有する方法(シンボリックリンクとかbindマウントとか)については、ここでは記載しません。
ユーザーとディレクトリを作成します。
# useradd -u 1051 -g group1 -d /home/user1 -M \ -s /sbin/nologin -c 'user1 (SFTP Only)' user1 # useradd -u 1052 -g group1 -d /home/user2 -M \ -s /sbin/nologin -c 'user2 (SFTP Only)' user2 # mkdir /home/user1 # mkdir /home/user2 # chown root.group1 /home/user1 # chown root.group1 /home/user2 # chmod 750 /home/user1 # chmod 750 /home/user2
ソケットファイル用ディレクトリを作成します。
# mkdir -m2755 /home/user1/dev # mkdir -m2755 /home/user2/dev
2. OpenSSHの設定
sshd_configで、internal-sftpのログ出力とChrootの設定を行います。
user1, user2は、Chrootさせ、SFTPしか実行できないようにします。
ログレベルはINFOを指定しています。
# vi /etc/ssh/sshd_config -- ... #Subsystem sftp /usr/libexec/openssh/sftp-server Subsystem sftp internal-sftp -l INFO ... Match User user1,user2 ChrootDirectory /home/%u ForceCommand internal-sftp -l INFO ... --
「Match User user1,user2」の行は、グループが特定できるのであれば、
「Match Group group」のような指定でもよいでしょう。
設定を反映させるため、sshdを再起動します。
(CentOS 7)
# systemctl restart sshd
(CentOS 6)
# /etc/init.d/sshd restart
3. rsyslogの有効化
CentOS 7は、標準ではrsyslogが無効となっているので、起動し、自動起動を有効とします。
# systemctl start rsyslog # systemctl enable rsyslog
journaldでログ管理の運用を行っている場合は、rsyslogを起動することで(CentOS 6と同じように)多くのログがjournaldとは別に記録されるようになります。
rsyslogの設定で不要なログ書き出しを止めるなど、調整してください。
CentOS 6で、rsyslogでソケットを介してログ出力をする場合は、標準インストールされている rsyslog v5 ではなく、rsyslog v7 が必要となります。
このため、rsyslog パッケージを削除し、rsyslog7 パッケージをインストールします。
単純にrsyslogを削除すると、依存関係で cron, sysstat パッケージも削除されてしまうため、依存関係パッケージを削除せずに、rsyslog7 にアップデートします。
(参考)
・cron と依存関係パッケージを削除せずに rsyslog7 にアップグレードする – Redhat Customer Portal
https://access.redhat.com/ja/solutions/1456213
# rpm -e --nodeps rsyslog; yum install rsyslog7
rsyslog7を起動し、自動起動設定を行います。
# /etc/init.d/rsyslog start # chkconfig rsyslog on
4. rsyslogの設定
rsyslogでログ取得設定を行います。
chrootユーザーごとに、chrootディレクトリ配下にソケットを開くことで、ログ書き出しがソケットファイル /dev/log に転送され、/var/log/sftp.log に記録されるようになる、というイメージでしょうか。
「if $programname == ‘internal-sftp’」でプログラム名 internal-sftp のログを補足し、デフォルトの /var/log/secure ではなく、/var/log/sftp.log に出力するようにします。
# vi /etc/rsyslog.d/sftp.conf -- module(load="imuxsock") input(type="imuxsock" Socket="/home/user1/dev/log" CreatePath="on") input(type="imuxsock" Socket="/home/user2/dev/log" CreatePath="on") if $programname == 'internal-sftp' \ then /var/log/sftp.log & ~ --
1行目の「module(load=”imuxsock”)」は、/etc/rsyslog.conf で「$ModLoad imuxsock」行があるときは不要です。
設定を反映させるため、rsyslogを再起動します。
(CentOS 7)
# systemctl restart rsyslog
(CentOS 6)
# /etc/init.d/rsyslog restart
rsyslogを再起動すると、ソケットファイルが自動作成されます。
# ls -l /home/user1/dev/ total 0 srw-rw-rw- 1 root root 0 2018-05-25 14:54 log
5. ログローテート設定
syslogのログローテート設定に、/var/log/sftp.log を追記します。
圧縮、ローテート間隔、保存世代などは適宜変更します。
# vi /etc/logrotate.d/syslog -- /var/log/cron /var/log/maillog /var/log/messages /var/log/secure /var/log/spooler /var/log/sftp.log { missingok sharedscripts postrotate /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true endscript } --
動作確認
クライアントからSFTP接続、ファイルのアップロード、ダウンロード、削除を実施し、要件どおりログを取得できることを確認します。
以下は、CentOS 7で、chrootディレクトリ配下の /upload ディレクトリに、
ローカルの /test, /test/test1.html をアップロード、ダウンロード、削除したときのログ出力例です。
※CentOS 6のときは微妙に違いますが、要件は満たしているはずです。
(ローカル)
$ ls -R .: test ./test: test1.html
ログ中のhostnameやアクセス元IPアドレスは伏せています。
接続時
-- /var/log/sftp.log May 25 15:42:14 <hostname> internal-sftp[1486]: session opened for local user user1 from [<ip-address>] May 25 15:42:14 <hostname> internal-sftp[1486]: opendir "/" May 25 15:42:14 <hostname> internal-sftp[1486]: closedir "/" -- -- /var/log/messages May 25 15:42:13 <hostname> systemd: Starting User Slice of user1. May 25 15:42:13 <hostname> systemd: Started Session 20 of user user1. May 25 15:42:13 <hostname> systemd-logind: New session 20 of user user1. May 25 15:42:13 <hostname> systemd: Starting Session 20 of user user1. -- -- /var/log/secure May 25 15:42:13 <hostname> sshd[1483]: Accepted publickey for user1 from <ip-address> port 54800 ssh2: RSA SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx May 25 15:42:13 <hostname> sshd[1483]: pam_unix(sshd:session): session opened for user user1 by (uid=0) --
アップロード時
May 25 15:43:53 <hostname> internal-sftp[1490]: session opened for local user user1 from [<ip-address>] May 25 15:43:53 <hostname> internal-sftp[1490]: opendir "/upload/test" May 25 15:43:53 <hostname> internal-sftp[1490]: sent status No such file May 25 15:43:54 <hostname> internal-sftp[1490]: opendir "/upload" May 25 15:43:54 <hostname> internal-sftp[1490]: closedir "/upload" May 25 15:43:54 <hostname> internal-sftp[1490]: mkdir name "/upload/test" mode 0777 May 25 15:43:54 <hostname> internal-sftp[1490]: opendir "/upload/test" May 25 15:43:54 <hostname> internal-sftp[1490]: closedir "/upload/test" May 25 15:43:54 <hostname> internal-sftp[1490]: opendir "/upload/test" May 25 15:43:54 <hostname> internal-sftp[1490]: closedir "/upload/test" May 25 15:43:55 <hostname> internal-sftp[1490]: open "/upload/test/test1.html" flags WRITE,CREATE,TRUNCATE mode 0666 May 25 15:43:55 <hostname> internal-sftp[1490]: close "/upload/test/test1.html" bytes read 0 written 182
ダウンロード時
May 25 15:46:33 <hostname> internal-sftp[1524]: session opened for local user user1 from [<ip-address>] May 25 15:46:34 <hostname> internal-sftp[1524]: opendir "/upload/test" May 25 15:46:34 <hostname> internal-sftp[1524]: closedir "/upload/test" May 25 15:46:34 <hostname> internal-sftp[1524]: open "/upload/test/test1.html" flags READ mode 0666 May 25 15:46:34 <hostname> internal-sftp[1524]: close "/upload/test/test1.html" bytes read 182 written 0
削除時
May 25 15:46:59 <hostname> internal-sftp[1486]: remove name "/upload/test/test1.html" May 25 15:46:59 <hostname> internal-sftp[1486]: rmdir name "/upload/test" May 25 15:46:59 <hostname> internal-sftp[1486]: opendir "/upload" May 25 15:46:59 <hostname> internal-sftp[1486]: closedir "/upload"
要件を満たしてログを取得できることが確認できました!
ファイル操作のほか、接続時の
「session opened for local user user1 from [
で、ユーザー名やアクセス元IPアドレスも確認できます。
要件 – ソケットファイル追加なし
通常は上記の設定方法で「解決」だと思いますが、要件が次のようになったとします。
- chrootユーザーもchrootではないユーザーも、SFTP操作ログを /var/log/sftp.log に記録する。
- SFTP操作ログを /var/log/messages や /var/log/secure など他のログファイルに記録しない。
- SFTPではない通常のSSH接続時のログをSFTP操作ログファイル /var/log/sftp.log に記録しない。
- SFTPユーザーを追加するときに、rsyslogやソケットファイル追加の設定は不要とする。
4つ目の要件が追加されています。
この要件を追加した理由としては、
- 運用上、SFTPユーザ―の追加時に、rsyslogやソケットファイル追加の設定を忘れそう。
- SSFTPユーザーから、ソケットファイルが見えてしまう(所有者はrootユーザーなので、SFTPユーザーは削除できない。)
などが考えられます。
試行錯誤の末たどりついた設定方法を以下にまとめます。
設定 – ソケットファイル追加なし
設定手順は、以下を参考にしました。
・chrootされたSFTP専用ユーザのFTP転送logを簡単に/var/log/sftp.logへはきだす – Qiita
https://qiita.com/hurukichi/items/22aa0d024bbd25b3e797
・【vsftpd】chrootされたSFTP専用ユーザのFTP転送logを/var/log/sftp.logへはきだす方法
http://fanblogs.jp/kumon/archive/18/0
先ほどと同様、ログ書き出しには、rsyslogを使用します。
特定のファシリティのログを捕捉して、SFTP操作時の特定の文字列でフィルタリングすることで、SFTP操作ログの出力先を分離します。
1. chrootユーザーの作成
2. OpenSSHの設定
3. rsyslogの有効化
4. rsyslogの設定
5. ログローテート設定
1. chrootユーザーの作成
chrootユーザーは先ほどと同様とします。
ユーザーとディレクトリを作成します。
ソケットファイル用ディレクトリの作成は不要です。
# useradd -u 1051 -g group1 -d /home/user1 -M \ -s /sbin/nologin -c 'user1 (SFTP Only)' user1 # useradd -u 1052 -g group1 -d /home/user2 -M \ -s /sbin/nologin -c 'user2 (SFTP Only)' user2 # mkdir /home/user1 # mkdir /home/user2 # chown root.group1 /home/user1 # chown root.group1 /home/user2 # chmod 750 /home/user1 # chmod 750 /home/user2
2. OpenSSHの設定
sshd_configで、internal-sftpのログ出力とChrootの設定を行います。
「-f AUTH」でファシリティを指定している点が先ほどとの違いです。
# vi /etc/ssh/sshd_config -- ... #Subsystem sftp /usr/libexec/openssh/sftp-server Subsystem sftp internal-sftp -f AUTH -l INFO ... Match User user1,user2 ChrootDirectory /home/%u ForceCommand internal-sftp -f AUTH -l INFO ... --
設定を反映させるため、sshdを再起動します。
(CentOS 7)
# systemctl restart sshd
(CentOS 6)
# /etc/init.d/sshd restart
3. rsyslogの有効化
CentOS 7では、先ほどと同様にrsyslogを起動します。
# systemctl start rsyslog # systemctl enable rsyslog
CentOS 6の場合、今回はchroot用ソケットファイルは使用しないので、rsyslog7へのアップデートは不要です。
4. rsyslogの設定
rsyslogでログ取得設定を行います。
# vi /etc/rsyslog.d/sftp.conf -- module(load="imuxsock") if $syslogfacility-text == 'authpriv' \ and ($msg contains 'open' or $msg contains 'close' or \ $msg contains 'remove' or $msg contains 'mkdir' or \ $msg contains 'rmdir' or $msg contains 'sent status') \ and not ($msg contains 'sshd:session') \ and not ($msg contains 'su-l:session') \ then /var/log/sftp.log & ~ --
補足します。
「if $syslogfacility-text」でログファシリティを指定します。
これだけだと、sshdを使用する通常のSSH接続等のログも捕捉してしまうので、
「$msg contains ~」でSFTP操作のログを絞り込みます。
chroot用ソケットファイルを指定しない場合は、プログラム名が「internal-sftp」ではなく「sshd」となるため、「if $programname == ‘internal-sftp’」の条件は使えません。
「$msg contains ~」で絞り込まなかったログは、/var/log/secure に出力されてしまいます。
以下の「and not ($msg contains ~)」については、、
and not ($msg contains 'sshd:session') \ and not ($msg contains 'su-l:session') \
↑これは通常のSSH接続やsudo時のログを /var/log/sftp.log ではなく、/var/log/secure に出力するためのフィルタ設定です。
なお、たまに以下のような設定例を見かけますが、これだけですと、ファイルのアップロード時のみのログ出力となります。
if $syslogfacility-text == 'authpriv' \ and $msg contains 'flags WRITE,CREATE,TRUNCATE mode 0666' \ then /var/log/sftp.log & ~
アップロード操作のみの記録が欲しいのであればそれでよいのですが、せっかくなら、削除の記録も取ったほうがよいと思います。
僕が試した限りでは、こんな感じでフィルタリングできそうでしたが、他にもSFTP操作特有の文字列を見つけたら、適宜フィルタルールを追加してください。
設定を反映させるため、rsyslogを再起動します。
(CentOS 7)
# systemctl restart rsyslog
(CentOS 6)
# /etc/init.d/rsyslog restart
5. ログローテート設定
先ほどと同様です。
# vi /etc/logrotate.d/syslog -- /var/log/cron /var/log/maillog /var/log/messages /var/log/secure /var/log/spooler /var/log/sftp.log { missingok sharedscripts postrotate /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true endscript } --
動作確認 – ソケットファイル追加なし
先ほどと同様に、クライアントからSFTP接続、ファイルのアップロード、ダウンロード、削除を実施し、要件どおりログを取得できることを確認します。
以下は、CentOS 7で、chrootディレクトリ配下の /upload ディレクトリに、
ローカルの /test, /test/test.html をアップロード、ダウンロード、削除したときのログ出力例です。
(ローカル)
$ ls -R .: test ./test: test1.html
ログ中のhostnameやアクセス元IPアドレスは伏せています。
接続時
-- /var/log/sftp.log May 25 17:53:00 <hostname> sshd[1591]: session opened for local user user1 from [<ip-address>] [postauth] May 25 17:53:00 <hostname> sshd[1591]: opendir "/" [postauth] May 25 17:53:01 <hostname> sshd[1591]: closedir "/" [postauth] -- -- /var/log/messages May 25 17:53:00 <hostname> systemd: Created slice User Slice of user1. May 25 17:53:00 <hostname> systemd: Starting User Slice of user1. May 25 17:53:00 <hostname> systemd: Started Session 26 of user user1. May 25 17:53:00 <hostname> systemd-logind: New session 26 of user user1. May 25 17:53:00 <hostname> systemd: Starting Session 26 of user user1. -- -- /var/log/secure May 25 17:53:00 <hostname> sshd[1591]: Accepted publickey for user1 from <ip-address> port 55223 ssh2: RSA SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx May 25 17:53:00 <hostname> sshd[1591]: pam_unix(sshd:session): session opened for user user1 by (uid=0) --
アップロード時
May 18 18:01:28 <hostname> sshd[1634]: opendir "/upload/test" [postauth] May 18 18:01:28 <hostname> sshd[1634]: sent status No such file [postauth] May 18 18:01:28 <hostname> sshd[1634]: opendir "/upload" [postauth] May 18 18:01:28 <hostname> sshd[1634]: closedir "/upload" [postauth] May 18 18:01:28 <hostname> sshd[1634]: mkdir name "/upload/test" mode 0777 [postauth] May 18 18:01:28 <hostname> sshd[1634]: opendir "/upload/test" [postauth] May 18 18:01:28 <hostname> sshd[1634]: closedir "/upload/test" [postauth] May 18 18:01:29 <hostname> sshd[1634]: opendir "/upload/test" [postauth] May 18 18:01:29 <hostname> sshd[1634]: closedir "/upload/test" [postauth] May 18 18:01:29 <hostname> sshd[1634]: open "/upload/test/test1.html" flags WRITE,CREATE,TRUNCATE mode 0666 [postauth] May 18 18:01:29 <hostname> sshd[1634]: close "/upload/test/test1.html" bytes read 0 written 182 [postauth]
ダウンロード時
May 18 18:02:06 <hostname> sshd[1629]: opendir "/upload/test" [postauth] May 18 18:02:06 <hostname> sshd[1629]: closedir "/upload/test" [postauth] May 18 18:02:06 <hostname> sshd[1629]: opendir "/upload/test" [postauth] May 18 18:02:06 <hostname> sshd[1629]: closedir "/upload/test" [postauth] May 18 18:02:06 <hostname> sshd[1629]: opendir "/upload" [postauth] May 18 18:02:06 <hostname> sshd[1634]: open "/upload/test/test1.html" flags READ mode 0666 [postauth] May 18 18:02:06 <hostname> sshd[1629]: closedir "/upload" [postauth] May 18 18:02:06 <hostname> sshd[1629]: opendir "/upload" [postauth] May 18 18:02:06 <hostname> sshd[1634]: close "/upload/test/test1.html" bytes read 182 written 0 [postauth] May 18 18:02:06 <hostname> sshd[1629]: closedir "/upload" [postauth]
削除時
May 18 18:02:25 <hostname> sshd[1629]: remove name "/upload/test/test1.html" [postauth] May 18 18:02:25 <hostname> sshd[1629]: rmdir name "/upload/test" [postauth] May 18 18:02:25 <hostname> sshd[1629]: opendir "/upload" [postauth] May 18 18:02:26 <hostname> sshd[1629]: closedir "/upload" [postauth]
おわりに
「chrootユーザーのSFTP操作ログを取得する」設定手順として、chroot用ソケットファイルを使用する/しないの2つの手順を記載しました。
後半の「chroot用ソケットファイルを使用しない方法」については、若干バッドノウハウのような気もしますが、運用上の都合でやむを得ないケースもあるでしょう。
(関連記事)
・Garage labsサーバー部10Uに参加しました。~Linuxサーバーセキュリティ対策part3 – ファイル転送編
https://inaba-serverdesign.jp/blog/20130718/garagelabs_server10u.html