{"record":{"id":"6e11fc9f3e14daec","repo":"pentaho/pentaho-kettle","slug":"ssh-over-http-proxy-connection-failed-proxy-target-note","errorCode":null,"errorMessage":"SSH over HTTP proxy connection failed: \nProxy: :\nTarget: :\nNote: Ensure HTTP proxy supports CONNECT method and target is reachable.","messagePattern":"SSH over HTTP proxy connection failed: \nProxy: :\nTarget: :\nNote: Ensure HTTP proxy supports CONNECT method and target is reachable\\.","errorType":"exception","errorClass":"SshConnectionException","httpStatus":null,"severity":"critical","filePath":"engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java","lineNumber":171,"sourceCode":"\n    configureHttpProxyConnector();\n\n    log( DEBUG, \"Connecting to HTTP proxy: \" + config.getProxyHost() + \":\" + config.getProxyPort() );\n    log( DEBUG, \"Target SSH server (via proxy): \" + config.getHost() + \":\" + config.getPort() );\n\n    return client.connect( config.getUsername(), config.getProxyHost(), config.getProxyPort() );\n  }\n\n  private void configureHttpProxyConnector() throws SshConnectionException {\n    try {\n      client.setClientProxyConnector( this::sendHttpConnectRequest );\n    } catch ( Exception e ) {\n      String errorMsg = \"SSH over HTTP proxy connection failed: \" + e.getMessage()\n          + \"\\nProxy: \" + config.getProxyHost() + \":\" + config.getProxyPort()\n          + \"\\nTarget: \" + config.getHost() + \":\" + config.getPort() + formatUserInfo()\n          + \"\\nNote: Ensure HTTP proxy supports CONNECT method and target is reachable.\";\n      log( ERROR, errorMsg );\n      throw new SshConnectionException( errorMsg, e );\n    }\n  }\n\n  private String formatUserInfo() {\n    return \" (user: \" + config.getUsername() + \")\";\n  }\n\n  private void sendHttpConnectRequest( ClientSession session ) throws IOException {\n    log( DEBUG, \"Sending HTTP CONNECT proxy metadata\" );\n\n    String connectRequest = buildHttpConnectRequest();\n    log( DEBUG, \"HTTP CONNECT request: \" + connectRequest.replace( \"\\r\\n\", \"\\\\r\\\\n\" ) );\n\n    IoSession ioSession = session.getIoSession();\n    ByteArrayBuffer buffer = new ByteArrayBuffer( connectRequest.getBytes() );\n    ioSession.writeBuffer( buffer );\n\n    log( DEBUG, \"HTTP CONNECT request sent via proxy connector\" );","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java#L153-L189","documentation":"MinaSshConnection.configureHttpProxyConnector() wraps any failure to establish the SSH session through the configured HTTP proxy into SshConnectionException with a detailed message including proxy host:port, target host:port, and user info. It fires when the HTTP proxy refuses, cannot CONNECT, or cannot reach the target.","triggerScenarios":"Calling connect() with proxyHost/proxyPort configured when the proxy is down or unreachable, the proxy rejects CONNECT to the target port, proxy auth is required but not supplied, or the target is blocked by proxy ACLs.","commonSituations":"Corporate HTTP proxies that only allow CONNECT to 443 while the SSH target listens on 22, stale proxy credentials after rotation, misconfigured proxy port, or proxies that silently drop rather than reject the CONNECT tunnel.","solutions":["Verify the proxy host/port and that the proxy is reachable from the client host","Confirm the proxy allows CONNECT to the SSH target port; many only permit 443 — use a proxy or gateway that permits port 22","Supply proxy credentials if the proxy requires authentication","Test the tunnel independently (e.g. curl -x proxy CONNECT) to isolate proxy vs target issues","If a proxy is not actually needed, clear proxyHost/proxyPort so the direct connection path is used"],"exampleFix":"// before\nconfig.setProxyHost(\"corp-proxy\"); config.setProxyPort(8080); // proxy forbids CONNECT :22\n// after\nconfig.setProxyHost(\"ssh-gateway\"); config.setProxyPort(3128); // CONNECT allowed to target:22\n// or remove proxy:\n// config.setProxyHost(null);","handlingStrategy":"try-catch","validationCode":"// probe the proxy CONNECT path before connecting\ntry (Socket px = new Socket(config.getProxyHost(), config.getProxyPort());\n     OutputStream os = px.getOutputStream(); InputStream is = px.getInputStream()) {\n  os.write((\"CONNECT \" + config.getHost() + \":\" + config.getPort() + \" HTTP/1.1\\r\\nHost: \"\n      + config.getHost() + \":\" + config.getPort() + \"\\r\\n\\r\\n\").getBytes(StandardCharsets.US_ASCII));\n  os.flush();\n  String resp = new String(is.readNBytes(1024), StandardCharsets.US_ASCII);\n  if (!resp.contains(\" 200 \")) throw new IllegalStateException(\"proxy CONNECT refused: \" + resp.split(\"\\r\\n\")[0]);\n}","typeGuard":"boolean proxyConnectOk(String proxyHost, int proxyPort, String targetHost, int targetPort) {\n  try (Socket px = new Socket(proxyHost, proxyPort)) {\n    px.getOutputStream().write((\"CONNECT \" + targetHost + \":\" + targetPort + \" HTTP/1.1\\r\\n\\r\\n\").getBytes());\n    byte[] b = px.getInputStream().readNBytes(64);\n    return new String(b).contains(\" 200 \");\n  } catch (IOException e) { return false; }\n}","tryCatchPattern":"try {\n  conn.connect();\n} catch (SshConnectionException e) {\n  if (e.getMessage().contains(\"HTTP proxy connection failed\")) {\n    log.error(\"Proxy {}:{} cannot tunnel to {}:{} — check CONNECT ACL/credentials\",\n      config.getProxyHost(), config.getProxyPort(), config.getHost(), config.getPort());\n  }\n  throw e;\n}","preventionTips":["Confirm the proxy permits CONNECT to the SSH port (many only allow 443) — use an SSH gateway if not","Validate proxy host/port/credentials before connect; recheck after credential rotation","Probe the CONNECT tunnel with curl -x or raw socket before relying on it","Clear proxy config when a direct route exists so the direct path is used"],"tags":["ssh","proxy","http","network","connect"],"backgroundTag":"connection-refused","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}