1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
19 "golang.org/x/crypto/ssh"
20 "golang.org/x/crypto/ssh/terminal"
23 func ExampleNewServerConn() {
24 // Public key authentication is done by comparing
25 // the public key of a received connection
26 // with the entries in the authorized_keys file.
27 authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
29 log.Fatalf("Failed to load authorized_keys, err: %v", err)
32 authorizedKeysMap := map[string]bool{}
33 for len(authorizedKeysBytes) > 0 {
34 pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
39 authorizedKeysMap[string(pubKey.Marshal())] = true
40 authorizedKeysBytes = rest
43 // An SSH server is represented by a ServerConfig, which holds
44 // certificate details and handles authentication of ServerConns.
45 config := &ssh.ServerConfig{
46 // Remove to disable password auth.
47 PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
48 // Should use constant-time compare (or better, salt+hash) in
49 // a production setting.
50 if c.User() == "testuser" && string(pass) == "tiger" {
53 return nil, fmt.Errorf("password rejected for %q", c.User())
56 // Remove to disable public key auth.
57 PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
58 if authorizedKeysMap[string(pubKey.Marshal())] {
59 return &ssh.Permissions{
60 // Record the public key used for authentication.
61 Extensions: map[string]string{
62 "pubkey-fp": ssh.FingerprintSHA256(pubKey),
66 return nil, fmt.Errorf("unknown public key for %q", c.User())
70 privateBytes, err := ioutil.ReadFile("id_rsa")
72 log.Fatal("Failed to load private key: ", err)
75 private, err := ssh.ParsePrivateKey(privateBytes)
77 log.Fatal("Failed to parse private key: ", err)
80 config.AddHostKey(private)
82 // Once a ServerConfig has been configured, connections can be
84 listener, err := net.Listen("tcp", "0.0.0.0:2022")
86 log.Fatal("failed to listen for connection: ", err)
88 nConn, err := listener.Accept()
90 log.Fatal("failed to accept incoming connection: ", err)
93 // Before use, a handshake must be performed on the incoming
95 conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
97 log.Fatal("failed to handshake: ", err)
99 log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])
101 // The incoming Request channel must be serviced.
102 go ssh.DiscardRequests(reqs)
104 // Service the incoming Channel channel.
105 for newChannel := range chans {
106 // Channels have a type, depending on the application level
107 // protocol intended. In the case of a shell, the type is
108 // "session" and ServerShell may be used to present a simple
109 // terminal interface.
110 if newChannel.ChannelType() != "session" {
111 newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
114 channel, requests, err := newChannel.Accept()
116 log.Fatalf("Could not accept channel: %v", err)
119 // Sessions have out-of-band requests such as "shell",
120 // "pty-req" and "env". Here we handle only the
122 go func(in <-chan *ssh.Request) {
123 for req := range in {
124 req.Reply(req.Type == "shell", nil)
128 term := terminal.NewTerminal(channel, "> ")
131 defer channel.Close()
133 line, err := term.ReadLine()
143 func ExampleHostKeyCheck() {
144 // Every client must provide a host key check. Here is a
145 // simple-minded parse of OpenSSH's known_hosts file
147 file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
153 scanner := bufio.NewScanner(file)
154 var hostKey ssh.PublicKey
156 fields := strings.Split(scanner.Text(), " ")
157 if len(fields) != 3 {
160 if strings.Contains(fields[0], host) {
162 hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
164 log.Fatalf("error parsing %q: %v", fields[2], err)
171 log.Fatalf("no hostkey for %s", host)
174 config := ssh.ClientConfig{
175 User: os.Getenv("USER"),
176 HostKeyCallback: ssh.FixedHostKey(hostKey),
179 _, err = ssh.Dial("tcp", host+":22", &config)
184 var hostKey ssh.PublicKey
185 // An SSH client is represented with a ClientConn.
187 // To authenticate with the remote server you must pass at least one
188 // implementation of AuthMethod via the Auth field in ClientConfig,
189 // and provide a HostKeyCallback.
190 config := &ssh.ClientConfig{
192 Auth: []ssh.AuthMethod{
193 ssh.Password("yourpassword"),
195 HostKeyCallback: ssh.FixedHostKey(hostKey),
197 client, err := ssh.Dial("tcp", "yourserver.com:22", config)
199 log.Fatal("Failed to dial: ", err)
202 // Each ClientConn can support multiple interactive sessions,
203 // represented by a Session.
204 session, err := client.NewSession()
206 log.Fatal("Failed to create session: ", err)
208 defer session.Close()
210 // Once a Session is created, you can execute a single command on
211 // the remote side using the Run method.
214 if err := session.Run("/usr/bin/whoami"); err != nil {
215 log.Fatal("Failed to run: " + err.Error())
217 fmt.Println(b.String())
220 func ExamplePublicKeys() {
221 var hostKey ssh.PublicKey
222 // A public key may be used to authenticate against the remote
223 // server by using an unencrypted PEM-encoded private key file.
225 // If you have an encrypted private key, the crypto/x509 package
226 // can be used to decrypt it.
227 key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
229 log.Fatalf("unable to read private key: %v", err)
232 // Create the Signer for this private key.
233 signer, err := ssh.ParsePrivateKey(key)
235 log.Fatalf("unable to parse private key: %v", err)
238 config := &ssh.ClientConfig{
240 Auth: []ssh.AuthMethod{
241 // Use the PublicKeys method for remote authentication.
242 ssh.PublicKeys(signer),
244 HostKeyCallback: ssh.FixedHostKey(hostKey),
247 // Connect to the remote server and perform the SSH handshake.
248 client, err := ssh.Dial("tcp", "host.com:22", config)
250 log.Fatalf("unable to connect: %v", err)
255 func ExampleClient_Listen() {
256 var hostKey ssh.PublicKey
257 config := &ssh.ClientConfig{
259 Auth: []ssh.AuthMethod{
260 ssh.Password("password"),
262 HostKeyCallback: ssh.FixedHostKey(hostKey),
264 // Dial your ssh server.
265 conn, err := ssh.Dial("tcp", "localhost:22", config)
267 log.Fatal("unable to connect: ", err)
271 // Request the remote side to open port 8080 on all interfaces.
272 l, err := conn.Listen("tcp", "0.0.0.0:8080")
274 log.Fatal("unable to register tcp forward: ", err)
278 // Serve HTTP with your SSH server acting as a reverse proxy.
279 http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
280 fmt.Fprintf(resp, "Hello world!\n")
284 func ExampleSession_RequestPty() {
285 var hostKey ssh.PublicKey
286 // Create client config
287 config := &ssh.ClientConfig{
289 Auth: []ssh.AuthMethod{
290 ssh.Password("password"),
292 HostKeyCallback: ssh.FixedHostKey(hostKey),
294 // Connect to ssh server
295 conn, err := ssh.Dial("tcp", "localhost:22", config)
297 log.Fatal("unable to connect: ", err)
301 session, err := conn.NewSession()
303 log.Fatal("unable to create session: ", err)
305 defer session.Close()
306 // Set up terminal modes
307 modes := ssh.TerminalModes{
308 ssh.ECHO: 0, // disable echoing
309 ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
310 ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
312 // Request pseudo terminal
313 if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
314 log.Fatal("request for pseudo terminal failed: ", err)
316 // Start remote shell
317 if err := session.Shell(); err != nil {
318 log.Fatal("failed to start shell: ", err)