Repository navigation
Conversation
This comment has been minimized.
This comment has been minimized.
|
Documentation preview: https://091bc40d.shellhub-docs.pages.dev |
otavio
force-pushed
the
fix/ssh-proxy-trusted-ips
branch
from
October 23, 2026 21:15
873b8d2 to
b551e8d
Compare
Member
Author
|
/review |
The listener read the loopback-only policy from a package variable. Taking it as an argument lets the server build the policy from its configuration.
A PROXY header from an untrusted peer failed the SSH handshake inside gliderssh, and nothing reached the log. On cloud.shellhub.io every SSH login closed before the banner after the upgrade to v0.27.0, with no server-side trace. The listener now logs a warning naming the peer, which is the address to trust. The read error surfaces from gossh.NewServerConn, so the warning hangs off ConnectionFailedCallback rather than the listener. The test serves a server built by NewServer, so it fails when that wiring is dropped. It dials the host's own non-loopback address, because loopback is always trusted and cannot show the rejection; it skips on a host without one. Refs: shellhub-io/team#362
This comment has been minimized.
This comment has been minimized.
otavio
force-pushed
the
fix/ssh-proxy-trusted-ips
branch
from
October 23, 2026 21:18
b551e8d to
9a48db5
Compare
Member
Author
|
/review |
|
Documentation preview: https://7607693d.shellhub-docs.pages.dev |
This comment has been minimized.
This comment has been minimized.
otavio
force-pushed
the
fix/ssh-proxy-trusted-ips
branch
from
October 23, 2026 21:26
9a48db5 to
c94a9d6
Compare
Member
Author
|
/review |
This comment has been minimized.
This comment has been minimized.
|
Documentation preview: https://37f575c8.shellhub-docs.pages.dev |
Since GHSA-c5cf-fr53-8wq4 the SSH listener reads a PROXY header only from loopback, and the ranges were hard-coded. A Layer 4 load balancer or an ingress that passes TCP through sends the header from another address, so v0.27.0 closed every such SSH connection. SHELLHUB_PROXY and SHELLHUB_PROXY_TRUSTED_IPS did not help, because only the gateway reads them. SHELLHUB_SSH_PROXY_TRUSTED_IPS lists the extra ranges, space-separated like the gateway's variable. It is a separate name because the two defaults differ: the gateway trusts every peer, SSH trusts loopback only. Empty keeps the advisory's protection. A header from a peer outside the list is still rejected, and a malformed range stops the server at startup instead of panicking in MustPolicyFromRanges. Trust is by source address, so any peer in a listed range can declare a client address. A deployment that lists a pod network has to restrict who reaches port 2222, for example with a NetworkPolicy that admits only the ingress pods. The documentation warns Compose users off the Docker bridge range, which the userland proxy makes every external client appear to come from. Fixes: shellhub-io/team#362
otavio
force-pushed
the
fix/ssh-proxy-trusted-ips
branch
from
October 23, 2026 21:33
c94a9d6 to
249b577
Compare
Member
Author
|
/review |
This comment has been minimized.
This comment has been minimized.
|
Documentation preview: https://7441cede.shellhub-docs.pages.dev |
The load balancer, troubleshooting, firewall rule, access policy and session pages said the client address of SSH connections comes from SHELLHUB_PROXY_TRUSTED_IPS, which only the gateway reads. They now name SHELLHUB_SSH_PROXY_TRUSTED_IPS for SSH clients. The gateway variable still decides the address of web terminal sessions: the gateway sets X-Real-IP, and the web terminal hands that address to the SSH session it opens on loopback. Troubleshooting also covers the symptom seen on cloud.shellhub.io: SSH closing before the banner, with the server's rejection warning. Refs: shellhub-io/team#362
otavio
force-pushed
the
fix/ssh-proxy-trusted-ips
branch
from
October 23, 2026 21:40
249b577 to
1dbb378
Compare
Member
Author
|
/review |
|
Claude finished @otavio's task in 3m 4s —— View job Code Review CompleteReviewed 13 files on all three axes: Standards (repo rules, language conventions, tests, code smells), Spec (does it implement the issue?) and Correctness (security and runtime defects). No new issues found. The code looks good as-is. |
|
Documentation preview: https://76be20d3.shellhub-docs.pages.dev |
This branch has not been deployed
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.
Summary
The SSH listener trusted a PROXY protocol header only from loopback, with the ranges hard-coded. Behind a Layer 4 load balancer or an ingress that passes TCP through, v0.27.0 closed every SSH connection and logged nothing.
SHELLHUB_SSH_PROXY_TRUSTED_IPSis empty by default, so a deployment that sets nothing keeps the GHSA-c5cf-fr53-8wq4 protection. It has its own name because the gateway'sSHELLHUB_PROXY_TRUSTED_IPSdefaults to trusting every peer.docker-compose.ymland.env. The docs pages that said the gateway variables apply to SSH are corrected.For cloud.shellhub.io, after release: Envoy passes the header through on port 22 again, the server gets
SHELLHUB_SSH_PROXY_TRUSTED_IPS=10.0.128.0/17, and a NetworkPolicy limits port 2222 to the Envoy pods. Trust is by source address, so that NetworkPolicy is part of the fix.Evidence
server/ssh/server/proxy_test.goruns a real SSH handshake through the production listener. The client sendsPROXY TCP4 198.51.100.7 ...from the host's own non-loopback address, since loopback is always trusted and can't show the bug.go test ./ssh/... ./app/...and golangci-lint v2.14.0 pass (0 issues). The docs lint (remark, cspell, vale) passes.Merge Danger
Door: two-way
A new optional variable with a safe default. Reverting restores the loopback-only listener.
Blast Radius: SSH
Every SSH connection goes through this listener. With the variable unset, the only change is the new warning. If the variable is set too wide, any peer in the range can forge a client address, which affects firewall rules, lockout, access policies and the audit trail. The docs and the commit say so.
Closes shellhub-io/team#362