Bug Description
The gateway's SSH proxy can only use an Ed25519 host key, so it advertises ssh-ed25519 as its sole host key algorithm. Clients on FIPS-restricted systems (ex: RHEL with FIPS:STIG crypto policy) cannot connect to 12222 SSH proxy, because their SSH build has no Ed25519 support at all and the handshake fails at host key negotiation.
gateway/proxyproto/sshproxy/keys.go:20 discards any non-Ed25519 key:
func decodeOpenSSHPrivateKey(pemBytes []byte) (ed25519.PrivateKey, error) {
privateKey, err := ssh.ParseRawPrivateKey(pemBytes)
if err != nil { return nil, err }
ed25519Key, ok := privateKey.(*ed25519.PrivateKey)
if !ok {
return nil, fmt.Errorf("key is not Ed25519, found=%T", privateKey)
}
return *ed25519Key, nil
}hosts_key is documented as "Base64-encoded PEM private key used as the SSH host key", which reads as algorithm-agnostic, but supplying an ECDSA or RSA key fails the config apply, and on a cold boot gateway/main.go hits log.Fatalf and the pod crashloops. When hosts_key is empty the gateway auto-generates Ed25519 (gateway/api/serverconfig/misc.go:501), so there is no way to obtain a FIPS-compatible host key. Both the password and certificate proxies share this key, so cert auth doesn't avoid it.
Running parseHostsKey against real ssh-keygen output on the pinned golang.org/x/crypto v0.56.0:
ed25519 ACCEPTED -> advertises "ssh-ed25519"
ecdsa-sha2-nistp256 REJECTED: key is not Ed25519, found=*ecdsa.PrivateKey
ecdsa-sha2-nistp384 REJECTED: key is not Ed25519, found=*ecdsa.PrivateKey
rsa-3072 REJECTED: key is not Ed25519, found=*rsa.PrivateKeyProposed fix
ssh.NewSignerFromKey in parseHostsKey already handles ECDSA and RSA; only the assertion blocks them:
func decodeOpenSSHPrivateKey(pemBytes []byte) (any, error) {
return ssh.ParseRawPrivateKey(pemBytes)
}parseHostsKey needs no change. keys_test.go:45 asserts the concrete Ed25519 type and would need a type assert. Auto-generation can stay Ed25519 — this only affects operator-supplied keys.
I verified the patched function on the pinned x/crypto, including an Ed25519 regression check:
ed25519 (regression) OK -> advertises "ssh-ed25519"
ecdsa-sha2-nistp256 OK -> advertises "ecdsa-sha2-nistp256"
ecdsa-sha2-nistp384 OK -> advertises "ecdsa-sha2-nistp384"
rsa-3072 OK -> advertises "ssh-rsa"And end-to-end with a real OpenSSH client restricted to FIPS algorithms, against a server built the same way the gateway builds its own:
# ECDSA host key, client restricted to ecdsa-sha2-nistp256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
# RSA-3072 host key, client restricted to rsa-sha2-512,rsa-sha2-256
debug1: kex: host key algorithm: rsa-sha2-512The RSA signer's base type string is ssh-rsa, but x/crypto advertises the RFC 8332 rsa-sha2-256/512 variants and the handshake negotiates SHA-2, so no SHA-1 signature is involved.
Steps to Reproduce
- (After deploying hoop gateway) run
ssh hoop@<placeholder> -p 12222
Expected Behavior
Should be able to SSH via SSH proxy
Actual Behavior
When trying to connect via SSH Proxy (ssh hoop@<placeholder> -p 12222) connect fails (doesn't even prompt for password).
HostKeyAlgorithms=ecdsa-sha2-nistp256,rsa-sha2-256,rsa-sha2-512
-> Unable to negotiate: no matching host key type found. Their offer: ssh-ed25519Adding ed25519 as a fallback connects, but only by abandoning the FIPS requirement. (FIPS 186-5 does approve EdDSA, but deployed FIPS SSH builds — RHEL's included — generally still exclude it, so this isn't reachable as a policy change.)
Version
v1.195.1
Browser(s)
Other
Operating System
RHEL9
Screenshots
No response
Additional Context
No response
Relevant Log Output
undefinedCode of Conduct
- I agree to follow this project's Code of Conduct
🔗 Synced to Linear: SUP-282