SSH(Secure Shell Protocol)工作在 TCP/IP 應用層與傳輸層,提供加密傳輸通道。其核心分層:

SSH_MSG_SERVICE_REQUEST 請求 ssh-userauth 服務。SSH_MSG_USERAUTH_REQUEST),攜帶用戶名、服務名、認證方法名。
模塊化分層:
TransportControl 選擇算法)。AuthRequestByPassword、AuthRequestByPublicKey 等)。

發送 SSH_MSG_USERAUTH_REQUEST,方法名為 none。服務端拒絕並返回支持的方法列表(如 publickey,gssapi-with-mic,password)。
public class AuthRequestByNone {
public byte[] getRequestMessage() {
ProcessTypes type = new ProcessTypes();
type.asByte(SSH_MSG_USERAUTH_REQUEST);
type.asString(userName);
type.asString(serviceName);
type.asString(SSH_NONE_AUTHENTICATION_METHOD);
return type.getBytes();
}
}
解析失敗響應(代碼 51)提取 name-list 字段,獲取可用認證方法。
請求格式:
byte SSH_MSG_USERAUTH_REQUEST string userName string serviceName string "password" boolean FALSE string plaintext password (UTF-8)
實現關鍵:
public boolean passwordAuthentication(String user, String pass) throws IOException {
initialize(user); // 協商算法、獲取支持列表
if (!verifyAuthenticatonMethods(SSH_PASSWORD_AUTHENTICATION_METHOD)) return false;
AuthRequestByPassword req = new AuthRequestByPassword(serviceName, user, pass);
transportManager.sendMessage(req.getRequestMessage());
byte[] msg = getMessage();
return !isRequestFailed(msg); // 52 成功,51 失敗
}
安全建議:生產環境禁用密碼認證,改用公鑰;必須啟用 Fail2ban 限制嘗試次數。
流程:客戶端用私鑰簽名會話 ID + 請求數據,服務端用授權公鑰驗證簽名。Java 實現需:
sessionId || SSH_MSG_USERAUTH_REQUEST || userName || serviceName || "publickey" || TRUE || keyAlgorithm || publicKeyBlob。代碼結構類似密碼認證,核心差異在 getRequestMessage() 中組裝簽名 Blob。
服務端發送提示(SSH_MSG_USERAUTH_INFO_REQUEST),客戶端交互式輸入響應。常見於:
sshd 運行、防火牆放行 22 端口。ssh 協議,分析握手、認證交互細節。bad service request(服務名錯誤)、Permission denied(認證方法不支持或憑證錯誤)。本文以密碼認證為例,完整展示了 SSH 用戶認證層的 Java 實現邏輯。關鍵點:
TransportManager 統一處理加解密、壓縮、序列化。AuthManager 解耦具體認證方式,便於擴展新方法(如硬件 Token、生物識別)。後續可深入:公鑰認證完整代碼、GSSAPI/Kerberos 整合、SSH Agent 轉發、連接層通道管理(Shell、Exec、Subsystem、Port Forwarding)。