-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsshrb
More file actions
executable file
·213 lines (168 loc) · 4.89 KB
/
sshrb
File metadata and controls
executable file
·213 lines (168 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/bin/bash
err() {
echo "$@" 2>/dev/null
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')] basecamp::reachback § $@" 1>/dev/null
}
# -----------------------------------------------
launch_httpd() {
local readonly addr="$1"
local readonly port="$2"
local readonly family="$3"
local rootdir="$4"
if [[ -z "${rootdir}" ]]; then
rootdir="/var/tmp/basecamp"
fi
mkdir -p ${rootdir}
pushd ${rootdir} >/dev/null
python <<EOT >/dev/null 2>&1 &
import socket, signal
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
class DerivativeServer(HTTPServer):
address_family = socket.AF_${family}
def main():
try:
httpd = DerivativeServer(('${addr}', ${port}), SimpleHTTPRequestHandler)
except socket.error as e:
raise SystemExit(e.errno)
def handler(signal, frame): # terminate server upon SIGTERM (OS kill)
Thread(target = httpd.shutdown, args=()).start()
signal.signal(signal.SIGTERM, handler) # register handler for OS kill
httpd.serve_forever() # start the server
if __name__ == '__main__':
main()
EOT
local readonly pid="$!"
popd >/dev/null 2>&1
echo -n "${pid} ${rootdir}"
}
choose_ports() {
local readonly addr="$1"
local readonly family="$2"
vacant_ports=$(python - "${addr}" "socket.AF_${family}" <<'EOT'
import errno, socket, sys
from random import SystemRandom
def main():
addr = sys.argv[1]
family = eval(sys.argv[2])
ports = []
busy_ports = []
vacant_ports = []
forbidden_ports = []
ctr = 0
while ctr < 20:
port = SystemRandom().randint(50000,59999)
if port not in ports:
ports.append(port)
ctr += 1
for port in ports:
try:
sock = socket.socket(family, socket.SOCK_STREAM)
sock.bind((addr, port))
sock.listen(5)
sock.close()
except socket.error as e:
if e.errno is errno.EADDRINUSE:
busy_ports.append(port)
elif e.errno is errno.EACCES:
forbidden_ports.append(port)
else:
raise SystemExit(e.errno)
vacant_ports.append(port)
if len(vacant_ports) > 0:
print ' '.join(str(port) for port in vacant_ports)
elif len(busy_ports) >= len(forbidden_ports):
raise SystemExit(errno.EADDRINUSE)
elif len(forbidden_ports) > len(busy_ports):
raise SystemExit(errno.EACCES)
if __name__ == '__main__':
main()
EOT
)
echo -n "${vacant_ports}"
# Return Code Legend:
#
# Code Unix Linux Meaning
# EACCES 13 13 Permission denied
# EAFNOSUPPORT 47 97 Address family not supported
# EADDRINUSE 48 98 Address already in use
# EADDRNOTAVAIL 49 99 Can't assign requested address
#
}
demolish_carrier() {
local readonly handle="$1"
local readonly target="$2"
local readonly muxdir="${handle%/*}"
ssh -O exit -S ${handle} ${target} >/dev/null 2>&1
local rc="$?"
rm -rf "${muxdir}"
return "${rc}"
}
establish_carrier() {
local readonly target="$1"
mkdir -p ~/.ssh/basecamp
local readonly handle="$(mktemp -d ~/.ssh/basecamp/mux.XXXXXXXXX)/control"
ssh -f -N -T -n \
-o ConnectTimeout=7 \
-o ControlMaster=yes \
-o ControlPersist=yes \
-o HostKeyAlgorithms=ssh-ed25519,ssh-rsa \
-o ServerAliveInterval=55 \
-S "${handle}" ${target} >/dev/null 2>&1
local rc="$?"
if [[ "${rc}" -ne 0 ]]; then
err "Unable to engage target host: ${target#*@}"
exit "${rc}"
fi
echo -n "${handle}"
}
launch_session() {
local readonly local_addr="$1"
local readonly family="$2"
local readonly handle="$3"
local readonly target="$4"
if [[ "${family}" == "INET6" ]]; then
local readonly host="[${local_addr}]"
else
local readonly host="${local_addr}"
fi
local readonly ports="$(choose_ports ${local_addr} ${family})"
local rc="$?"
if [[ "${rc}" -ne 0 ]]; then
return "${rc}"
fi
local local_port=0
for port in ${ports[@]}; do
local remote_port="$(ssh -O forward -R 0:${host}:${port} -S ${handle} ${target})"
if [[ "$?" -eq 0 ]]; then
local_port="${port}"
break
fi
done
if [[ "${local_port}" -eq 0 ]]; then
err "Could not open socket: ${local_addr} ${family}"
return 1
fi
local httpd_pid
local httpd_rootdir
read httpd_pid httpd_rootdir <<< $(launch_httpd ${local_addr} ${local_port} ${family})
echo; echo
echo "${httpd_rootdir} ~~~~~~ http://localhost:${remote_port}"
echo; echo
ssh -S ${handle} ${target}
kill "${httpd_pid}"
}
main() {
local readonly target="$1"
local readonly handle="$(establish_carrier ${target})"
launch_session '::1' 'INET6' "${handle}" "${target}"
local rc="$?"
if [[ "${rc}" -ne 0 ]]; then
launch_session '127.0.0.1' 'INET' "${handle}" "${target}"
local rc="$?"
fi
demolish_carrier "${handle}" "${target}"
exit "${rc}"
}
# -----------------------------------------------
main "$@"