-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.go
119 lines (99 loc) · 2.74 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main
import (
"fmt"
"io"
"log"
"os"
"sync"
gssh "github.com/gliderlabs/ssh"
"golang.org/x/crypto/ssh"
"github.com/arkan/bastion/pkg/logchannel"
)
func main() {
sshBastionTarget, sshBastionPassword := os.Getenv("SSH_BASTION_TARGET"), os.Getenv("SSH_BASTION_PASSWORD")
if sshBastionTarget == "" || sshBastionPassword == "" {
fmt.Printf("Please set SSH_BASTION_TARGET and SSH_BASTION_PASSWORD\n")
fmt.Printf("EXAMPLE:\n")
fmt.Printf("export SSH_BASTION_PASSWORD=password\n")
fmt.Printf("export SSH_BASTION_TARGET=192.168.1.62:22\n")
os.Exit(1)
}
gssh.Handle(func(s gssh.Session) {
// authorizedKey := gossh.MarshalAuthorizedKey(s.PublicKey())
// io.WriteString(s, fmt.Sprintf("public key used by %s:\n", s.User()))
// s.Write(authorizedKey)
clientConfig := &ssh.ClientConfig{
User: "arkan",
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Auth: []ssh.AuthMethod{
ssh.Password(sshBastionPassword),
},
}
remoteConn, err := ssh.Dial("tcp", sshBastionTarget, clientConfig)
if err != nil {
log.Println("[ERROR] SSH connection failed", err)
return
}
defer remoteConn.Close()
channel2, reqs2, err := remoteConn.OpenChannel("session", []byte{})
if err != nil {
log.Println("[ERROR] SSH connection open channel failed", err)
return
}
log.Println("[INFO] SSH connecion established")
defer log.Println("[INFO] SSH connecion closed")
proxy(s.MaskedReqs(), reqs2, s, channel2)
})
publicKeyOption := gssh.PublicKeyAuth(func(ctx gssh.Context, key gssh.PublicKey) bool {
return true // allow all keys, or use ssh.KeysEqual() to compare against known keys
})
log.Println("starting ssh server on port 2222...")
log.Fatal(gssh.ListenAndServe(":2222", nil, publicKeyOption))
}
func proxy(reqs1, reqs2 <-chan *ssh.Request, channel1 ssh.Channel, channel2 ssh.Channel) {
f, err := os.OpenFile("session.ttyrec", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
if err != nil {
panic(err)
}
wrappedChannel1 := logchannel.New(channel1, f)
var closer sync.Once
closeFunc := func() {
wrappedChannel1.Close()
channel2.Close()
}
defer closer.Do(closeFunc)
closerChan := make(chan bool, 1)
// From remote, to client.
go func() {
_, _ = io.Copy(wrappedChannel1, channel2)
closerChan <- true
}()
go func() {
_, _ = io.Copy(channel2, channel1)
closerChan <- true
}()
for {
select {
case req := <-reqs1:
if req == nil {
return
}
b, err := channel2.SendRequest(req.Type, req.WantReply, req.Payload)
if err != nil {
return
}
req.Reply(b, nil)
case req := <-reqs2:
if req == nil {
return
}
b, err := channel1.SendRequest(req.Type, req.WantReply, req.Payload)
if err != nil {
return
}
req.Reply(b, nil)
case <-closerChan:
return
}
}
}