Skip to content

Commit 029af06

Browse files
authored
Merge pull request #39 from kpedro88/add_tunn
Add tunn
2 parents ab53137 + 8fba1c7 commit 029af06

File tree

3 files changed

+316
-0
lines changed

3 files changed

+316
-0
lines changed

README.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
# lpc-scripts
22
scripts of use on the cmslpc cluster
33

4+
Table of Contents
5+
=================
6+
7+
* [call_host.sh](#call_hostsh)
8+
* [Note](#note)
9+
* [Usage](#usage)
10+
* [Manual](#manual)
11+
* [Automatic](#automatic)
12+
* [Details](#details)
13+
* [Options](#options)
14+
* [Caveats](#caveats)
15+
* [bind_condor.sh](#bind_condorsh)
16+
* [Usage](#usage-1)
17+
* [Setting up bindings](#setting-up-bindings)
18+
* [tunn](#tunn)
19+
* [Detailed usage](#detailed-usage)
20+
* [Web browser usage](#web-browser-usage)
21+
* [Unit and Integration testing](#unit-and-integration-testing)
22+
* [Automated](#automated)
23+
* [Manual](#manual-1)
24+
* [Bats for Bash scripts](#bats-for-bash-scripts)
25+
* [Pytest for Python modules](#pytest-for-python-modules)
26+
27+
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
28+
429
## `call_host.sh`
530

631
Many commands are installed on interactive nodes but are not accessible inside containers.
@@ -189,6 +214,75 @@ In this particular case, it is necessary to upgrade `pip` because the Python ver
189214
**NOTE**: These recipes only install the bindings for Python3. (Python2 was still the default in `CMSSW_10_6_X`.)
190215
You will need to make sure any scripts using the bindings are compatible with Python3.
191216
217+
## `tunn`
218+
219+
A simple utility to create and manage SSH tunnels.
220+
221+
The basic usage of `tunn` follows this pattern:
222+
1. `tunn make [email protected]`
223+
2. `tunn list`:
224+
```
225+
index: socket port command
226+
0: "/home/[user]/.tsock_xyz" 8XXX "[email protected]"
227+
```
228+
3. `tunn kill 0`:
229+
```
230+
Exit request sent.
231+
```
232+
233+
If you have host aliases defined in your `~/.ssh/config` file, you can use them with `tunn`.
234+
235+
### Detailed usage
236+
237+
The configuration and command-line options for `tunn` are described in its usage message:
238+
```
239+
tunn [operation] [options] [arguments]
240+
241+
Default settings are obtained from the config file at /home/[user]/.tunnconfig.
242+
To override the config file location, put this in your .bashrc or other login file:
243+
export TUNN_CONFIG=/my/preferred/file
244+
The available config variables are: TUNN_PREFIX, TUNN_PORT, TUNN_VERBOSE.
245+
Their values should be specified in the config file using bash syntax, e.g.:
246+
TUNN_PORT=8XXX
247+
(If TUNN_PORT is not specified in the config file or via the command line option,
248+
the default value is taken from the last three digits of your UID.)
249+
250+
Operations:
251+
252+
make make new tunnel
253+
-n [name] tunnel socket name prefix (default: /home/[user]/.tsock)
254+
-p [port] tunnel port (default: 8XXX)
255+
[destination] ssh destination for tunnel (required)
256+
257+
list list open tunnels
258+
259+
kill kill specified tunnel
260+
[index] index of tunnel (required)
261+
262+
Common options:
263+
-u (unclean) do not auto-remove closed tunnels from list
264+
-v toggle verbosity (default: false)
265+
-h print this message and exit
266+
```
267+
268+
### Web browser usage
269+
270+
There are addons available for web browsers to route traffic through ssh tunnels.
271+
[FoxyProxy](https://getfoxyproxy.org/downloads/) is recommended for most browsers (Chrome, Firefox, and derivatives; Safari has [equivalent internal settings](https://help.getfoxyproxy.org/index.php/knowledge-base/how-to-use-your-proxy-services-with-safari/).)
272+
273+
You can add LPC as a proxy server in the "Proxies" tab, with settings as follows:
274+
* Title: LPC
275+
* Hostname: localhost
276+
* Type: SOCKS5
277+
* Port: [your TUNN_PORT value 8XXX]
278+
* Proxy by patterns: [blank], "Include", "Wildcard", Title: FNAL, Pattern: \*://\*.fnal.gov/
279+
280+
<details>
281+
<summary>Firefox example screenshot:</summary>
282+
283+
![Foxyproxy settings screenshot](./docs/foxyproxy_lpc_generic.png)
284+
</details>
285+
192286
## Unit and Integration testing
193287
194288
### Automated

docs/foxyproxy_lpc_generic.png

12.2 KB
Loading

tunn

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/bin/bash
2+
3+
# helper functions
4+
5+
tunn_check_op() {
6+
if [ "$TUNN_OP" != "$1" ]; then
7+
usage 1
8+
fi
9+
}
10+
11+
tunn_echo() {
12+
if [ "$TUNN_VERBOSE" == "true" ]; then
13+
echo "$@"
14+
fi
15+
}
16+
17+
tunn_read_impl() {
18+
# get list of tunnels
19+
readarray -t TUNN_LIST < "$TUNN_LISTFILE"
20+
export TUNN_LIST
21+
}
22+
23+
tunn_update() {
24+
tunn_read_impl
25+
# clear list of tunnels
26+
: > "$TUNN_LISTFILE"
27+
# write open tunnels back into list
28+
for ((i=0; i < ${#TUNN_LIST[@]}; i++)); do
29+
tunn_entry $i
30+
# shellcheck disable=SC2086
31+
if ssh $TUNN_DEST -S "$TUNN_SOCKETNAME" -O check >&/dev/null; then
32+
echo "${TUNN_LIST[$i]}" >> "$TUNN_LISTFILE"
33+
else
34+
tunn_echo "Removing dead tunnel: ${TUNN_LIST[$i]}"
35+
rm "$TUNN_SOCKETNAME" >&/dev/null
36+
fi
37+
done
38+
unset TUNN_LIST
39+
}
40+
41+
tunn_read() {
42+
if [ -z "$TUNN_UNCLEAN" ]; then
43+
tunn_read_impl
44+
tunn_update
45+
fi
46+
tunn_read_impl
47+
}
48+
49+
tunn_entry() {
50+
ENTRY="${TUNN_LIST[$1]}"
51+
# split, respecting quotes
52+
declare -a "ENTRY_ARR=($ENTRY)"
53+
54+
# reconstruct command based on output format
55+
export TUNN_SOCKETNAME="${ENTRY_ARR[0]}"
56+
export TUNN_PORT="${ENTRY_ARR[1]}"
57+
export TUNN_DEST="${ENTRY_ARR[2]}"
58+
}
59+
60+
# operations
61+
62+
tunn_make() {
63+
TUNN_DEST="$*"
64+
if [ -z "$TUNN_DEST" ]; then
65+
usage 1
66+
fi
67+
68+
# generate a random name for socket
69+
TUNN_SOCKETNUM=$(uuidgen)
70+
TUNN_SOCKETNAME="$TUNN_PREFIX"_"$TUNN_SOCKETNUM"
71+
72+
# execute tunnel command
73+
# shellcheck disable=SC2086
74+
ssh $TUNN_DEST -N -D "$TUNN_PORT" -f -M -S "$TUNN_SOCKETNAME" 2>/dev/null
75+
TUNN_EXIT=$?
76+
77+
# add to list of tunnels
78+
if [ $TUNN_EXIT -eq 0 ]; then
79+
echo "\"$TUNN_SOCKETNAME\" $TUNN_PORT \"$TUNN_DEST\"" >> "$TUNN_LISTFILE"
80+
tunn_echo "Tunnel ready, port: $TUNN_PORT"
81+
else
82+
echo "Could not create tunnel (exit code $TUNN_EXIT)"
83+
exit $TUNN_EXIT
84+
fi
85+
}
86+
87+
tunn_list() {
88+
if [ -n "$1" ]; then
89+
usage 1
90+
fi
91+
92+
tunn_read
93+
if [ ${#TUNN_LIST[@]} -eq 0 ]; then
94+
return
95+
fi
96+
echo "index: socket port destination"
97+
for ((i=0; i < ${#TUNN_LIST[@]}; i++)); do
98+
echo "$i: ${TUNN_LIST[$i]}"
99+
done
100+
}
101+
102+
tunn_kill() {
103+
INDEX="$1"
104+
if [ -z "$INDEX" ]; then
105+
usage 1
106+
fi
107+
108+
# get this tunnel
109+
tunn_read
110+
if [ "$INDEX" -lt ${#TUNN_LIST[@]} ]; then
111+
tunn_entry "$INDEX"
112+
else
113+
echo "Tunnel index $INDEX not found"
114+
exit 2
115+
fi
116+
117+
# execute kill command
118+
# shellcheck disable=SC2086
119+
ssh $TUNN_DEST -S "$TUNN_SOCKETNAME" -O exit
120+
tunn_echo "Killed tunnel: ${TUNN_LIST[$INDEX]}"
121+
122+
# update list
123+
sed -i "$((INDEX+1))"d "$TUNN_LISTFILE"
124+
}
125+
126+
# defaults
127+
TUNN_LISTFILE=~/.tunnlist
128+
: "${TUNN_CONFIG:=~/.tunnconfig}"
129+
TUNN_SOCKETNAME=""
130+
TUNN_DEST=""
131+
TUNN_UNCLEAN=""
132+
133+
# get config defaults
134+
if [ -e "$TUNN_CONFIG" ]; then
135+
# shellcheck source=/dev/null
136+
source "$TUNN_CONFIG"
137+
fi
138+
: "${TUNN_PREFIX:=~/.tsock}"
139+
UTMP=$(id -u)
140+
UTMP=${UTMP:0-3}
141+
: "${TUNN_PORT:=8${UTMP}}"
142+
: "${TUNN_VERBOSE:=false}"
143+
144+
declare -A TUNN_INVERT
145+
TUNN_INVERT[true]=false
146+
TUNN_INVERT[false]=true
147+
148+
usage() {
149+
ECHO="echo -e"
150+
$ECHO "tunn [operation] [options] [arguments]"
151+
$ECHO
152+
$ECHO "Default settings are obtained from the config file at ${TUNN_CONFIG}."
153+
$ECHO "To override the config file location, put this in your .bashrc or other login file:"
154+
$ECHO "\texport TUNN_CONFIG=/my/preferred/file"
155+
$ECHO "The available config variables are: TUNN_PREFIX, TUNN_PORT, TUNN_VERBOSE."
156+
$ECHO "Their values should be specified in the config file using bash syntax, e.g.:"
157+
$ECHO "\tTUNN_PORT=8XXX"
158+
$ECHO "(If TUNN_PORT is not specified in the config file or via the command line option,"
159+
$ECHO "the default value is taken from the last three digits of your UID.)"
160+
$ECHO
161+
$ECHO "Operations:"
162+
$ECHO
163+
$ECHO "make \t make new tunnel"
164+
$ECHO "\t-n [name] \t tunnel socket name prefix (default: ${TUNN_PREFIX})"
165+
$ECHO "\t-p [port] \t tunnel port (default: $TUNN_PORT)"
166+
$ECHO "\t[destination] \t ssh destination for tunnel (required)"
167+
$ECHO
168+
$ECHO "list \t list open tunnels"
169+
$ECHO
170+
$ECHO "kill \t kill specified tunnel"
171+
$ECHO "\t[index] \t index of tunnel (required)"
172+
$ECHO
173+
$ECHO "Common options:"
174+
$ECHO "-u \t (unclean) do not auto-remove closed tunnels from list"
175+
$ECHO "-v \t toggle verbosity (default: $TUNN_VERBOSE)"
176+
$ECHO "-h \t print this message and exit"
177+
exit "$1"
178+
}
179+
180+
# get operation
181+
TUNN_OP="$1"
182+
shift 1
183+
184+
TUNN_OPFN=""
185+
case "$TUNN_OP" in
186+
make) TUNN_OPFN=tunn_make
187+
;;
188+
list) TUNN_OPFN=tunn_list
189+
;;
190+
kill) TUNN_OPFN=tunn_kill
191+
;;
192+
*) usage 1
193+
;;
194+
esac
195+
196+
while getopts "n:p:uvh" opt; do
197+
case "$opt" in
198+
n) tunn_check_op make; TUNN_PREFIX="$OPTARG"
199+
;;
200+
p) tunn_check_op make; TUNN_PORT="$OPTARG"
201+
;;
202+
u) TUNN_UNCLEAN=true
203+
;;
204+
v) TUNN_VERBOSE="${TUNN_INVERT[$TUNN_VERBOSE]}"
205+
;;
206+
h) usage 0
207+
;;
208+
*) usage 1
209+
;;
210+
esac
211+
done
212+
213+
# ensure list file exists
214+
if [ ! -e "$TUNN_LISTFILE" ]; then
215+
touch "$TUNN_LISTFILE"
216+
fi
217+
218+
# get args for operation (if any)
219+
shift $((OPTIND - 1))
220+
221+
# execute operation
222+
$TUNN_OPFN "$@"

0 commit comments

Comments
 (0)