sidorares / node-mysql2

:zap: fast mysqljs/mysql compatible mysql driver for node.js
https://sidorares.github.io/node-mysql2/
MIT License
4.03k stars 610 forks source link

SSH2 + TLS seems to hang mysql2 #1386

Open odubuc opened 2 years ago

odubuc commented 2 years ago

Using the answer from this code on StackOverflow, I've successfully connected and executed queries using SSH2 as a jump host and a plain ( non ssl ) mysql2 connection. When looking up on the server, I can see my user connection as plain "TCP/IP" which is good for the test.

However, if I specify the SSL information in the "createConnection" function, when the code hits "execute", it hangs without any errors. On the MySQL server, I can see the user seems to be connected with a state of "sleep". connection type is "SSL/TLS" so the connection seems to be established but I cannot figure out why the code hangs.

( Of course if I connect directly without SSH2, TLS establishes without any issues and the query execute immediately ).

This is the code used. To make this work or fail, simply comment the ssl object and it will pass. otherwise it will hang at sql.execute

( note : In my tests, the jump host and mysql are on two seperate machines. )

import { readFileSync } from "fs";
import { createConnection } from "mysql2";
import { Client } from "ssh2";

const ssh = new Client();
ssh.on("ready", function () {
    ssh.forwardOut("jump_host_ip", 3306, "database_ip", 3306, (err, stream) => {
        if (err) throw err;
        const sql = createConnection({
            user: "user",
            ssl: {
                ca: readFileSync("path_to_ca").toString(),
                cert: readFileSync("path_to_cert").toString(),
                key: readFileSync("path_to_key").toString(),
            },
            password: "password",
            database: "database",
            stream: stream,
        });
        sql.execute("select @@hostname;", (iError, iResult) => {
            console.log(iError, iResult);
        });
    });
}).connect({
    host: "jump_host_ip",
    username: "username",
    port: 22,
    passphrase:
        "passphrase",
    keepaliveInterval: 30000, 
    privateKey: readFileSync("path_to_private_key"),
});

Enabling debug: true only gives me this output.

Add command: ClientHandshake
Add command: Prepare
Add command: Execute
 raw: 0a382e302e3233002e9813002912187a642a174400ffffc00200ffcf15000000000000000000004e371720340f23512e4e3b43006d7973716c5f6e61746976655f70617373776f726400
Trace:
    at Connection.handlePacket (C:\[...]\node_modules\mysql2\lib\connection.js:427:17)
    at PacketParser.onPacket (C:\[...]\node_modules\mysql2\lib\connection.js:85:12)
    at PacketParser.executeStart (C:\[...]\node_modules\mysql2\lib\packet_parser.js:75:16)
    at Channel.<anonymous> (C:\[...]\node_modules\mysql2\lib\connection.js:92:25)
    at Channel.emit (events.js:375:28)
    at Channel.emit (domain.js:470:12)
    at Channel.Readable.read (internal/streams/readable.js:500:10)
    at flow (internal/streams/readable.js:982:34)
    at resume_ (internal/streams/readable.js:963:3)
    at processTicksAndRejections (internal/process/task_queues.js:82:21)
0 undefined ==> ClientHandshake#unknown name(0,,78)
Server hello packet: capability flags:3489660927=(long password, found rows, long flag, connect with db, no schema, compress, odbc, local files, ignore space, protocol 41, interactive, ssl, ignore sigpipe, transactions, reserved, secure connection, multi statements, multi results, ps multi results, plugin auth, connect attrs, plugin auth lenenc client data, can handle expired passwords, session track, deprecate eof, ssl verify server cert, remember options)
0 1284142 <== ClientHandshake#unknown name(1,,36)
0 1284142 <== 20000001cffbaa0000000000e00000000000000000000000000000000000000000000000
Upgrading connection to TLS
Sending handshake packet: flags:11205583=(long password, found rows, long flag, connect with db, odbc, local files, ignore space, protocol 41, ssl, ignore sigpipe, transactions, reserved, secure connection, multi results, plugin auth, plugin auth lenenc client data, session track)
0 1284142 <== ClientHandshake#unknown name(2,,95)
0 1284142 <== 5b000002cffbaa0000000000e00000000000000000000000000000000000000000000000757365725f6462690014e9fd8789b06667603ad53e1daa02726405ca5292666f63757332006d7973716c5f6e61746976655f70617373776f726400
odubuc commented 2 years ago

Adding more information to this issue: I'm getting the exact same problem using SSH2 directly to database server, and connecting mysql2 on localhost. mysql2 initiate the TLS handshake and doesn't seem to complete. same debug output.