Jenkins Publish Over SSH插件连接失败:Permission denied问题求助
看起来你碰到了一个挺诡异的问题——明明tomcat用户直接用ssh命令或者自己写的JSch代码都能正常连接远程服务器,但Jenkins的Publish Over SSH插件不管用哪种认证方式(密钥/密码)、甚至填虚假配置,都返回一模一样的java.net.SocketException: Permission denied (connect failed)错误。结合你的环境(Jenkins部署在Tomcat下,运行用户为tomcat),我整理了几个核心的排查方向和解决办法:
核心排查思路
这种“无论配置对错都返回同一错误”的现象,大概率不是SSH认证本身的问题,而是Jenkins/Tomcat进程被限制了网络连接的权限,或者存在全局网络配置干扰。
1. 先排查SELinux/AppArmor这类安全模块的限制
很多Linux发行版默认启用SELinux或AppArmor,它们会严格限制进程的网络行为,很可能阻止了Tomcat发起出站SSH连接:
- 先临时关闭SELinux测试:
之后重新测试插件的连接,如果成功了,那就是SELinux在搞鬼。接下来要添加永久规则允许Tomcat发起网络连接:sudo setenforce 0sudo setsebool -P tomcat_can_network_connect 1 - 如果是用AppArmor的环境,检查Tomcat的配置文件(一般在
/etc/apparmor.d/usr.sbin.tomcat*),确保里面有允许网络连接的规则:network inet stream, network inet6 stream,
2. 验证Tomcat进程的网络出站权限
有些环境会用防火墙规则或iptables限制特定用户/进程的出站流量,你可以模拟tomcat用户测试网络连通性:
- 尝试用telnet连接远程服务器的SSH端口(22):
如果telnet失败,说明是网络层面的限制,需要调整防火墙规则,允许tomcat用户访问远程主机的22端口。sudo runuser -u tomcat -- telnet remotehost 22
3. 检查Jenkins的全局代理配置
Jenkins如果配置了全局HTTP代理,会导致所有网络请求(包括SSH连接)都走代理,但SSH连接是不需要HTTP代理的:
- 进入Jenkins「系统管理」→「系统配置」,拉到「代理」部分,看看是不是启用了HTTP代理。如果是的话,一定要把你的远程主机添加到
No Proxy Hosts列表里,这样插件连接SSH时就不会走代理了。
4. 确认插件的JSch版本和测试代码一致
有时候Publish Over SSH插件内置的JSch版本和你自己测试用的JSch版本有差异,可能导致兼容性问题:
- 去Jenkins的插件管理页面,查看Publish Over SSH插件的详情,找到它依赖的JSch版本,和你测试代码里用的版本对比。如果版本差得比较多,试试把插件更到最新版,或者确认插件的依赖有没有正常加载。
5. 检查Tomcat的启动环境变量
Tomcat启动时的JVM参数如果设置了代理相关的系统属性,也会干扰SSH连接:
- 查看Tomcat的启动配置文件(比如
/etc/tomcat/tomcat.conf或者bin/catalina.sh),看看有没有类似下面的参数:
如果有这类代理参数,又没把SSH目标主机排除在外,插件就会尝试通过HTTP代理去连SSH,自然会失败。JAVA_OPTS="$JAVA_OPTS -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=8080"
优先尝试的解决办法
根据你的情况,最可能的原因是SELinux限制了Tomcat的网络连接权限,或者Jenkins配置了全局代理但没排除目标主机,建议优先测试这两个方向:
- 临时关闭SELinux,测试插件连接是否成功,成功的话就添加永久SELinux规则;
- 检查Jenkins的全局代理配置,确保远程主机在无代理列表中;
- 用
runuser模拟tomcat用户测试telnet远程22端口,确认网络连通性。
内容的提问来源于stack exchange,提问作者pbmmp




