【rbash】SCP転送したいがSSH接続時はコマンドの実行を制限したい場合
タイトル通りですが、SCP転送させたいがSSH接続は制限するというちょっとワガママなことを実現させる方法になります。
目次
・要件
・ユーザーの作成
・鍵作成&設定
・rbashの設定
・環境変数 $PATHの設定
要件
・SCP転送でファイルを送りたい
・SSH接続(*1)されても、ある程度制限かけたい(*2)
・SCP転送用のユーザーを用意する
SCP転送先&ホームディレクトリ:/opt/test-file
(*1)
SSH接続先でのコマンド実行方法としては以下の2パターンが考えられるので、どちらも制限したいと思います。
[root@src-server ~]# ssh test-user@aaa.aaa.aaa.aaa [test-user@dest-server ~]# ls
②SSHコマンドと同時にSSH接続先でコマンドを実行する
例)
[root@src-server ~]# ssh test-user@aaa.aaa.aaa.aaa ls
(*2)
ある程度の制限とは、SSH接続先であるサーバ内のディレクトリやファイルを参照または変更できないことを言います。
例えば、ls,mv,rm,rmdirコマンドの実行禁止。
前提
・転送元サーバ、転送先
OS:CentOS7.9
Shell:bash
ユーザーの作成
SCP転送用のユーザー、グループを作成します。
ユーザー名:test-user
グループ名:test-group
[test-user@dest-server ~]# groupadd test-group [test-user@dest-server ~]# grep test-group /etc/group test-group:x:1002: [test-user@dest-server ~]# useradd test-user -g 1002 -d /opt/test-file [test-user@dest-server ~]# grep test-user /etc/passwd test-user:x:2001:1002::/opt/test-file:/bin/bash
鍵作成&設定
test-user用の公開鍵と秘密鍵を作成します。
[test-user@dest-server ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/opt/test-file/.ssh/id_rsa): Created directory '/opt/test-file/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /opt/test-file/.ssh/id_rsa. Your public key has been saved in /opt/test-file/.ssh/id_rsa.pub. The key fingerprint is: SHA256:cqxkgcm6HyA8/fmD663EM+XyTXEy7hHxmmjSL7L0ujc test-user@dest-server The key's randomart image is: +---[RSA 2048]----+ | | | . o | | + . . | |. .. o o | |.oo. +.S= o | | ..ooo=+o O | | . .@o= * | | .o+@E= . | | oBO=++ | +----[SHA256]-----+
公開鍵の名前は変更させ、パーミッションは600に変更してください。
[test-user@dest-server ~]# mv /opt/test-file/.ssh/id_rsa.pub /opt/test-file/.ssh/authorized_keys [test-user@dest-server ~]# chmod 600 /opt/test-file/.ssh/authorized_keys
rbashの設定
rbashを作成します。
rbashとは、制限機能付きシェルのことで、cdコマンドの実行等を制限してくれます。
rbashが制限できる機能の詳細は、以下のマニュアルにあります。
Man page of RBASH
[test-user@dest-server ~]# ln -s /bin/bash /bin/rbash [test-user@dest-server ~]# ll /bin/ | grep bash lrwxrwxrwx. 1 root root 9 Jan 28 14:36 rbash -> /bin/bash
test-userが実行するシェルをrbashに変更します。
[test-user@dest-server ~]# usermod -s /bin/rbash test-user [test-user@dest-server ~]# grep test-user /etc/passwd test-user:x:2001:1002::/opt/test-file:/bin/rbash
環境変数 $PATHの設定
現状の設定だとtest-userの実行シェルはrbashを指定していますが、test-userの./bash_profileで設定されている$PATHはデフォルトのままです。
仮にSSH接続した場合、rbashのシェルとして実行されるのでcdコマンドの実行は制限できます。
ただし$PATHの中身は変わっていないので、binディレクトリ配下などにあるコマンドが実行できてしまい、結果としてcdコマンド以外のコマンドは通常通り実行できてしまいます。
そのため、$PATHはscpコマンドしか実行できないよう、scpコマンドのシンボリックリンクが配置されているディレクトリを指定する必要があります。
[test-user@dest-server ~]# vim /opt/test-file/.bash_profile PATH=$PATH:$HOME/.local/bin:$HOME/bin ↓ PATH=/opt/test-file
では、実際にSSH接続してコマンドの実行は制限できているか確認してみます。
まずはパターン①を実施します。
①SSH接続後にSSH接続先のサーバでコマンドの実行
[root@src-server ~]# ls -rbash: ls: command not found [root@src-server ~]# cd -rbash: cd: restricted
lsコマンドはコマンドの参照先(今回の場合では/opt/test-file配下)にlsコマンドの実行に必要なファイルが存在しないので、参照エラーとなっています。
cdコマンドはrbashで実行を制限しているので、「restriced」と表示されています。
次にパターン②を実施します。
②SSHコマンドと同時にSSH接続先でコマンドを実行する
[root@src-server ~]# ssh test-user@192.168.2.32 ls -ls total 0 0 -rw-r--r--. 1 root root 0 Jan 28 14:53 hoge
残念ながらrbashと$PATHを変更したにも関わらず、「ls -ls」コマンドが実行されてしまいました。。。
調べてみるとどうやら以下の仕様が原因のようです。
ssh(1) manページ
コマンド が指定されている場合は コマンド はログインシェルの代わりにリモートホスト上で実行されます。
bash は、リモートシェルデーモン rshd やセキュアシェルデーモン sshd によって実行された場合など、標準入力がネットワーク接続に接続された 状態で実行されたかどうかを調べます。 この方法によって実行されていると bash が判断した場合、 ~/.bashrc が存在し、かつ読み込み可能であれば、 bash はコマンドをこのファイルから読み込んで実行します。
先ほどパターン②で実行したSSHコマンドの「ls -ls」コマンドが実行できてしまうのは、
SSH接続時だが.pash_profileではなく、.bashrcファイルを実行しているため「/opt/test-file」ではないデフォルトの$PATHで実行されてしまうからのようです。
従ってパターン②のリモートコマンドの実行を制限するために、.bashrcファイルで$PATHを定義するように設定を変更します。また今回.bashrcで$PATHを定義するので、.bash_profileの$PATHはコメントアウトします。
[root@src-server ~]# vim /opt/test-file/.bash_profile PATH=/opt/test-file ↓ #PATH=/opt/test-file :wq
[root@src-server ~]# vim /opt/test-file/.bashrc PATH=/opt/test-file :wq
再度、パターン②を実行します。
②SSHコマンドと同時にSSH接続先でコマンドを実行する
[root@src-server ~]# ssh test-user@x ls -ls rbash: ls: command not found
今度はちゃんと制限できましたね。
最後にSCP転送を試すと
[root@src-server ~]# scp ./source-file test-user@192.168.2.32:~ rbash: scp: command not found lost connection
SCP転送が失敗しましたね。
先ほどscp転送先サーバであるtest-userのシェルはrbashで実行するように変更したせいか、scpコマンドはNGのようです。
なのでscpコマンドが実行できるようにscpファイルのシンボリックリンクを作成します。
[test-user@dest-server ~]# ln -s /bin/scp /opt/test-file/scp [test-user@dest-server ~]# ls -l /opt/test-file/ lrwxrwxrwx. 1 root root 8 Jan 28 15:40 scp -> /bin/scp
再度SCP転送を試してみます。
[root@src-server ~]# scp -i id_rsa ./source-file test-user@192.168.2.32:~ source-file 100% 0 0.0KB/s 00:00 [test-user@dest-server ~]# ls -l -rw-r--r--. 1 test-user test-group 0 Jan 28 15:52 source-file
無事、SCP転送できました。
これで上記の要件はすべて満たせますね。
最後にこのままだと転送先サーバ上でSCPコマンドが実行できてしまうので、iptablesもしくはセキュリティグループでアウトバウンド側のSSH(デフォルトport22)は通信できないよう設定すれば問題ないかと思います。