Search code examples
jdbcazure-sql-databasessh-tunnel

Failing to connect to Azure DB via SSH-Tunnel using a JDBC connection


I am unable to connect to an Azure DB via SSH-Tunnel using a JDBC connection. For security reasons, I cannot directly access the Azure DB, but I have a jump server / tunnel VM that I can use to indirectly connect to the DB.

  • command line access (via JDBC) to the Azure DB works from the tunnel VM
  • establishing an SSH tunnel (ssh -f vm_user@tunnel_vm_host -L 127.0.0.1:1433:mydb-server.database.windows.net:1433 -N) and then connecting to the Azure DB via 127.0.0.1:1433 and dbuser@mydb-server.database.windows.net works, if I use a client using the MS OLE DB SQL driver
  • establishing a connection using the MS SQL JDBC driver fails: com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host xxx.yyy.zzz.worker.database.windows.net, port 11111 has failed. Error: "Connection refused: connect. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".
  • from what I can see with Wireshark, if the JDBC driver is used, the communication to the Azure DB is started using the tunnel (127.0.0.1:randomport <--> 127.0.0.1:1433), but then switches to outside the tunnel, using my-external-IP:randomport <--> xxx.yyy.zzz.worker.database.windows.net:11111, which fails due to the firewall.

What am I missing to get this running?

Drivers used:

  • JDBC driver version is mssql 8.2.2.0 jre11
  • MS OLE DB Driver for SQL Server 18.3.0.0

Test program:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class AzureDbTest {
  public static void main(final String[] args) throws SQLException {
    final String user = "db-user@mydb-server.database.windows.net";
    final String password = "password";
    final int portNumber = 1433;
    final String databaseName = "mydb";
    final String serverName = "127.0.0.1";
    final String url = String.format("jdbc:sqlserver://%s:%s;database=%s;user=%s;password=%s;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;",
        serverName, portNumber, databaseName, user, password);
    Connection connection = null;
    try {
      connection = DriverManager.getConnection(url);
      final String schema = connection.getSchema();
      System.out.println("Successful connection - Schema: " + schema);
    } catch (final Exception e) {
      e.printStackTrace();
    } finally {
      if (connection != null) {
        connection.close();
      }
    }
  }
}

Solution

  • The connection policy of the DB server needs to be proxy in order to work with the ssh tunnel.

    Details on the differences of the available connection policies can be found in the Azure SQL Database and Azure Synapse Analytics connectivity architecture article.