fix(connections): connect MongoDB over SSH and Cloudflare tunnels (#1621)#1622
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1621
Problem
A MongoDB connection over an SSH (or Cloudflare) tunnel fails to connect. The SSH section's own "Test connection" passes, but the General-section test and a real connect fail with:
Root cause
tunneledConnection()rewrites a connection'shost/portto the local tunnel endpoint (127.0.0.1:<localPort>), but the MongoDB driver prefersadditionalFields["mongoHosts"]overhost/port, and that field still holds the originallocalhost:27017. Every MongoDB connection always hasmongoHostspopulated, even single-host ones, so the driver dials the original address and bypasses the tunnel.The SSH-section "Test connection" only checks the libssh2 handshake, which is why it passes while the actual driver connect fails.
Why not just clear
mongoHostsClearing the seed list alone fixes the single-host case but leaves replica sets broken: with a single seed and no
directConnection, the driver defaults to topology discovery, runshello, learns the members' advertised hostnames, and connects to those directly, escaping the tunnel. A tunnel forwards one local port, so the correct behavior is a direct connection to that one node. This is also the documented way mature clients (Studio 3T, NoSQLBooster, the PyMongo docs) reach MongoDB through a tunnel.Fix
In
tunneledConnection(), for a non-SRV MongoDB connection:mongoHostsso the driver uses the rewritten127.0.0.1:<localPort>directConnection=trueso topology discovery does not leave the tunneldirectConnectionis invalid with an SRV URI, and an IP cannot satisfy SRV/TLS; tunnel + SRV is not supported regardless)Applies to both SSH and Cloudflare tunnels via the shared helper.
directConnection=truemeans the client talks only to the tunneled node: no replica set failover, and writes require that node to be the primary. That is inherent to single-port tunneling and is strictly better than failing to connect. The multi-host SSH warning in the connection form was updated to match.Changes
DatabaseManager+Tunnel.swift: collapse the MongoDB seed list to the tunnel endpoint and force a direct connectionDatabaseConnection.swift:usesMongoSrvhelper mirroring the driver's SRV detectionGeneralPaneView.swift: corrected the multi-host tunnel warningDatabaseManagerTunnelTests.swift: tests for the rewrite, the SRV skip, and the non-MongoDB no-opNo PluginKit ABI change; host app only.
Tests