Назад | Перейти на главную страницу

Аутентификация открытого ключа SSH работает только в том случае, если ранее существовал активный сеанс

У меня довольно странная проблема с моей конфигурацией SSH. Я настроил свой сервер с помощью карты удаленного доступа и настроил все с помощью программы просмотра KVM.

Итак, во время входа на сервер через KVM Viewer я настроил SSH только с помощью pubkey и попытался войти в систему с моего локального ноутбука. Работало нормально.

Если я выхожу из сеанса KVM (или выхожу из системы с пользователем в сеансе KVM), я больше не могу войти через ssh (pubkey запрещен). Вход по SSH работает только до тех пор, пока пользователь где-то еще находится в системе.

Есть подсказки, в чем может быть проблема?


Вывод в консоль при неудачном входе в систему (обмен всеми личными данными):

OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011 debug1: Reading configuration data /Users/mylocaluser/.ssh/config debug1: Reading configuration data /etc/ssh_config debug1: /etc/ssh_config line 20: Applying options for * debug1: /etc/ssh_config line 103: Applying options for * debug1: Connecting to 100.100.100.100 [100.100.100.100] port 12345. debug1: Connection established. debug1: identity file /Users/mylocaluser/.ssh/id_rsa type 1 debug1: identity file /Users/mylocaluser/.ssh/id_rsa-cert type -1 debug1: identity file /Users/mylocaluser/.ssh/id_dsa type -1 debug1: identity file /Users/mylocaluser/.ssh/id_dsa-cert type -1 debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.2 debug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 debug1: match: OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 pat OpenSSH* debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5-etm@openssh.com none debug1: kex: client->server aes128-ctr hmac-md5-etm@openssh.com none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Server host key: RSA ab:12:23:34:45:56:67:78:89:90:12:23:34:45:56:67 debug1: Host '[100.100.100.100]:12345' is known and matches the RSA host key. debug1: Found key in /Users/mylocaluser/.ssh/known_hosts:36 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: Roaming not allowed by server debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey debug1: Next authentication method: publickey debug1: Offering RSA public key: /Users/mylocaluser/.ssh/id_rsa debug1: Authentications that can continue: publickey debug1: Offering RSA public key: /Users/mylocaluser/.ssh/id_rsa2 debug1: Authentications that can continue: publickey debug1: Trying private key: /Users/mylocaluser/.ssh/id_dsa debug1: No more authentication methods to try. Permission denied (publickey).

Вывод в консоль для успешного входа в систему (возможно только при "активном сеансе"): OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011 debug1: Reading configuration data /Users/mylocaluser/.ssh/config debug1: Reading configuration data /etc/ssh_config debug1: /etc/ssh_config line 20: Applying options for * debug1: /etc/ssh_config line 103: Applying options for * debug1: Connecting to 100.100.100.100 [100.100.100.100] port 12345. debug1: Connection established. debug1: identity file /Users/mylocaluser/.ssh/id_rsa type 1 debug1: identity file /Users/mylocaluser/.ssh/id_rsa-cert type -1 debug1: identity file /Users/mylocaluser/.ssh/id_dsa type -1 debug1: identity file /Users/mylocaluser/.ssh/id_dsa-cert type -1 debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.2 debug1: Remote protocol version 2.0, remote software version OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 debug1: match: OpenSSH_6.6.1p1 Ubuntu-2ubuntu2 pat OpenSSH* debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5-etm@openssh.com none debug1: kex: client->server aes128-ctr hmac-md5-etm@openssh.com none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Server host key: RSA ab:12:23:34:45:56:67:78:89:90:12:23:34:45:56:67 debug1: Host '[100.100.100.100]:12345' is known and matches the RSA host key. debug1: Found key in /Users/mylocaluser/.ssh/known_hosts:36 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: Roaming not allowed by server debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey debug1: Next authentication method: publickey debug1: Offering RSA public key: /Users/mylocaluser/.ssh/id_rsa debug1: Server accepts key: pkalg ssh-rsa blen 279 debug1: Authentication succeeded (publickey). Authenticated to 100.100.100.100 ([100.100.100.100]:12345). debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env LANG = de_DE.UTF-8 Welcome to Ubuntu 14.04.1 LTS

Когда домашний каталог пользователя зашифрован с помощью ecryptfs sshd не могу прочитать authorized_keys из домашнего каталога пользователя до его монтирования.

Во время входа в систему sshd буду использовать pam для аутентификации пользователя и pam будет использовать пароль, введенный пользователем, для монтирования зашифрованного домашнего каталога.

Это проблематично, если вы хотите ограничить sshd чтобы разрешить только аутентификацию с открытым ключом.

Однако вы можете разместить незашифрованный authorized_keys файл на сервере. Это позволит пользователю войти в систему с помощью ключа, но поскольку это не вызывает pam, домашний каталог не будет смонтирован, и смонтировать домашний каталог без знания пароля тоже не получится.

Поскольку незашифрованный домашний каталог скрывается зашифрованным домашним каталогом, размещение незашифрованного authorized_keys file в первую очередь может быть немного сложным. В этом может помочь привязка базовой файловой системы.

Если например /home это просто каталог в корневой файловой системе, вы можете сделать следующее:

mkdir /mnt/rootfs
mount --bind / /mnt/rootfs

И тогда вы можете создать /mnt/rootfs/home/$USER/.ssh/authorized_keys

Вы можете сделать больше. Поскольку зашифрованная и незашифрованная версия authorized_keys это два разных файла, в них можно поместить разное содержимое. Например, незашифрованная версия может вызывать сценарий для монтирования зашифрованного домашнего каталога:

command="/usr/local/bin/ecryptfs-mount-from-ssh" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM1Ot12ThbTcPOGpfh7AiRqp3P4BMm3DNo4mDg7gDFPwCmM9rKRHTH0fBVSqkSGlXm84q29bckDukg7vfqkbTpbkP3e2YmTkP6p1J2SoX2QMUnBRRgL9It/ZiAfA2I4QzUrcywVvokO1F2DqcRLy5e5wKTUFfvIm6D2QfBmGbnW2Kkpn16hQyLT1ClXjFC1qXUhazePv0cAtWUCUGjRcLr/ipOphS7eOB46cGhYqtbMkKx0t93ZG4f6jM0o32cYy3RqprpZpTmCeG1gDyG+IlSLBYXYggr72iwTKsTZ9pMDTCBQ8Pb7l317TPOcJzTtDxnpgpGE3x4Vu/Ww+zhsIeT kasperd 2014 May 24

Важная часть - это command указан перед ключом. Это вызывается вместо оболочки. Но это происходит только тогда, когда используется этот конкретный открытый ключ, и только если домашний каталог пользователя не смонтирован.

Если домашний каталог пользователя уже смонтирован, это authorized_keys файл скрыт, и вместо него используется зашифрованная версия. Зашифрованная версия authorized_keys не имеет command, поэтому сценарий для монтирования домашнего каталога не запускается.

Итак, что входит в сценарий. Вот моя версия:

#!/bin/bash -e

if [ $# = 1 ]
then
    PUBKEY="$(
        grep "$1" "$HOME/.ssh/authorized_keys" |
            sed -e 's/.* ssh-rsa //;s/ .*//')"
    /usr/local/bin/ssh-agent-ecryptfs-decryption.py "$PUBKEY" "$1" |
        ecryptfs-unwrap-passphrase "$HOME/.ecryptfs-ssh-wrapped/$1" - |
        ecryptfs-add-passphrase --fnek
fi
ecryptfs-mount-private
cd "$HOME"

if [ "$SSH_ORIGINAL_COMMAND" != "" ]
then
    exec /bin/bash -c "$SSH_ORIGINAL_COMMAND"
fi

exec /bin/bash -l

В приведенном выше примере authorized_keys файл вызывается без аргументов, поэтому первый if блок пропускается. В ecryptfs-mount-private таким образом команда запросит пароль пользователя. Но для этого не требуется sshd включить аутентификацию по паролю, и таким образом будет работать на sshd только с аутентификацией с открытым ключом.

Следующая команда перейдет в зашифрованный домашний каталог пользователя (до тех пор скрипт будет выполняться внутри незашифрованного домашнего каталога).

Последняя часть скрипта выполнит команду, заданную как аргумент для ssh команда, если она есть, или оболочка входа пользователя, если команда не была дана.

Одно предостережение заключается в том, что это не работает с пересылкой X11, потому что домашний каталог еще не доступен, когда cookie будет сохранен. Но любой другой сеанс, открытый в то время, когда домашний каталог уже смонтирован, сможет обрабатывать пересылку X11.

С помощью ~/.ssh/rc вместо этого может решить проблему пересылки X11. Это то, что я еще не изучал.

Первый if block - это своего рода хитрость, которую я придумал, чтобы можно было смонтировать домашний каталог пользователя без пароля. Вместо этого используется перенаправленный ssh-agent чтобы смонтировать домашний каталог пользователя. В этой части содержится отказ от ответственности об отсутствии экспертной оценки, поэтому доверять криптографии в ssh-agent-ecryptfs-decryption.py полностью на ваш страх и риск.

Скрипт python выглядит так:

#!/usr/bin/env python

from sys import argv
from os import environ
import socket

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(environ['SSH_AUTH_SOCK'])

def encode_int(v):
    return ('%08x' % v).decode('hex')

def encode_string(s):
    return encode_int(len(s)) + s

def encode_mpint(v):
    h = '%x' % v
    if len(h) & 1: h = '0' + h
    return ('%04x%s' % (len(h) * 4, h)).decode('hex')

key_blob = argv[1].decode('base64')
msg = 'ecryptfs-decrypt ' + argv[2]

s.send(encode_string(chr(13) +
                     encode_string(key_blob) +
                     encode_string(msg) +
                     encode_int(0)))

response = s.recv(1024)

assert response == encode_string(chr(14) + response[5:]), argv[1]

passphrase = response[-48:].encode('base64').replace('\n', '')

print passphrase

Так как же работает расшифровка? Прежде всего, аргумент сценария, предоставленный authorized_keys - любое случайное значение. UUID, созданный с помощью uuidgen может работать. Сценарий оболочки использует команду grep для поиска соответствующей строки в authorized_keys файл для извлечения открытого ключа.

Открытый ключ в кодировке base64, а также uuid передаются скрипту python. Используемый открытый ключ - это именно тот ключ, с помощью которого пользователь прошел аутентификацию. Сценарий python запрашивает у перенаправленного агента подпись в конкретном сообщении с использованием рассматриваемого открытого ключа (поскольку подписывание сообщений - это именно то, что ssh-agent сможет сделать). Затем часть подписи кодируется с помощью base64 для создания пароля.

Этот пароль используется для расшифровки ecryptfs обернутый файл паролей, но основной файл зашифрован с использованием пароля для входа пользователя. Он зашифрован паролем, сгенерированным из ключа ssh.

Вчера меня так вдохновила идея Касперда, что я сделал следующее:

https://github.com/bjornnorman/decryptfs-ssh

Я уже немного попробовал, и, кажется, работает блестяще. Это упрощает добавление / удаление ключей для дешифрования домашних папок ecryptfs без пароля при использовании SSH ...

Как и оригинал kasperd, он не был подвергнут экспертной оценке экспертами, но поскольку он находится на github, теперь любой может принять участие. :)

Вам все равно придется перемещать ключи за пределы вашей домашней папки, но с этим вы, по крайней мере, можете избежать неприятного входа в систему с паролем ...

Наслаждайтесь!

Вот простое решение, но оно не выглядит элегантным.

Поскольку ваша домашняя папка зашифрована, просто поставьте authorized_keys файл в незашифрованном месте.

Затем вам нужно указать ssh, где authorized_keys является. В /etc/ssh/sshd_config, добавить:

Match User [your_user_name]
AuthorizedKeysFile [new_path_to_authorized_keys]

ПРИМЕЧАНИЕ. Обязательно установите Match в конце файла. В Match остается в силе до конца файла или другого Match встречается.

Теперь вы можете войти в систему через ssh, и вам не нужно сначала входить в систему локально. Но после входа в систему по ssh вам нужно запустить:

ecrypts-mount-private

и введите свой пароль, чтобы смонтировать вашу домашнюю папку, а затем cd домой вручную.