如何使用OpenSSH私钥通过Go语言连接SFTP服务器
Got it, let's walk through how to replicate your terminal SFTP connection in Go using crypto/ssh and github.com/pkg/sftp. Here's a complete, working example that handles private key authentication and explicitly enables the ssh-dss host key algorithm like your terminal command does:
package main import ( "fmt" "io/ioutil" "log" "time" "github.com/pkg/sftp" "golang.org/x/crypto/ssh" ) func main() { // Configuration parameters (replace these with your actual values) username := "sftp_username" hostname := "hostname" privateKeyPath := "<path_to_identity_file_or_private_key>" port := "22" // Default SFTP port, adjust if your server uses a different one // Step 1: Load and parse the private key privateKeyBytes, err := ioutil.ReadFile(privateKeyPath) if err != nil { log.Fatalf("Failed to read private key file: %v", err) } // Parse the private key into an ssh.Signer (works for OpenSSH format keys) signer, err := ssh.ParsePrivateKey(privateKeyBytes) if err != nil { log.Fatalf("Failed to parse private key: %v", err) } // Step 2: Configure SSH client settings to match your terminal command sshConfig := &ssh.ClientConfig{ User: username, Auth: []ssh.AuthMethod{ // Use the parsed private key for authentication ssh.PublicKeys(signer), }, // Explicitly allow ssh-dss host key algorithm (matches -oHostKeyAlgorithms=+ssh-dss) Config: ssh.Config{ HostKeyAlgorithms: []string{ssh.KeyAlgoDSS}, }, // For testing, you can use ssh.InsecureIgnoreHostKey() (not recommended for production) // In production, replace this with logic to verify the server's actual DSS host key HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: 30 * time.Second, } // Step 3: Dial the SSH server sshAddr := fmt.Sprintf("%s:%s", hostname, port) sshClient, err := ssh.Dial("tcp", sshAddr, sshConfig) if err != nil { log.Fatalf("Failed to connect to SSH server: %v", err) } defer sshClient.Close() // Ensure we clean up the SSH connection // Step 4: Create the SFTP client from the SSH connection sftpClient, err := sftp.NewClient(sshClient) if err != nil { log.Fatalf("Failed to initialize SFTP client: %v", err) } defer sftpClient.Close() // Clean up the SFTP client when done // Example: List files in the remote root directory to verify connection files, err := sftpClient.ReadDir(".") if err != nil { log.Fatalf("Failed to read remote directory: %v", err) } fmt.Println("Successfully connected! Remote directory contents:") for _, file := range files { fmt.Printf("- %s (size: %d bytes)\n", file.Name(), file.Size()) } }
Key Details to Note:
Private Key Handling: If you have your private key as a byte array instead of a file, skip the
ioutil.ReadFilestep and pass the byte array directly tossh.ParsePrivateKey. This works for standard OpenSSH private key formats (including encrypted keys, though you'll need to add passphrase handling if yours is encrypted).ssh-dss Host Key Support: The
Config.HostKeyAlgorithmsfield is set to explicitly allowssh-dss, which matches the-oHostKeyAlgorithms=+ssh-dssflag in your terminal command. For production use, replacessh.InsecureIgnoreHostKey()with logic to validate the server's actual DSS host key (to avoid man-in-the-middle attacks).Cleanup: We use
deferto ensure both the SSH and SFTP connections are closed properly, even if an error occurs.
Dependencies:
Install the required packages first:
go get github.com/pkg/sftp go get golang.org/x/crypto/ssh
This code should behave exactly like your terminal command, connecting to the SFTP server using your private key and accepting the ssh-dss host key algorithm.
内容的提问来源于stack exchange,提问作者Rohit T

