Repository navigation
Add per-host SOCKS5 proxy routes - #336
Merged
Merged
Conversation
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
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.
Problem and outcome
Closes #334.
Saved SSH hosts can now select a reusable, user-owned SOCKS5 proxy. Terminal connections and their session SFTP channels use that route, including password authentication at the proxy, reconnects, and persistent sessions. Direct and Jump Host connections retain their existing behavior.
The implementation uses a small standard-library SOCKS5 CONNECT client with a bounded handshake, then passes the resulting socket to the existing Paramiko transport. Proxy metadata has its own per-user store; passwords use the existing encrypted credential service. No dependencies were added.
Scope and security boundaries
SOCKS_REMOTE_DNS_ALLOWLIST. With internal blocking enabled, names outside it use a validated local IP. Delegated DNS cannot constrain the proxy's final target IP; this trust boundary is documented.New optional settings:
SOCKS_REMOTE_DNS_ALLOWLISTandSOCKS_PROXY_MAX_RECORDS. Existing defaults remain unchanged.Standalone Quick SFTP, Automation, SOCKS-to-Jump chaining, Tailscale SSH through SOCKS, and route-preserving ssh_config export remain unsupported and fail explicitly. They are separate follow-ups.
Compatibility decisions
The current source uses
CONNECTION_CONFIG_MAX_BYTESfor the combined store quota andCONNECTION_STORE_MAX_BYTESfor each file; both contracts are preserved. Existing Jump DNS allowlist parsing is also preserved while the new SOCKS setting receives strict startup validation.The current export format is JSON, rather than ssh_config. Exported SOCKS hosts carry an explicit omitted-route warning, and reimport is blocked so route loss cannot create a direct connection.
ProxyCommandremains rejected.Validation
Current revision:
dfb741ec1b92beb0ad2f64fddddb71ae97475d30, including the updatedmainbranch. All 31 executed GitHub checks passed; the three release-only jobs were skipped. The complete test workflow, container security workflow, and CodeQL workflow are green.The CI follow-up fixes a race in the SOCKS test peer: an immediately rejected client could finish before the server accepted its queued connection, and cleanup closed the listener too early. Cleanup now waits for the peer before closing the listener. A deterministic regression reproduced the original failure and passes with the fix; existing timeouts and error assertions remain intact. All 91 SOCKS protocol tests passed locally on Python 3.11 and 3.14 on Windows and Python 3.12 with two workers on Linux. The previously failing Python 3.14 CI shard passed with 1,774 tests and one skip. This follow-up changes test code only.
Initial feature revision:
cf2e0a1eba59f50695cb448b494c347a5241ed9c. Runtime, backend tests and dependencies are byte-for-byte unchanged from97f855cb3d926350f89a8f11aab7b1b62ad72699, on which the full Python, OpenSSH and production-image gates passed. The final commit adds one readiness wait to a browser-test helper; JavaScript and the complete browser gate are rerun on the final commit.97f855cand hardened smoke passed: single-worker gthread, readiness, runtime restrictions, online/offline backups, restore/SQLite, restart, and clean shutdown.cf2e0a1: 908 passed (906 shared cases across eight isolated shards plus two exclusive terminal-load cases), with no failures, skips or retries.Regression coverage includes hostile/fragmented SOCKS replies, total deadlines and cancellation, authentication downgrade rejection, network-policy and DNS matrices, user isolation, credentials and unchanged legacy hashes, corrupt/oversized storage, route changes and deletion, no-direct-fallback launch paths, and real SSH/SFTP through the proxy.
Direct credential-payload compatibility, SOCKS capture fixtures, and missing-proxy alert dismissal have regression coverage. The editor preserves the exact saved SSH key before its inventory loads, verified with a failing-before/passing-after regression. Browser fixtures wait for actual inventory/readiness and use user-visible command filters. Capture, credential, focus and viewport assertions remain intact; all 16 isolated repeated scenarios passed without retries.
Python checks use isolated Windows virtual environments and temporary directories; the complete browser suite runs in isolated Linux containers. Graphify could not run because this checkout has neither its graph nor its interpreter marker.
Delivery
This PR implements the feature; it does not publish a release or change a running installation. No merge, release, or deployment was performed.