pupirka
/
parent.go
117 строк · 3.1 Кб
1package main
2
3import (
4"errors"
5"fmt"
6"golang.org/x/crypto/ssh"
7"io"
8"math/rand"
9"net"
10"time"
11)
12
13var MDeviceList = make(map[string]Device)
14var MLocalPort = make(map[uint16]string)
15
16func SshForwardNewDevice(parent Device, child Device) Device {
17child.LogDebug("SshForwardNewDevice: Get new address", child.Name)
18lport := SshLocalGeneratePort()
19go SshClientRunForward(&parent, child, lport)
20child.Address = "localhost"
21child.PortSSH = lport
22child.LogDebug(fmt.Sprintf("SshForwardNewDevice: new address (%s), new port (%d)", child.Address, child.PortSSH))
23return child
24
25}
26
27func SshClientRunForward(parent *Device, child Device, lport uint16) {
28auth, _ := SshClientDeviceAuth(parent)
29
30config := &ssh.ClientConfig{
31Config: ssh.Config{
32KeyExchanges: sshkkeysAlgo,
33Ciphers: sshChippers,
34},
35User: parent.Username,
36Auth: auth,
37HostKeyCallback: ssh.InsecureIgnoreHostKey(),
38Timeout: time.Duration(parent.Timeout) * time.Second,
39}
40
41localAddrString := fmt.Sprintf("localhost:%d", lport)
42localListener, err := net.Listen("tcp", localAddrString)
43if err != nil {
44child.LogError(fmt.Sprintf("SshClientRunForward net.Listen failed: %s", err.Error()))
45return
46}
47
48for {
49// Setup localConn (type net.Conn)
50localConn, err := localListener.Accept()
51if err != nil {
52child.LogError(fmt.Sprintf("SshClientRunForward listen.Accept failed: %s", err.Error()))
53return
54}
55go forward(localConn, config, SshAddressFormat(parent), SshAddressFormat(&child))
56}
57}
58
59func forward(localConn net.Conn, config *ssh.ClientConfig, parentaddress string, childaddress string) {
60// Setup sshClientConn (type *ssh.ClientConn)
61sshClientConn, err := ssh.Dial("tcp", parentaddress, config)
62if err != nil {
63LogConsole.Info(fmt.Sprintf("ssh.Dial failed %s ... Child %s, Parent %s", err.Error(), childaddress, parentaddress))
64_ = sshClientConn.Close()
65return
66}
67// Setup sshConn (type net.Conn)
68sshConn, err := sshClientConn.Dial("tcp", childaddress)
69
70// Copy localConn.Reader to sshConn.Writer
71go func() {
72_, err = io.Copy(sshConn, localConn)
73if err != nil {
74LogConsole.Info(fmt.Sprintf("io.Copy failed %s ... Child %s, Parent %s", err.Error(), childaddress, parentaddress))
75_ = sshConn.Close()
76_ = sshClientConn.Close()
77return
78}
79}()
80
81// Copy sshConn.Reader to localConn.Writer
82go func() {
83_, err = io.Copy(localConn, sshConn)
84if err != nil {
85LogConsole.Info(fmt.Sprintf("io.Copy failed %s ... Child %s, Parent %s", err.Error(), childaddress, parentaddress))
86_ = sshConn.Close()
87_ = sshClientConn.Close()
88return
89}
90}()
91
92}
93
94func SshLocalGeneratePort() uint16 {
95min := 40000
96max := 50000
97
98for {
99rand.Seed(time.Now().UnixNano())
100r := rand.Intn(max-min+1) + min
101if _, ok := MLocalPort[uint16(r)]; ok {
102continue
103}
104MLocalPort[uint16(r)] = ""
105return uint16(r)
106}
107}
108
109func SshNeedForward(device *Device) (Device, Device, error) {
110
111if _, ok := MDeviceList[device.Parent]; !ok {
112return Device{}, Device{}, errors.New("SshNeedForward: no isset parent device")
113}
114parent := MDeviceList[device.Parent]
115dev := *device
116return parent, dev, nil
117}
118