-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathparent.go
117 lines (101 loc) · 3.07 KB
/
parent.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
package main
import (
"errors"
"fmt"
"golang.org/x/crypto/ssh"
"io"
"math/rand"
"net"
"time"
)
var MDeviceList = make(map[string]Device)
var MLocalPort = make(map[uint16]string)
func SshForwardNewDevice(parent Device, child Device) Device {
child.LogDebug("SshForwardNewDevice: Get new address", child.Name)
lport := SshLocalGeneratePort()
go SshClientRunForward(&parent, child, lport)
child.Address = "localhost"
child.PortSSH = lport
child.LogDebug(fmt.Sprintf("SshForwardNewDevice: new address (%s), new port (%d)", child.Address, child.PortSSH))
return child
}
func SshClientRunForward(parent *Device, child Device, lport uint16) {
auth, _ := SshClientDeviceAuth(parent)
config := &ssh.ClientConfig{
Config: ssh.Config{
KeyExchanges: sshkkeysAlgo,
Ciphers: sshChippers,
},
User: parent.Username,
Auth: auth,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: time.Duration(parent.Timeout) * time.Second,
}
localAddrString := fmt.Sprintf("localhost:%d", lport)
localListener, err := net.Listen("tcp", localAddrString)
if err != nil {
child.LogError(fmt.Sprintf("SshClientRunForward net.Listen failed: %s", err.Error()))
return
}
for {
// Setup localConn (type net.Conn)
localConn, err := localListener.Accept()
if err != nil {
child.LogError(fmt.Sprintf("SshClientRunForward listen.Accept failed: %s", err.Error()))
return
}
go forward(localConn, config, SshAddressFormat(parent), SshAddressFormat(&child))
}
}
func forward(localConn net.Conn, config *ssh.ClientConfig, parentaddress string, childaddress string) {
// Setup sshClientConn (type *ssh.ClientConn)
sshClientConn, err := ssh.Dial("tcp", parentaddress, config)
if err != nil {
LogConsole.Info(fmt.Sprintf("ssh.Dial failed %s ... Child %s, Parent %s", err.Error(), childaddress, parentaddress))
_ = sshClientConn.Close()
return
}
// Setup sshConn (type net.Conn)
sshConn, err := sshClientConn.Dial("tcp", childaddress)
// Copy localConn.Reader to sshConn.Writer
go func() {
_, err = io.Copy(sshConn, localConn)
if err != nil {
LogConsole.Info(fmt.Sprintf("io.Copy failed %s ... Child %s, Parent %s", err.Error(), childaddress, parentaddress))
_ = sshConn.Close()
_ = sshClientConn.Close()
return
}
}()
// Copy sshConn.Reader to localConn.Writer
go func() {
_, err = io.Copy(localConn, sshConn)
if err != nil {
LogConsole.Info(fmt.Sprintf("io.Copy failed %s ... Child %s, Parent %s", err.Error(), childaddress, parentaddress))
_ = sshConn.Close()
_ = sshClientConn.Close()
return
}
}()
}
func SshLocalGeneratePort() uint16 {
min := 40000
max := 50000
for {
rand.Seed(time.Now().UnixNano())
r := rand.Intn(max-min+1) + min
if _, ok := MLocalPort[uint16(r)]; ok {
continue
}
MLocalPort[uint16(r)] = ""
return uint16(r)
}
}
func SshNeedForward(device *Device) (Device, Device, error) {
if _, ok := MDeviceList[device.Parent]; !ok {
return Device{}, Device{}, errors.New("SshNeedForward: no isset parent device")
}
parent := MDeviceList[device.Parent]
dev := *device
return parent, dev, nil
}