5

Is it possible to configure OpenSSH (or any other standard sshd) to accept any key offered by a connecting client?

EG ssh -i ~/arbitraryKey hostname grants a login shell while ssh hostanme doesn't.

I ask because of a half remembered anecdote about a misconfigured server but I've had a look and I couldn't find anything that would actually let this happen without some form of deliberate hacking of the daemon. (Recompiling etc)

4

Configuring an SSH server to accept any password would be easy with PAM — put pam_permit on the auth stack, and voilà. The possibility of misconfiguring such an open system is inherent to the flexibility of PAM — since it lets you chain as many tests as you want, the possibility of doing 0 tests is unavoidable (at least without introducing weird exceptions that wouldn't cover all cases).

Key authentication doesn't go through PAM, and there's no configuration setting for “accept any key”. That would only be useful in extremely rare cases (for testing or honeypots), so it isn't worth providing it as an option (with the inherent risk of misconfiguration).

1

Gilles suggested that an anonymous ssh configuration would "only be useful in extremely rare cases", but one of those rare cases is the tmate service, used by developers the world over for pair programming and other sorts of shared terminal sessions.

You can use the Paramiko library for Python to create an ssh server that will accept connections using any public key, but that will reject connections that do not provide any key.

For example:

#!/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

This will permit ssh connections for which a private key is available. It doesn't matter which key is being used. It will reject any connections that are not capable of publickey authentication.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.