-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmaster.go
133 lines (118 loc) · 2.69 KB
/
master.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"flag"
"fmt"
"net"
"os"
)
func main() {
fmt.Println("*** Reverse Tunnel Master***")
tnAddr := flag.String("t", "", "tunnel address")
lnAddr := flag.String("l", "", "address to be listened")
flag.Parse()
if *tnAddr == "" || *lnAddr == "" {
fmt.Println("Address not specified, please see usage")
os.Exit(0)
}
rtm := NewRTMaster(*lnAddr, *tnAddr)
rtm.Start()
}
// RTMaster is the Master side of reverse tunnel.
type RTMaster struct {
lnAddr *net.TCPAddr
tnAddr *net.TCPAddr
cliCount int
cliConns map[int]net.Conn
tnConn *net.TCPConn
ch chan TunnelData
}
// NewRTMaster returns a RTMaster.
func NewRTMaster(lnAddr, tnAddr string) *RTMaster {
l, err := net.ResolveTCPAddr("tcp", lnAddr)
if err != nil {
fmt.Println("Invilid address")
}
t, err := net.ResolveTCPAddr("tcp", tnAddr)
if err != nil {
fmt.Println("Invilid address")
}
return &RTMaster{
lnAddr: l,
tnAddr: t,
cliCount: 0,
cliConns: make(map[int]net.Conn),
ch: make(chan TunnelData),
}
}
// Start start the reverse tunnel.
func (rtm *RTMaster) Start() {
// start tunnel
go func() {
tn, err := net.ListenTCP("tcp", rtm.tnAddr)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
fmt.Println("Listening on:", rtm.tnAddr.String())
rtm.tnConn, _ = tn.AcceptTCP()
rtm.tnConn.SetKeepAlive(true)
fmt.Println("[+] Tunnel established")
rtm.handleTunnelConn()
}()
// listen externel requests
ln, err := net.ListenTCP("tcp", rtm.lnAddr)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
fmt.Println("Listening on:", rtm.lnAddr.String())
for {
rtm.cliConns[rtm.cliCount], _ = ln.Accept()
go rtm.handleClientConn(rtm.cliCount)
rtm.cliCount++
}
}
func (rtm *RTMaster) handleTunnelConn() {
// forward req to tunnel
go func() {
for td := range rtm.ch {
tmp := []byte{byte(td.id), byte(td.size)}
tmp = append(tmp, td.data[:]...)
rtm.tnConn.Write(tmp)
fmt.Println("[*] forward", td.size, "bytes from client", td.id)
}
}()
// read from tunnel and send back to client
for {
var buf [bufSize]byte
_, err := rtm.tnConn.Read(buf[:])
if err != nil {
return
}
td := TunnelData{
id: int(buf[0]),
size: int(buf[1]),
data: buf[2:],
}
fmt.Println("[*] send back", td.size, "bytes", "to client", td.id)
rtm.cliConns[td.id].Write(td.data[:td.size])
}
}
// read req and forward to tunnel
func (rtm *RTMaster) handleClientConn(id int) {
fmt.Println("[!] Client", id, "comes ("+rtm.cliConns[id].RemoteAddr().String()+")")
for {
// reserve place for id and size
var buf [bufSize - 2]byte
n, err := rtm.cliConns[id].Read(buf[:])
if err != nil {
return
}
td := TunnelData{
id: id,
size: n,
data: buf[:],
}
rtm.ch <- td
}
}