我的 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
第一个块。因此,该命令将要求输入用户的密码。但这不需要启用密码验证,因此只需使用公钥验证即可。if
ecryptfs-mount-private
sshd
sshd
下一个命令将更改为用户的加密主目录(直到那时脚本才会在未加密的主目录中运行)。
脚本的最后一部分将运行作为命令参数给出的命令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
手动到您的主目录。