无法使用带有私钥的Apache Camel访问SFTP位置。
SFTP URI:sftp://user@host:22/usr/users/me/inbox/myfolder/?privateKeyFile=ssk-key.pem
确认密钥文件是正确的。
错误:
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot connect to sftp://user@host:22
at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:146)
at org.apache.camel.component.file.remote.RemoteFileConsumer.connectIfNecessary(RemoteFileConsumer.java:203)
at org.apache.camel.component.file.remote.SftpConsumer.doStart(SftpConsumer.java:52)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
at org.apache.camel.impl.DefaultCamelContext.startService(DefaultCamelContext.java:3269)
at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRouteConsumers(DefaultCamelContext.java:3563)
at org.apache.camel.impl.DefaultCamelContext.doStartRouteConsumers(DefaultCamelContext.java:3499)
at org.apache.camel.impl.DefaultCamelContext.safelyStartRouteServices(DefaultCamelContext.java:3429)
at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRoutes(DefaultCamelContext.java:3197)
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:3053)
at org.apache.camel.impl.DefaultCamelContext.access$000(DefaultCamelContext.java:175)
at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:2848)
at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:2844)
at org.apache.camel.impl.DefaultCamelContext.doWithDefinedClassLoader(DefaultCamelContext.java:2867)
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:2844)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:2813)
at org.apache.camel.main.Main.doStart(Main.java:127)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61)
at org.apache.camel.main.MainSupport.run(MainSupport.java:138)
at org.apache.camel.main.MainSupport.run(MainSupport.java:390)
at com.me.mypackage.MainApp.main(MainApp.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: com.jcraft.jsch.JSchException: SSH_MSG_DISCONNECT: 2 Protocol error: no matching DH grp found
at com.jcraft.jsch.Session.read(Session.java:996)
at com.jcraft.jsch.Session.connect(Session.java:323)
at org.apache.camel.component.file.remote.SftpOperations.connect(SftpOperations.java:118)
... 26 more
答案 0 :(得分:3)
编辑:在尝试下面之前,首先检查您正在运行的Java版本。如果是版本7或更早版本,请尝试升级到JRE 8并查看问题是否仍然存在。自从我回答这个问题后,我遇到了拒绝使用Java 7的情况,但是在8时工作正常。这可能与某些默认安全提供程序设置有关。
查看堆栈跟踪的结尾,Camel正在使用JSch库通过SSH支持FTP。知道这可以用于进一步的故障排除,因为您可以查找JSch支持哪些密钥交换算法。
当客户端尝试与服务器建立安全连接时,会交换支持的算法列表,以确定客户端和服务器支持的算法。然后为密钥交换选择一种算法。
从服务器返回的错误消息判断,SFTP服务器很可能使用OpenSSH。返回错误消息并且服务器断开连接的部分位于OpenSSH源中:
kex->dh = PRIVSEP(choose_dh(min, nbits, max));
if (kex->dh == NULL) {
sshpkt_disconnect(ssh, "no matching DH grp found");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
" DH grp"指Diffie-Hellman组。 Diffie-Hellman是一种公钥交换方法。这些组确定支持哪些密钥长度。一些例子:
在上面的C代码位中,您会注意到DH组搜索最小位数,首选位数(nbits
)和最大位数。这些数字由客户端(Camel中的JSch)提供,以指示它支持的内容。然后服务器寻找最佳组。如果找不到这些条件,则会与消息no matching DH grp found
断开连接。
您可以在此IETF备忘录中找到一些信息:https://tools.ietf.org/html/rfc4419。相关的一点:
C发送" min || n || MAX"到S,表示最小可接受的组大小,组的首选大小,以及客户端将接受的最大组大小。
- 醇>
S找到一个最符合客户请求的组,并发送" p ||克"到C.
C是客户端,S是服务器。
那么,该怎么办?首先,检查与您的私钥对应的公钥的长度。然后从管理SFTP服务器的任何人那里请求有关支持的密码算法,密钥交换算法和 DH组的信息。服务器可能仅支持最小密钥高于您使用的密钥长度的组。或者反过来说:客户端的公钥长于服务器支持的最大值。
如果服务器端的人员是安装某个软件包的类型而没有真正了解他们正在做什么或正在配置什么,那么您可能很难获得该信息。在这种情况下,您可能会通过网络数据包捕获(使用Wireshark等工具)从服务器和客户端找到支持的密码和密钥交换算法,但要非常小心。您希望得到您的上级许可,这样就不会被误解为试图破坏安全措施或窃听。在某些国家,法律及其对此的解释略显愚蠢,温和地说。
根据结果,服务器可能需要更新其OpenSSH版本,或者为其他DH组配置它;或者你需要选择不同长度的钥匙。由于这可能会影响安全级别,因此您必须征得SFTP服务器运营商的许可以及您正在为其执行项目的人员。
看起来Camel允许您使用URI中的ciphers
选项指定允许哪些加密密码。如果您没有指定它,则使用JSch的默认列表。遗憾的是,我没有看到指定使用哪种密钥交换算法的选项。看起来JSch确实支持许多交换算法(在密钥交换中找到它:http://www.jcraft.com/jsch/README)
尝试找出您的Camel版本使用的JSch版本。如果您可以更新Camel并且较新版本包含较新的JSch版本,请先尝试。如果您无法更新,或者您已经使用最新版本的Camel,请查看包含哪个版本的JSch,以及是否可以将其替换为更新的版本而不会破坏。最新的JSch版本可能支持旧版本没有的东西,并且由于安全漏洞导致某些算法和密钥长度的更新和弃用,有时旧版本的客户拒绝使用到目前为止的服务器(或其他方式)。
还要查看如何在JSch中启用日志记录(似乎它没有使用像Log4j或java.util.logging这样的默认框架),并尝试将系统属性javax.net.debug
设置为值{ {1}}(例如,通过命令行参数all
)。它可能会提供额外的信息。