web-dev-qa-db-ja.com

認証用の秘密鍵を受け入れる

接続しているクライアントから提供されたキーを受け入れるようにOpenSSH(またはその他の標準sshd)を構成することは可能ですか?

EG ssh -i ~/arbitraryKey hostnameはログインシェルを許可しますが、ssh hostanmeは許可しません。

サーバーの構成が間違っているという逸話を半分覚えているので尋ねますが、調べてみたところ、デーモンを意図的にハッキングしない限り、実際にこれを実現できるものは見つかりませんでした。 (再コンパイルなど)

5
Lex R

PAMを使用すると、任意のパスワードを受け入れるようにSSHサーバーを構成するのは簡単です— put pam_permitauthスタック上で、voilà。このようなオープンシステムを誤って構成する可能性は、PAMの柔軟性に固有のものです。必要な数のテストを連鎖させることができるため、0のテストを実行する可能性は避けられません(少なくとも、すべてのケースをカバーしない奇妙な例外を導入することなく) )。

キー認証はPAMを経由せず、「任意のキーを受け入れる」ための構成設定はありません。これは非常にまれなケース(テストまたはハニーポットの場合)でのみ役立つため、オプションとして提供する価値はありません(構成ミスの固有のリスクがあります)。

Gillesは、匿名のssh構成は「非常にまれなケースでのみ役立つ」と提案しましたが、そのまれなケースの1つは、世界中の開発者がペアプログラミングやその他の種類の共有に使用する tmate サービスです。ターミナルセッション。

Paramiko ライブラリをPythonに使用して、任意の公開鍵を使用した接続を受け入れるsshサーバーを作成できますが、それはキーを提供しない接続を拒否します。

例えば:

#!/usr/bin/python
import paramiko
import socket
import threading

Host_key = paramiko.RSAKey(filename='hostkey')


class Server(paramiko.ServerInterface):
    def __init__(self):
        self.event = threading.Event()

    def check_channel_request(self, kind, chanid):
        if kind == 'session':
            return paramiko.OPEN_SUCCEEDED

    def check_auth_publickey(self, username, key):
        return paramiko.AUTH_SUCCESSFUL

    def get_allowed_auths(self, username):
        return 'publickey'

    def check_channel_exec_request(self, channel, command):
        # This is the command we need to parse
        print('client sent command: {}'.format(command))
        self.event.set()
        return True


def listener():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', 2222))

    sock.listen(100)
    client, addr = sock.accept()

    t = paramiko.Transport(client)
    t.set_gss_Host(socket.getfqdn(""))
    t.load_server_moduli()
    t.add_server_key(Host_key)
    server = Server()
    t.start_server(server=server)

    # Wait 30 seconds for a command
    server.event.wait(30)
    t.close()


while True:
    try:
        listener()
    except KeyboardInterrupt:
        pass

これにより、秘密鍵が使用可能なssh接続が許可されます。 どのキーが使用されているかは関係ありません。公開鍵認証ができない接続はすべて拒否されます。

1
larsks