chrootユーザーのSFTP操作ログ取得設定

isdはじめに

「chrootユーザーのSFTP操作ログを取得する」設定が意外と難しかったので、ここにまとめておきます。
OSはCentOS 7を対象としますが、CentOS 6における設定についても書きます。
各コマンドはrootユーザーで実行することを想定しています。

isd要件

ログ取得の要件は次のとおりとします。

  1. chrootユーザーもchrootではないユーザーも、SFTP操作ログを /var/log/sftp.log に記録する。
  2. SFTP操作ログを /var/log/messages や /var/log/secure など他のログファイルに記録しない。
  3. SFTPではない通常のSSH接続時のログをSFTP操作ログファイル /var/log/sftp.log に記録しない。

isd設定

上記の要件を満たす設定手順としては、以下を参考にしました。

・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
}
--

 

isd動作確認

クライアントから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アドレスも確認できます。

isd要件 – ソケットファイル追加なし

通常は上記の設定方法で「解決」だと思いますが、要件が次のようになったとします。

  1. chrootユーザーもchrootではないユーザーも、SFTP操作ログを /var/log/sftp.log に記録する。
  2. SFTP操作ログを /var/log/messages や /var/log/secure など他のログファイルに記録しない。
  3. SFTPではない通常のSSH接続時のログをSFTP操作ログファイル /var/log/sftp.log に記録しない。
  4. SFTPユーザーを追加するときに、rsyslogやソケットファイル追加の設定は不要とする。

4つ目の要件が追加されています。
この要件を追加した理由としては、

  • 運用上、SFTPユーザ―の追加時に、rsyslogやソケットファイル追加の設定を忘れそう。
  • SSFTPユーザーから、ソケットファイルが見えてしまう(所有者はrootユーザーなので、SFTPユーザーは削除できない。)

などが考えられます。

試行錯誤の末たどりついた設定方法を以下にまとめます。

isd設定 – ソケットファイル追加なし

設定手順は、以下を参考にしました。

・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
}
--

 

isd動作確認 – ソケットファイル追加なし

先ほどと同様に、クライアントから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]

 

isdおわりに

「chrootユーザーのSFTP操作ログを取得する」設定手順として、chroot用ソケットファイルを使用する/しないの2つの手順を記載しました。

後半の「chroot用ソケットファイルを使用しない方法」については、若干バッドノウハウのような気もしますが、運用上の都合でやむを得ないケースもあるでしょう。

(関連記事)
・Garage labsサーバー部10Uに参加しました。~Linuxサーバーセキュリティ対策part3 – ファイル転送編
https://inaba-serverdesign.jp/blog/20130718/garagelabs_server10u.html
 

Follow me!