我的问题与这里提出的问题类似: 蚂蚁 scp 任务失败
BUILD FAILED com.jcraft.jsch.JSchException: reject HostKey: ....
我的问题是为什么在我的已知主机文件中找不到密钥?
无论我拥有哪种known_hosts文件,主机密钥都会被拒绝。通过 ssh 连接工作得很好,并添加了相关条目,但也许jsch
无法读取 OpenSSH 生成的known_hosts
文件?
Ant 文档提到已知主机文件需要采用 SSH2 格式,而不是 SSH1。具有讽刺意味的是,来自OpenSSH的SSH2格式known_hosts文件应该是~/.ssh/known_hosts2
的,但已知主机的默认值是~/.ssh/known_hosts
。
SSH2创建的已知主机文件是~/.ssh2/knownhosts/
,因此可以安全地将其计算为预期的格式。到目前为止,我一直无法让 OpenSSH 创建一个known_hosts2
文件,而且手册页也没有太大帮助。那么文档实际上意味着文件需要采用 SSH2 格式是什么意思?
我已经尝试了dsa
和rsa
密钥,但都不起作用(两者都适用于 OpenSSH)。
我搜索了两天,我找到的唯一答案是"set trust="true
"。是的,这让任务顺利进行,但并非没有对安全性视而不见。
这是我发现的一种适用于较新版本的 jch 的格式:
[xx.xx.xx.xx]:22 ssh-rsa .......
在旧版本中,它是这样的:
xx.xx.xx.xx ssh-rsa ......
即没有方括号和端口号。 (如果您使用端口 22,不确定是否需要端口号,但我使用为 SSH 分配了非默认端口的服务器对其进行了测试。 而且,如果它不明显,xx.xx.xx.xx
应该是服务器的 IP 地址,或主机名或其他任何东西。
我通过让 JCraft/jsch 库为我生成known_hosts文件找到了这种格式。 如果您访问 www.jcraft.com 您可以下载 jsch 源代码的 zip 和一些示例。 要么构建源代码来制作一个罐子,要么下载现成的罐子。 我解压缩了zip下载,然后将jar文件放在同一个目录中。
有一个包含KnownHosts.java
的examples
文件夹。 您需要编译该文件,然后运行它 - 它会要求您提供known_hosts文件(只需先在默认位置创建一个空文件(~/.ssh/known_hosts
),然后选择该文件。 然后它会询问您连接到服务器的详细信息... 输入这些,例如sshusername@xx.xx.xx.xx
,程序将尝试连接,然后为您填充known_hosts文件。
为了方便像我这样永远不记得如何从命令行做事的 Windows 用户,以下是编译和运行该KnownHosts.java
文件所需的内容:
首先,导航到目录(解压缩并放入 jar 文件,如上所述)。
然后运行:
javac -cp jsch-0.1.49.jar examples/KnownHosts.java
编译已知主机.java。 然后:
java -cp "examples;jsch-0.1.49.jar" KnownHosts
来运行它。 按照上述说明操作,您应该有一个工作known_hosts文件。
最后一点:KnownHosts 程序假定端口为 22。 我对其进行了编辑,以允许我输入类似sshusername@xx.xx.xx.xx:8888
的内容,以便我可以指定具有自定义端口的服务器并使其如上所述工作。 在KnownHosts的源代码中.java我查找了如下行:
Session session=jsch.getSession(user, host, 22);
并将其替换为:
int port = 22;
final int colonIndex = host.indexOf(':');
if (colonIndex > -1) {
final String[] split = host.split(":");
host = split[0];
port = Integer.parseInt(split[1]);
}
Session session=jsch.getSession(user, host, port);
然后按上述方式编译并运行。
sshexec ant 任务正在查找文件"known_hosts",默认为 ${user.home}/.ssh/known_hosts
验证"user.home"系统属性的值。可能它指向未预料到的地方。 或者在 ant 任务的属性中显式提供"已知主机"值。
您可能对两个参数感兴趣:
trust
: 如果设置为true,将信任未知主机。默认值设置为false。knownhosts
:设置为已知主机文件的位置。
第一个将允许您将任务设置为不检查它是否是已知主机。第二个将允许您指定包含已知主机的文件。这样,您可以将其指定为${user.home}/.ssh/known_hosts2
并覆盖默认值。
顺便说一下,执行此操作的一个好方法是使用这些值的属性,然后使用属性文件重写这些属性:
[...]
<property name="build.properties" value="build.properties"/>
<property file="${build.properties}"/>
<!-- Can be overridden via 'build.properies' file -->
<property name="knownhosts.file" value="${user.home}/.ssh/knownhosts"/>
<property name="remote.host" value="foo-system"/>
[...]
<scp file="${copy.this.file}"
todir="${user}@{host}:${remote.dir}"
knownhosts="${knownhosts.file}"/>
[...]