web-dev-qa-db-ja.com

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

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

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

新しいユーザーは、notである必要があります:

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

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

105
Lekensteyn

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

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

これで、クライアントは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ユーザーは次のことができません。

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

これには多くの解決策があり、私が提案しているものよりもはるかに堅牢であると確信しています。ただし、これはニーズには十分かもしれません。そのためには、ユーザーが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」を使用できます。 グーグル はあまり役に立ちませんでした。 ssh -R 6901:localhost:6901を許可するには、「no-port-forwarding、permitremoteopen = 10001」のようなものが役立つと思われます。

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

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

3
smoser