使用Java通过带PEM文件的SSH隧道连接Vertica DB遇连接错误
问题诊断与解决方案
核心问题:JDBC未使用SSH转发的本地端口
你的代码已通过PortForwarder.openConnection()获取到本地转发端口localBindingPort,但最终生成的JDBC URL仍直接指向远程数据库的公网IP和原端口(10.13.3.213:5433),完全未利用SSH隧道的本地转发能力。SSH隧道的作用是将本地端口的请求转发至SSH服务器,再由其转发到目标数据库,因此JDBC必须连接**localhost+本地转发端口**,而非直接连接数据库公网地址。
具体修复步骤
1. 修正JDBC URL生成逻辑
将JDBC URL中的主机改为localhost,端口替换为获取到的localBindingPort:
int localBindingPort = PortForwarder.openConnection(); // 替换主机为localhost,使用转发后的本地端口 JDBCurl = String.format("jdbc:vertica://localhost:%d/%s", localBindingPort, Schema); return DriverManager.getConnection(JDBCurl, username, password);
2. 校验SSH端口转发参数正确性
检查portsString的参数格式与取值:
Port:本地要绑定的未被占用端口(如54330)Host:数据库在SSH服务器内网中的可访问地址(若SSH服务器能直接访问数据库公网IP10.13.3.213,则该值可保留,否则需替换为内网IP)SSHPort:数据库的实际服务端口(Vertica默认是5433)
3. 修正PEM密钥使用方式
使用PEM私钥时需注意:
- 若PEM文件无密码,不要调用
session.setPassword(password),否则会干扰密钥认证流程 - 确保传入的
pemFile是私钥文件路径(而非公钥),JSch需要私钥完成SSH认证 - 可显式指定密钥绝对路径避免路径问题:
jsch.addIdentity(new File(pemFile).getAbsolutePath()); // 仅当PEM有密码时才设置,无密码则注释此行 // session.setPassword(pemPassphrase);
4. 增强错误排查日志
在PortForwarder.openConnection()的异常捕获块中打印详细堆栈信息,确认SSH连接或端口转发是否成功:
catch (Exception e) { System.err.println("SSH连接/端口转发失败详情:"); e.printStackTrace(); System.exit(1); }
验证流程
- 先通过
telnet localhost localBindingPort测试本地转发端口是否能正常连通 - 再运行JDBC连接代码,确认是否通过隧道成功访问数据库
内容的提问来源于stack exchange,提问作者Will Preston
相关产品推荐
相关产品推荐

