配置透明SSH网关:基于用户名转发公钥认证至上游服务器可行性咨询
Great question! Let's break down your options for building this transparent SSH gateway that routes connections by username and delegates all public key authentication to your upstream servers—no local key storage needed on the gateway.
Option 1: HAProxy (Recommended for True Transparency)
HAProxy is perfect here because it can act as a TCP reverse proxy that inspects SSH handshake payloads to route based on the username, without handling any authentication at all. All auth logic stays entirely on your upstream servers, which aligns exactly with your requirements.
Here's a simplified HAProxy config example to get you started:
# Frontend listening for all SSH connections frontend ssh_gateway bind *:22 mode tcp # Wait until we have enough payload to extract the username tcp-request content accept if { req_len gt 0 } # Match usernames from the SSH handshake payload acl user_john req_payload(0,15) -m str "john" acl user_jane req_payload(0,15) -m str "jane" # Route to corresponding upstream servers use_backend johns_server if user_john use_backend janes_server if user_jane # Backend definitions for each user's upstream server backend johns_server mode tcp server john_upstream 10.0.0.10:22 check backend janes_server mode tcp server jane_upstream 10.0.0.11:22 check
How this works:
When an SSH client connects, it sends the username early in the handshake process. HAProxy captures this payload string, matches it against your ACL rules, and forwards the entire TCP connection to the correct upstream server. The gateway never touches authentication—upstream servers handle all pubkey checks directly.
Option 2: OpenSSH + ForceCommand + Dynamic Key Fetching
If you prefer to stick with OpenSSH on the gateway instead of a reverse proxy, you can combine AuthorizedKeysCommand (to dynamically fetch pubkeys from upstream) with ForceCommand (to route the user to their upstream server after auth).
Step 1: Configure sshd_config
Add these lines to your gateway's /etc/ssh/sshd_config:
# Dynamically fetch the user's pubkey from their upstream server AuthorizedKeysCommand /usr/local/bin/fetch_upstream_keys.sh %u AuthorizedKeysCommandUser nobody # After auth, automatically forward the user to their upstream server ForceCommand /usr/local/bin/forward_to_upstream.sh %u
Step 2: Write the key-fetching script (fetch_upstream_keys.sh)
This script pulls the user's authorized keys directly from their upstream server (the gateway needs a service SSH key to access all upstream servers without password):
#!/bin/bash USER=$1 # Map username to upstream server (customize this logic for your environment) case $USER in john) UPSTREAM="10.0.0.10" ;; jane) UPSTREAM="10.0.0.11" ;; *) exit 1 ;; esac # Fetch the user's authorized keys from upstream ssh -i /path/to/gateway_service_key $UPSTREAM cat "/home/$USER/.ssh/authorized_keys"
Step 3: Write the forwarding script (forward_to_upstream.sh)
This script connects the user to their upstream server after successful auth:
#!/bin/bash USER=$1 # Reuse the same username-to-server mapping case $USER in john) UPSTREAM="10.0.0.10" ;; jane) UPSTREAM="10.0.0.11" ;; *) exit 1 ;; esac # Forward the SSH session to the upstream server ssh -o StrictHostKeyChecking=no -i /path/to/gateway_service_key "$USER@$UPSTREAM"
Caveat:
This approach requires the gateway to perform a "proxy auth" step (fetching keys from upstream to validate the user) before forwarding. It works, but it's not as "transparent" as HAProxy since the gateway is involved in the auth flow—even if it doesn't store keys locally.
Option 3: Modify OpenSSH Source Code (Not Recommended)
Technically, you could patch OpenSSH to change where it looks for authorized keys (e.g., fetch from a remote API instead of local files). However, this is a terrible idea for most use cases:
- You'll have to reapply patches every time OpenSSH is updated, which is a maintenance nightmare.
- It introduces security risks if your patch isn't thoroughly tested.
- There's no need for this when HAProxy or the ForceCommand approach works perfectly.
Final Recommendation
Go with HAProxy if you want a true transparent gateway that doesn't touch auth at all. It's simpler to maintain, more secure, and aligns perfectly with your requirement of keeping all keys and auth logic on upstream servers.
内容的提问来源于stack exchange,提问作者hermetik

