-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmosh-with-jump
executable file
·95 lines (83 loc) · 2.37 KB
/
mosh-with-jump
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
#!/usr/bin/env bash
set -o errexit -o pipefail -o nounset
orig_args=("$@")
mosh_server_args=()
proxy=
proxy_port=
target=
while [[ $# -gt 0 ]]; do
case "$1" in
--jump-server=*)
proxy=${1#--jump-server=}
;;
-J | --jump-server)
shift
proxy=$1
;;
--proxy-port=*)
proxy_port=${1#--proxy-port=}
;;
-P | --proxy-port)
shift
proxy_port=$1
;;
-p)
mosh_server_args+=("$1" "$2")
shift
;;
-*)
mosh_server_args+=("$1")
;;
*)
if [[ -z $target ]]; then
target=$1
else
mosh_server_args+=("$1")
fi
;;
esac
shift
done
# if we're not using a jump server, let's just call mosh directly
if [[ -z $proxy ]]; then
exec mosh "${orig_args[@]}"
fi
# we may be dealing with host aliases, so let's have SSH resolve that first so
# that we can get the host. however, we'll continue using $proxy and $target for
# SSH itself.
proxy_host=$(ssh -G "$proxy" | perl -anE '/^hostname (.+)/ && print "$1"')
proxy_ip=$(dig "$proxy_host" +short)
target_host=$(ssh -G "$target" | perl -anE '/^hostname (.+)/ && print "$1"')
echo "proxy: $proxy"
echo "proxy host: $proxy_host"
echo "proxy ip address: $proxy_ip"
echo "target: $target"
echo "target host: $target_host"
# start up the mosh server via the proxy
mosh_server_out=$(ssh -J "$proxy" "$target" -- mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -l LANGUAGE=en_US "${mosh_server_args[@]}")
# parse out the port and key; we'll need the port for proxying
connect_line=$(grep -m1 '^MOSH CONNECT ' <<< "$mosh_server_out")
target_port=$(perl -anE 'print $F[2]' <<< "$connect_line")
key=$(perl -anE 'print $F[3]' <<< "$connect_line")
if [[ -z $proxy_port ]]; then
# we'll need find a free port on the proxy, which might be different from the target
find_free_port_cmd=$(
cat << EOF
for (( p=$target_port ; p < $target_port + 10; p++ )); do
if [[ -z \$(ss -Hlu sport = \$p) ]]; then
echo "\$p"
exit
fi
done
exit 1
EOF
)
proxy_port=$(ssh -n "$proxy" bash -c "${find_free_port_cmd@Q}")
fi
echo "proxy port: $proxy_port"
echo "target port: $target_port"
# set up UDP proxying
# overall, we have client <--> proxy:$proxy_port <--> target:$target_port
ssh -tt -n "$proxy" socat udp-l:"$proxy_port",fork udp:"$target_host":"$target_port" 2>&1 &
trap 'kill -TERM -$$' EXIT
MOSH_KEY=$key mosh-client "$proxy_ip" "$proxy_port"