-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
100 lines (84 loc) · 1.93 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package main
import (
"golang.org/x/crypto/ssh"
"log"
"net"
"io/ioutil"
"fmt"
"os/exec"
"github.com/kr/pty"
"sync"
"io"
)
func main() {
serverConfig := &ssh.ServerConfig{
NoClientAuth: true,
}
privateKeyBytes, err := ioutil.ReadFile("id_rsa")
if err != nil {
log.Fatal("Failed to load private key (./id_rsa)")
}
privateKey, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatal("Failed to parse private key")
}
serverConfig.AddHostKey(privateKey)
listener, err := net.Listen("tcp", "0.0.0.0:2222")
if err != nil {
log.Fatalf("Failed to listen on 2222 (%s)", err)
}
log.Print("Listening on 2222...")
for {
tcpConn, err := listener.Accept()
if err != nil {
log.Fatalf("Failed to accept on 2222 (%s)", err)
}
sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, serverConfig)
if err != nil {
log.Fatalf("Failed to handshake (%s)", err)
}
log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion())
go ssh.DiscardRequests(reqs)
go handleChannels(chans)
}
}
func handleChannels(chans <-chan ssh.NewChannel) {
for newChannel := range chans {
go handleChannel(newChannel)
}
}
func handleChannel(newChannel ssh.NewChannel) {
if t := newChannel.ChannelType(); t != "session" {
newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("Unknown channel type: %s", t))
return
}
sshChannel, _, err := newChannel.Accept()
if err != nil {
log.Fatalf("Could not accept channel (%s)", err)
return
}
bash := exec.Command("bash")
close := func() {
sshChannel.Close()
_, err := bash.Process.Wait()
if err != nil {
log.Printf("Failed to exit bash (%s)", err)
}
log.Printf("Session closed")
}
f, err := pty.Start(bash)
if err != nil {
log.Printf("Could not start pty (%s)", err)
close()
return
}
var once sync.Once
go func() {
io.Copy(sshChannel, f)
once.Do(close)
}()
go func() {
io.Copy(f, sshChannel)
once.Do(close)
}()
}