ポート転送用の制限されたSSHユーザーを作成する方法は?


106

ændrük は、他の誰かと簡単にSSH接続するための逆接続提案しました(リモートヘルプ用)。それが機能するためには、接続を受け入れるために追加のユーザーが必要です。このユーザーは、サーバーを介してポートを転送できる必要があります(サーバーはプロキシとして機能します)。

上記のことしかできない制限付きユーザーを作成するにはどうすればよいですか?

新しいユーザーは次のことができないようにする必要があります。

  • シェルコマンドを実行する
  • ファイルへのアクセスまたはサーバーへのファイルのアップロード
  • サーバーをプロキシとして使用する(例:webproxy)
  • ファイアウォールが原因で一般にアクセスできなかったローカルサービスにアクセスする
  • サーバーを殺す

要約すると、特権なしでSSHサーバーにのみ接続できる制限されたSSHユーザーを作成するにはどうすればよいですか?その接続を介して彼のコンピューターに接続できますか?


回答:


166

TL; DR-答えの一番下にある「制限の適用」

制限されたユーザーの追加は、2つの部分で構成されます。1.ユーザーの作成2. SSHデーモン(sshd)の構成

sshdの構成

SSHの可能性を知るのに最適な場所は、関連するマニュアルページを読むことです。

SSHクライアントはどこでアクションを実行できますか?

何かを制限する前に、SSHの機能を知る必要があります。マニュアルページを表示すると、

  • シェルコマンドの実行
  • sftpを介したファイルのアップロード
  • ポート転送
    • クライアントは、使用されていないポートをサーバーに転送します
    • サーバーは自分のポートをクライアントに転送します
    • サーバーは別のホストのポートをクライアントに転送します(プロキシー様)
  • X11転送(ディスプレイ転送)
  • 認証エージェントの転送
  • トンネルデバイスの転送

sshd(8)のマニュアルページのAuthenticationセクションから:

クライアントが自身の認証に成功すると、セッションを準備するためのダイアログが表示されます。この時点で、クライアントは、疑似ttyの割り当て、X11接続の転送、TCP接続の転送、または安全なチャネル介した認証エージェント接続の転送などを要求 できます。

この後、クライアントはシェルまたはコマンドの実行を要求します。その後、両サイドはセッションモードに入ります。このモードでは、どちらの側もいつでもデータを送信でき、そのようなデータはサーバー側のシェルまたはコマンド、およびクライアント側のユーザー端末との間で転送されます。

SSH機能を制限するためのオプション

動作を変更するファイルとそのオプションは次のとおりです。

  • ~/.ssh/authorized_keys -オプションを与えることができる接続を許可されているキーが含まれています:
    • command="command"-ユーザーが提供したコマンド(ある場合)は無視されます。クライアントが明示的に禁止されていない限り、クライアントはTCPおよび/またはX11転送を指定することに注意してください。このオプションは、シェル、コマンド、またはサブシステムの実行に適用されることに注意してください。
    • no-agent-forwarding -このキーが認証に使用される場合、認証エージェントの転送を禁止します。
    • no-port-forwarding -このキーが認証に使用される場合、TCP転送を禁止します
    • no-X11-forwarding -「このキーが認証に使用されている場合、X11転送を禁止します。」
    • permitopen="host:port" -指定されたホストとポートにのみ接続できるように、ローカルの「ssh -L」ポート転送を制限します。
  • ~/.ssh/environment-このファイルは、ログイン時に環境に読み込まれます(存在する場合)。環境処理はデフォルトで無効になっており、PermitUserEnvironmentオプションを介して制御されます
  • ~/.ssh/rc -ユーザーのホームディレクトリにアクセス可能になる前に実行される初期化ルーチンが含まれています。
  • /etc/ssh/sshd_config -システム全体の構成ファイル
    • AllowAgentForwarding -ssh-agent(1)転送が許可されるかどうかを指定します。
    • AllowTcpForwarding
    • ForceCommand -「クライアントおよび〜/ .ssh / rcが提供するコマンドを無視し、ForceCommandで指定されたコマンドの実行を強制します。コマンドは、ユーザーのログインシェルで-cオプションを使用して呼び出されます。」
    • GatewayPorts -「クライアントに転送されるポートへのリモートホストの接続を許可するかどうかを指定します。デフォルトでは、sshd(8)はリモートポート転送をループバックアドレスにバインドします。そのsshdは、リモートポートフォワーディングが非ループバックアドレスにバインドできるようにして、他のホストが接続できるようにする必要があります。
    • PermitOpen

      TCPポート転送が許可される宛先を指定します。転送仕様は、次のいずれかの形式である必要があります。

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      複数の転送は、空白で区切って指定できます。「any」の引数を使用して、すべての制限を削除し、転送要求を許可できます。デフォルトでは、すべてのポート転送要求が許可されています。

    • PermitTunnel-tun(4)デバイス転送が許可されるかどうかを指定します。デフォルトは「no」です
    • X11Forwarding-X11転送を許可するかどうかを指定します。デフォルトは「no」です

制限を適用する

システム全体の構成ファイルを変更すると、/etc/ssh/sshd_configパスワードベースの認証が適用されたり、制限~/.ssh/authorized_keysが誤って削除されたりした場合でも、構成を適用できます。グローバルデフォルトを変更した場合は、それに応じてオプションのコメントを解除する必要があります。

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

ユーザーを追加します:

sudo useradd -m limited-user

ForceCommandシェルが/bin/false(または/bin/true)のような非シェルに設定されている場合、/bin/false -c [command]何もしないので、オプションは省略できます。

これで、クライアントはSSH経由でサーバーのループバックアドレスのポート62222にのみ接続できます(パブリックIPアドレスでリッスンしません)

無効にAllowTcpForwardingすると、の使用も禁止されるため-R、そのような制限されたアカウントを使用して単一ポートを転送することはできなくなります。PermitOpen localhost:62222クライアントは喜んでサーバーに接続してリッスンできるため、サーバーのポート62222は使用されないと想定しています。

システム全体の構成でTCP転送が許可され、パスワードベースの認証が無効になっている場合は、キーごとの設定も使用できます。~/.ssh/authorized_keys次のオプションを編集して追加しますssh-(オプションとの間にスペースを入れますssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

確認する

期待どおりに機能することを確認するには、いくつかのテストケースを実行する必要があります。以下のコマンドでhostは、で設定されていない場合、実際のログインに置き換える必要があります~/.ssh/config。コマンドの背後に、クライアントまたはサーバー(指定どおり)で実行されるコマンドが表示されます。

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

結論

チェックリスト:SSHユーザーは次のことができません。

  • シェルコマンドの実行- 完了
  • ファイルへのアクセスまたはサーバーへのファイルのアップロード- 完了
  • サーバーをプロキシとして使用(例:webproxy)- 完了
  • ファイアウォールが原因で一般にアクセスできないローカルサービスにアクセスする- 一部、クライアントは62222以外のポートにアクセスできませんが、サーバーのポート62222をリッスンして接続できます
  • サーバーを強制終了- 完了 (これらのチェックはSSHサーバーに限定されていることに注意してください。マシン上に他の脆弱なサービスがある場合、攻撃者がコマンドを実行したり、サーバーを強制終了したりできます)

3
これを機能させるには、追加したアカウントのuseraddロックを解除する必要があります。パスワードを/etc/shadowasteric(*)に置き換えるか、またはを使用してパスワードを設定することでそれができますsudo passwd limited-user
レーケンシュタイン

2
SSHサーバーがsftp-serverコマンドを実行するため、SFTPは機能します。ではForceCommand、このコマンドはもう実行されません。
Lekensteyn

2
from=オプションも便利ですauthorized_keys。特定のIPアドレスまたはホスト名を持つソースへのキーの使用を制限できます。例、from="1.1.1.1"またはfrom="10.0.0.?,*.example.com"。すべてのauthorized_keysオプションについては、manページ(linux.die.net/man/8/sshd)のセクション「AUTHORIZED_KEYS FILE FORMAT」を参照してください。
ドンリー

2
「AllowTcpForwarding local」は、リモート転送を禁止します。(この答えが書かれたときに存在したかどうかはわかりません。)
サイモンサピン

1
これは永続的なssh接続によって壊れるので、に接続するときはファイル内に何かがあるべきではないことに注意Host * ControlMaster autoしてください。必要な場合は、~/.ssh/configssh -Nssh -N -o ControlMaster=no
-nh2

3

これには多くの解決策があり、私が提案しているものよりもはるかに堅牢であると確信しています。ただし、これで十分な場合があります。それを行うために、ユーザーがsshキーベースの認証を実行できると仮定しています(puttyまたは任意のUNIX sshがこれをサポートする必要があります)。

  • 通常どおりユーザーを追加します(「adduser」またはその他のツール)

  • ユーザー.ssh dirおよび.ssh / authorized_keysを作成します

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • このアカウントへのパスワードアクセスを無効にします。
your_user $ sudo usermod --lock ssh_forwarder

現在、ユーザーがシステムにアクセスできる唯一の方法は、適切なsshキーにアクセスすることです。sshは、実行しようとしても「/ bin / bash -c 'read a'」を実行します。「read a」は改行まで読み込めば、シェルは終了するので、ユーザーは「enter」を押すだけで接続を切断できます。

「command =」でできることは他にもたくさんあります。詳細についてはman authorized_keys、「コマンド」を参照して検索してください。

Enterキーを押すと接続が切断されるという事実が気に入らない場合は、 'command ='エントリに次のようなものを使用できます。

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

これは、ユーザーのホームディレクトリに一時的なfifoを作成し、そこから読み取りを試みます。そのファイルには何も書き込まれないため、これは無期限にハングします。さらに、その接続を強制的に終了したい場合、次のようなことができます:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

これはごくわずかなリソースを使用する必要があり、シェルの終了で終了しないスクリプトでは何も問題が発生しないはずです。

sleep 1h; echo You have been here too long. Good bye.

ユーザーにリモートフォワード(ssh -R)を許可する方法はわかりませんが、制限します(ssh -L)。おそらく「permitopen」を使用できます。 グーグルはあまり役に立ちませんでした。'no-port-forwarding、permitremoteopen = 10001'のようなものが許可するのに役立つと思われますssh -R 6901:localhost:6901

これは、ソリューション。それは間違いなく改善される可能性があり、リモートポートのオープンはすべて精査されるべきです。祖母が私のLANに接続できるようにすることが私の目標であり、vncを使用して彼女の画面を表示でき、それらのキーへのアクセスが彼女に限定されていた場合、私は個人的には合理的に安全だと感じます。これが企業向けの場合、より徹底的な調査が必要になります。知っておくべきことの1つは、シェルをまったく要求しないため、「command =」コードは実行されないことです。ssh -N

他の、おそらくより安全なメカニズムには、ユーザー用のカスタムシェルの作成や、それを装甲で固定することも含まれます。


3
これは非常にハックに見えます。コマンドを実行する必要がないため、シェルを用意する必要さえありません。参照のマニュアルページsshのための-Nオプションを選択します。これを実現するには、よりクリーンな方法が必要です。
レーケンシュタイン

それは本当だ。私はまた、よりクリーンなソリューションを期待しています。'permitremoteopen'オプションがあれば、authorized_keysとno-port-forwardingはかなり良い解決策になると思います。
喫煙者

再検索を行いました(上記参照)。以来ssh -N、まったくのコマンドを実行していない、それは問題ありませんcommand="something"セッションを閉じます。
レーケンシュタイン

何か不足していますか?それが見えたchsh ssh_forwarder -s /bin/false それが取るすべてです。
typelogic
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.