func main() { mylogger = logger.NewLogger("", 0) configPath := flag.String("config", "", "fssh config file") flag.Parse() if _, err := toml.DecodeFile(*configPath, &config); err != nil { mylogger.Fatal(err) } sshConfig := ssh.ServerConfig{ PublicKeyCallback: keyHandler, PasswordCallback: passwdHandler, } sshConfig.AddHostKey(readSecretKey(config.Key)) s, err := net.Listen("tcp", config.Address+":"+strconv.Itoa(config.Port)) if err != nil { mylogger.Fatal(err) } defer s.Close() for { c, err := s.Accept() if err != nil { mylogger.Fatal(err) } ssh.NewServerConn(c, &sshConfig) } }
func (s *Server) serve(conn net.Conn) error { config := ssh.ServerConfig{ PublicKeyCallback: s.config.PublicKeyCallback.wrap(), PasswordCallback: s.config.PasswordCallback.wrap(), } for _, hostKey := range s.config.HostKeys { config.AddHostKey(hostKey) } serverConn, channelRequestCh, globalRequestCh, err := ssh.NewServerConn(conn, &config) if err != nil { return err } // connection succeeded at this point. create the ssh connection and start the go procs. newConn := sshConn{ handler: s.config.Handler, conn: serverConn, newChannel: channelRequestCh, requests: globalRequestCh, } go newConn.processChannelRequests() go newConn.processGlobalRequests() return nil }
func main() { config := ssh.ServerConfig{ PublicKeyCallback: keyAuth, } config.AddHostKey(hostPrivateKeySigner) port := "2222" if os.Getenv("PORT") != "" { port = os.Getenv("PORT") } socket, err := net.Listen("tcp", ":"+port) if err != nil { panic(err) } for { conn, err := socket.Accept() if err != nil { panic(err) } // From a standard TCP connection to an encrypted SSH connection sshConn, _, _, err := ssh.NewServerConn(conn, &config) if err != nil { panic(err) } log.Println("Connection from", sshConn.RemoteAddr()) sshConn.Close() } }
// TestServer tests the SSH server. // // This listens on the non-standard port 2244 of localhost. This will generate // an entry in your known_hosts file, and will tie that to the testing key // used here. It's not recommended that you try to start another SSH server on // the same port (at a later time) or else you will have key issues that you // must manually resolve. func TestServer(t *testing.T) { key, err := sshTestingHostKey() if err != nil { t.Fatal(err) } cfg := ssh.ServerConfig{ NoClientAuth: true, } cfg.AddHostKey(key) c := NewCircuit() cxt := runServer(&cfg, c, t) // Give server time to initialize. time.Sleep(200 * time.Millisecond) if c.State() != ClosedState { t.Fatalf("circuit was not in closed state") } // Connect to the server and issue env var set. This should return true. client, err := ssh.Dial("tcp", testingServerAddr, &ssh.ClientConfig{}) if err != nil { t.Fatalf("Failed to connect client to local server: %s", err) } sess, err := client.NewSession() if err != nil { t.Fatalf("Failed to create client session: %s", err) } defer sess.Close() if err := sess.Setenv("HELLO", "world"); err != nil { t.Fatal(err) } if out, err := sess.Output("ping"); err != nil { t.Errorf("Output '%s' Error %s", out, err) } else if string(out) != "pong" { t.Errorf("Expected 'pong', got '%s'", out) } // Create a new session because the success of the last one closed the // connection. sess, err = client.NewSession() if err != nil { t.Fatalf("Failed to create client session: %s", err) } if err := sess.Run("illegal"); err == nil { t.Fatalf("expected a failed run with command 'illegal'") } if err := sess.Run("illegal command"); err == nil { t.Fatalf("expected a failed run with command 'illegal command'") } closer := cxt.Get("sshd.Closer", nil).(chan interface{}) closer <- true }
func basicServerConfig() *ssh.ServerConfig { config := ssh.ServerConfig{ Config: ssh.Config{ MACs: []string{"hmac-sha1"}, }, PasswordCallback: pwAuth, PublicKeyCallback: keyAuth, } config.AddHostKey(hostPrivateKeySigner) return &config }
func TestSetupForwardAgent(t *testing.T) { a, b, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer a.Close() defer b.Close() _, socket, cleanup := startAgent(t) defer cleanup() serverConf := ssh.ServerConfig{ NoClientAuth: true, } serverConf.AddHostKey(testSigners["rsa"]) incoming := make(chan *ssh.ServerConn, 1) go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) if err != nil { t.Fatalf("Server: %v", err) } incoming <- conn }() conf := ssh.ClientConfig{} conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) if err != nil { t.Fatalf("NewClientConn: %v", err) } client := ssh.NewClient(conn, chans, reqs) if err := ForwardToRemote(client, socket); err != nil { t.Fatalf("SetupForwardAgent: %v", err) } server := <-incoming ch, reqs, err := server.OpenChannel(channelType, nil) if err != nil { t.Fatalf("OpenChannel(%q): %v", channelType, err) } go ssh.DiscardRequests(reqs) agentClient := NewClient(ch) testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0) conn.Close() }
// startServer runs in a goroutine, configures the new server then listens for incoming connections func startServer(port string, errChan chan error) { config := ssh.ServerConfig{ PasswordCallback: authPassword, PublicKeyCallback: authKey, ServerVersion: "SSH-2.0-OpenSSH_6.7p1 Debian-5+deb8u2", } // generate a new private key each startcso it looks like a new server. privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { errChan <- err return } privateKeyDer := x509.MarshalPKCS1PrivateKey(privateKey) privateKeyBlock := pem.Block{ Type: "RSA PRIVATE KEY", Headers: nil, Bytes: privateKeyDer, } hostPrivateKeySigner, err := ssh.ParsePrivateKey(pem.EncodeToMemory(&privateKeyBlock)) if err != nil { errChan <- err return } config.AddHostKey(hostPrivateKeySigner) socket, err := net.Listen("tcp", ":"+port) if err != nil { errChan <- err return } for { conn, err := socket.Accept() if err != nil { break } // handle each incoming request in its own goroutine go handleSSH(conn, config) } // exit goroutine and advise the world errChan <- err return }
func startSSH(port string, b *batcher) (*SSHServer, error) { var err error s := &SSHServer{ port: port, b: b, } // start the ssh server listening config := ssh.ServerConfig{ PasswordCallback: authPassword, PublicKeyCallback: authKey, ServerVersion: "SSH-2.0-OpenSSH_6.7p1 Debian-5", } // generate a new private key each startcso it looks like a new server. privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err } privateKeyDer := x509.MarshalPKCS1PrivateKey(privateKey) privateKeyBlock := pem.Block{ Type: "RSA PRIVATE KEY", Headers: nil, Bytes: privateKeyDer, } hostPrivateKeySigner, err := ssh.ParsePrivateKey(pem.EncodeToMemory(&privateKeyBlock)) if err != nil { return nil, err } config.AddHostKey(hostPrivateKeySigner) s.socket, err = net.Listen("tcp", ":"+s.port) if err != nil { return nil, err } go s.listenForConn(config) return s, nil }
func TestAuth(t *testing.T) { a, b, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer a.Close() defer b.Close() agent, _, cleanup := startAgent(t) defer cleanup() if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil { t.Errorf("Add: %v", err) } serverConf := ssh.ServerConfig{} serverConf.AddHostKey(testSigners["rsa"]) serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { return nil, nil } return nil, errors.New("pubkey rejected") } go func() { conn, _, _, err := ssh.NewServerConn(a, &serverConf) if err != nil { t.Fatalf("Server: %v", err) } conn.Close() }() conf := ssh.ClientConfig{} conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers)) conn, _, _, err := ssh.NewClientConn(b, "", &conf) if err != nil { t.Fatalf("NewClientConn: %v", err) } conn.Close() }
func setupHostKey(config *ssh.ServerConfig) { var signers []ssh.Signer if keyEnv := os.Getenv("SSH_PRIVATE_KEYS"); keyEnv != "" { for _, block := range decodePemBlocks([]byte(keyEnv)) { signer, _ := signerFromBlock(block) if signer != nil { signers = append(signers, signer) } } } if *hostKey != "" { pemBytes, err := ioutil.ReadFile(*hostKey) if err != nil { debug("host key file error:", err) } for _, block := range decodePemBlocks(pemBytes) { signer, _ := signerFromBlock(block) if signer != nil { signers = append(signers, signer) } } } if len(signers) > 0 { for _, signer := range signers { config.AddHostKey(signer) } } else { debug("no host key provided, generating host key") key, err := rsa.GenerateKey(rand.Reader, 768) if err != nil { log.Fatalln("failed key generate:", err) } signer, err := ssh.NewSignerFromKey(key) if err != nil { log.Fatalln("failed signer:", err) } config.AddHostKey(signer) } }
func addKey(conf *ssh.ServerConfig, block *pem.Block) (err error) { var key interface{} switch block.Type { case "RSA PRIVATE KEY": key, err = x509.ParsePKCS1PrivateKey(block.Bytes) case "EC PRIVATE KEY": key, err = x509.ParseECPrivateKey(block.Bytes) case "DSA PRIVATE KEY": key, err = ssh.ParseDSAPrivateKey(block.Bytes) default: return fmt.Errorf("unsupported key type %q", block.Type) } if err != nil { return err } signer, err := ssh.NewSignerFromKey(key) if err != nil { return err } conf.AddHostKey(signer) return nil }
func getSshServerConfig(sshdConfig *config.Sshd) (*ssh.ServerConfig, error) { // In the latest version of crypto/ssh (after Go 1.3), the SSH server type has been removed // in favour of an SSH connection type. A ssh.ServerConn is created by passing an existing // net.Conn and a ssh.ServerConfig to ssh.NewServerConn, in effect, upgrading the net.Conn // into an ssh.ServerConn serverConfig := ssh.ServerConfig{ //Define a function to run when a client attempts a password login // TODO: Avoid Login by Password PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { // Should use constant-time compare (or better, salt+hash) in a production setting. if c.User() == "foo" && string(pass) == "bar" { return nil, nil } return nil, fmt.Errorf("password rejected for %q", c.User()) }, // TODO: Use PublicKeyCallback instead // PublicKeyCallback: func(conn ssh.ConnMetadata, key crypto.PublicKey) (*ssh.Permissions, error) { // TODO // } // TODO: // AuthLogCallback: func(conn ssh.ConnMetadata, method string, err error) { // TODO // } // // You may also explicitly allow anonymous client authentication, though anon bash // sessions may not be a wise idea // NoClientAuth: true, } private_key, err := getPrivateKey(sshdConfig) if err != nil { return nil, err } serverConfig.AddHostKey(private_key) return &serverConfig, nil }
runner *fakes.FakeRunner shellLocator *fakes.FakeShellLocator sessionChannelHandler *handlers.SessionChannelHandler newChannelHandlers map[string]handlers.NewChannelHandler defaultEnv map[string]string connectionFinished chan struct{} ) BeforeEach(func() { logger = lagertest.NewTestLogger("test") serverSSHConfig = &ssh.ServerConfig{ NoClientAuth: true, } serverSSHConfig.AddHostKey(TestHostKey) runner = &fakes.FakeRunner{} realRunner := handlers.NewCommandRunner() runner.StartStub = realRunner.Start runner.WaitStub = realRunner.Wait runner.SignalStub = realRunner.Signal shellLocator = &fakes.FakeShellLocator{} shellLocator.ShellPathReturns("/bin/sh") defaultEnv = map[string]string{} defaultEnv["TEST"] = "FOO" sessionChannelHandler = handlers.NewSessionChannelHandler(runner, shellLocator, defaultEnv, time.Second)
func main() { //SSH goroutine go func() { config := ssh.ServerConfig{ PublicKeyCallback: keyAuth, } config.AddHostKey(hostPrivateKeySigner) port := strconv.Itoa(hostSSHPort) socket, err := net.Listen("tcp", ":"+port) if err != nil { panic(err) } for { conn, err := socket.Accept() if err != nil { panic(err) } // From a standard TCP connection to an encrypted SSH connection sshConn, chans, reqs, err := ssh.NewServerConn(conn, &config) if err != nil { log.Println("Error accepting ssh connection: ", err) continue } log.Println("Connection from", sshConn.RemoteAddr()) // Print incoming out-of-band Requests go handleRequests(reqs) // Accept all channels go handleChannels(chans) } }() // // Garbage collecting goroutine // For testing, a stop-the-world gc using mutexes shall be 'nuff go func() { for { authRequestMap.Lock() for k, v := range authRequestMap.timestamps { killtime := time.Now().Add(-5 * time.Minute) if v.Before(killtime) { log.Debugf("Garbage collected key %s, %v old", k, time.Now().Sub(v)) delete(authRequestMap.timestamps, k) delete(authRequestMap.matches, k) } } authRequestMap.Unlock() time.Sleep(2 * time.Minute) } }() templateStart, err = template.New("index.html").ParseFiles("index.html") if err != nil { panic(err) } templateAuth, err = template.New("auth.html").ParseFiles("auth.html") if err != nil { panic(err) } http.HandleFunc("/auth", authRequestHandler) http.HandleFunc("/", startHandler) weblogOptions := &weblogs.Options{ Writer: nil, Logger: customLogger{}, } csrfHandler := nosurf.New(http.DefaultServeMux) csrfHandler.SetBaseCookie(http.Cookie{HttpOnly: true, Secure: sslEnabled}) handler := context.ClearHandler(weblogs.HandlerWithOptions(csrfHandler, weblogOptions)) if sslEnabled { go http.ListenAndServe(":"+strconv.Itoa(hostHTTPPort), handler) http.ListenAndServeTLS(":"+strconv.Itoa(hostTLSPort), sslCertPath, sslKeyPath, handler) } else { http.ListenAndServe(":"+strconv.Itoa(hostHTTPPort), handler) } }
proxyAddress string daemonAddress string proxyServer *server.Server sshdServer *server.Server ) BeforeEach(func() { fakeLogSender = fake_logs.NewFakeLogSender() logs.Initialize(fakeLogSender) proxyAuthenticator = &fake_authenticators.FakePasswordAuthenticator{} proxySSHConfig = &ssh.ServerConfig{} proxySSHConfig.PasswordCallback = proxyAuthenticator.Authenticate proxySSHConfig.AddHostKey(TestHostKey) daemonAuthenticator = &fake_authenticators.FakePasswordAuthenticator{} daemonAuthenticator.AuthenticateReturns(&ssh.Permissions{}, nil) daemonSSHConfig = &ssh.ServerConfig{} daemonSSHConfig.PasswordCallback = daemonAuthenticator.Authenticate daemonSSHConfig.AddHostKey(TestHostKey) daemonGlobalRequestHandlers = map[string]handlers.GlobalRequestHandler{} daemonNewChannelHandlers = map[string]handlers.NewChannelHandler{} var err error proxyListener, err = net.Listen("tcp", "127.0.0.1:0") Expect(err).NotTo(HaveOccurred()) proxyAddress = proxyListener.Addr().String()