SSH 公钥认证仅在活动会话存在之前有效

SSH 公钥认证仅在活动会话存在之前有效

我的 SSH 配置出现了一个相当奇怪的问题。我借助远程访问卡设置了服务器,并使用 KVM 查看器配置了所有内容。

因此,当我通过 KVM Viewer 登录服务器时,我仅使用公钥配置了 SSH,并尝试从本地笔记本电脑登录。一切正常。

如果我退出 KVM 会话(或以 KVM 会话中的用户身份注销),我将无法再通过 ssh 登录(公钥被拒绝)。只有当用户仍在某处登录时,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 [email protected] none debug1: kex: client->server aes128-ctr [email protected] 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 [email protected] none debug1: kex: client->server aes128-ctr [email protected] 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 [email protected] debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env LANG = de_DE.UTF-8 Welcome to Ubuntu 14.04.1 LTS

答案1

当用户的主目录被加密时,在主目录被挂载之前无法从用户的主目录ecryptfs sshd读取文件。authorized_keys

登录时sshd将用于pam验证用户身份,并pam使用用户输入的密码来挂载加密的主目录。

如果您想限制sshd仅允许公钥认证,这就有问题了。

但是您authorized_keys也可以在服务器上放置未加密的文件。这将允许用户使用密钥登录,但由于这不会调用pam,因此不会挂载主目录,并且在不知道密码的情况下挂载主目录也将不起作用。

由于未加密的主目录被加密的主目录隐藏,因此authorized_keys首先放置未加密的文件可能有点棘手。底层文件系统的绑定挂载可以帮助解决这个问题。

例如,如果/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在密钥之前指定的。这将被调用而不是 shell。但这仅在使用此特定公钥时发生,并且仅在未挂载用户的主目录时发生。

如果用户的主目录已挂载,则此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第一个块。因此,该命令将要求输入用户的密码。但这不需要启用密码验证,因此只需使用公钥验证即可。ifecryptfs-mount-privatesshdsshd

下一个命令将更改为用户的加密主目录(直到那时脚本才会在未加密的主目录中运行)。

脚本的最后一部分将运行作为命令参数给出的命令ssh(如果有)或用户登录 shell(如果没有给出命令)。

需要注意的是,这不适用于 X11 转发,因为当存储 cookie 时,主目录尚不可用。但在主目录已安装时打开的任何其他会话都将能够处理 X11 转发。

改用~/.ssh/rc可能会解决 X11 转发问题。这是我尚未研究过的事情。

第一个if块有点儿像 hack,我想到的是允许在不需要密码的情况下挂载用户的主目录。相反,它使用转发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是任意随机值。用生成的 uuiduuidgen可以正常工作。shell 脚本使用 grep 在文件中查找相关行authorized_keys以提取公钥。

将 base64 编码的公钥以及 uuid 提供给 python 脚本。使用的公钥正是用户进行身份验证时使用的公钥。python 脚本要求转发代理使用相关公钥对特定消息进行签名(因为签名消息正是可以执行的操作ssh-agent)。然后使用 base64 对签名的一部分进行编码以生成密码。

此密码用于解密ecryptfs包装的密码文件,但主文件使用用户的登录密码加密。此文件使用从 ssh 密钥生成的密码加密。

答案2

我昨天受到了 kasperd 的想法的启发,所以我做了这个:

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

我已经尝试了一下,它似乎工作得很好。使用 SSH 时,它可以非常简单地添加/删除用于无密码解密 ecryptfs 主文件夹的密钥...

与 kasperd 的原版一样,它还没有经过专家的同行评审 - 但自从它出现在 github 上后,现在任何人都可以参与其中。:)

您仍然需要将密钥移到主文件夹之外,但这样您至少可以避免令人讨厌的密码登录......

享受!

答案3

这是一个简单的解决方案,但似乎并不优雅。

由于您的主文件夹已加密,因此只需将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手动到您的主目录。

相关内容