@@ -35,7 +35,7 @@ source "$HOME/.tunmgrd.conf"
35
35
_logFile=$logDir /tunmgrd.log
36
36
_logColor=$logColor
37
37
for (( t= 0 ; t < ${# config[@]} ; ++ t)) ; do
38
- read addresses [t] options [t] tunnels [t] <<< " ${config[t]}"
38
+ read urls [t] modifiers [t] configs [t] <<< " ${config[t]}"
39
39
done
40
40
41
41
@@ -45,8 +45,8 @@ inf '\t- PID: %d' "$$"
45
45
inf ' \t- Logging to: %s' " $logDir "
46
46
inf
47
47
inf " Tunnels:"
48
- for t in " ${! addresses [@]} " ; do
49
- inf ' \t- [%s]%s (%s)' " ${options [t]} " " ${addresses [t]} " " ${tunnels [t]} "
48
+ for t in " ${! urls [@]} " ; do
49
+ inf ' \t- [%s]%s (%s)' " ${modifiers [t]} " " ${urls [t]} " " ${configs [t]} "
50
50
done
51
51
52
52
@@ -72,6 +72,9 @@ showStatus() {
72
72
printf " [%s:%s] [%s]%s\n" " $t " " $tstate " " ${type[t]} " " ${name[t]} "
73
73
done
74
74
}
75
+ shutdown () {
76
+ kill " ${pid[@]} " 2> /dev/null
77
+ }
75
78
76
79
77
80
# Run loop
@@ -81,10 +84,16 @@ trap shutdown EXIT
81
84
while true ; do
82
85
83
86
# Manage our tunnels.
84
- for t in " ${! addresses[@]} " ; do
85
- IFS=: read host port _ <<< " ${addresses[t]}:22"
86
-
87
- # Can we get a response over the connection?
87
+ for t in " ${! urls[@]} " ; do
88
+ IFS=: read host port _ <<< " ${urls[t]#*://}"
89
+ schema=${urls[t]%%://* }
90
+ case " $schema " in
91
+ ssh) port=${port:- 22} ;;
92
+ http) port=${port:- 80} ;;
93
+ https) port=${port:- 443} ;;
94
+ esac
95
+
96
+ # Can we get a response over the connection? -> up
88
97
if [[ ${out[t]} ]] && {
89
98
read -d ' '
90
99
for tries in {1..3}; do
@@ -94,72 +103,87 @@ while true; do
94
103
} < " ${out[t]} " ; then
95
104
[[ ${state[t]} != up ]] && {
96
105
state[t]=up
97
- inf ' Connection Up: %s' " ${addresses [t]} "
106
+ inf ' Connection Up: %s' " ${urls [t]} "
98
107
}
99
108
continue
100
109
fi
101
110
102
- # Is the process alive?
111
+ # No response received - Is the process alive? -> lag
103
112
if kill -0 " ${pid[t]} " 2> /dev/null; then
104
113
[[ ${state[t]} != @ (conn| lag) ]] && {
105
114
state[t]=lag
106
- wrn ' Connection Lagging: %s' " ${addresses [t]} "
115
+ wrn ' Connection Lagging: %s' " ${urls [t]} "
107
116
}
108
117
continue
109
118
fi
110
119
111
- # Connection unavailable and no live ssh client for it.
120
+ # Process disappeared. -> down
112
121
[[ ${state[t]} != @ (n/a| down| ) ]] && {
113
122
state[t]=down
114
- perr ' Connection Lost: %s' " ${addresses [t]} "
123
+ perr ' Connection Lost: %s' " ${urls [t]} "
115
124
wait " ${pid[t]} " 2> /dev/null
116
125
rrep ' %d: %s' " $? " " $( < " ${err[t]} " ) "
117
126
}
118
127
unset ' pid[t]'
119
128
120
129
121
- # Host unavailable?
130
+ # No process, check service availability. -> unavailable
122
131
if ! nc -z " $host " " $port " & > /dev/null; then
123
132
[[ ${state[t]} != n/a ]] && {
124
- wrn ' Connection Unavailable: %s' " ${addresses [t]} "
133
+ wrn ' Connection Unavailable: %s - %s:%d ' " ${urls [t]} " " $host " " $port "
125
134
state[t]=n/a
126
135
}
127
136
continue
128
137
fi
129
138
130
- # Open the tunnel
131
- inf ' Connection Opening: %s' " ${addresses[t]} "
132
- arguments=()
133
- if [[ ${options[t]} = * M* ]]; then
134
- arguments+=( -M )
135
- fi
136
- read -r -a ctunnels <<< " ${tunnels[t]}"
137
- for ctunnel in " ${ctunnels[@]} " ; do
138
- IFS=: read side ports <<< " $ctunnel"
139
- saddress=${ports%% ->* }
140
- daddress=${ports#* ->}
141
- IFS=: read shost sport <<< " $saddress"
142
- IFS=: read dhost dport <<< " $daddress"
143
- [[ $sport ]] || sport=$shost shost=localhost
144
- [[ $dport ]] || dport=$dhost dhost=localhost
145
- case $side in
146
- LOCAL) arguments+=( -L " $shost :$sport :$dhost :$dport " ) ;;
147
- REMOTE) arguments+=( -R " $shost :$sport :$dhost :$dport " ) ;;
148
- esac
149
- done
150
-
151
- # Launch the SSH client which sets up the actual connection.
139
+ # Service available, open a connection. -> connecting
140
+ inf ' Connection Opening: %s' " ${urls[t]} "
152
141
out[t]=$logDir /tunmgrd.tun$t .out
153
142
err[t]=$logDir /tunmgrd.tun$t .err
154
- ssh -n > " ${out[t]} " 2> >( tr -d ' \r' > " ${err[t]} " ) \
155
- -o " BatchMode yes" \
156
- -o " ExitOnForwardFailure yes" \
157
- -o " ServerAliveCountMax 3" \
158
- -o " ServerAliveInterval 5" \
159
- -p " $port " \
160
- " ${arguments[@]} " " $host " ' while sleep 1; do printf .; done' &
161
- state[t]=conn pid[t]=$!
162
143
144
+ arguments=()
145
+ if [[ ${modifiers[t]} = * M* ]]; then
146
+ arguments+=( -M )
147
+ fi
148
+ read -r -a cconfigs <<< " ${configs[t]}"
149
+
150
+ case " $schema " in
151
+ ssh)
152
+ for cconfig in " ${cconfigs[@]} " ; do
153
+ IFS=: read side ports <<< " $cconfig"
154
+ saddress=${ports%% ->* }
155
+ daddress=${ports#* ->}
156
+ IFS=: read shost sport <<< " $saddress"
157
+ IFS=: read dhost dport <<< " $daddress"
158
+ [[ $sport ]] || sport=$shost shost=localhost
159
+ [[ $dport ]] || dport=$dhost dhost=localhost
160
+ case $side in
161
+ LOCAL) arguments+=( -L " $shost :$sport :$dhost :$dport " ) ;;
162
+ REMOTE) arguments+=( -R " $shost :$sport :$dhost :$dport " ) ;;
163
+ esac
164
+ done
165
+
166
+ # Launch the SSH client which sets up the actual connection.
167
+ eval " $( keychain --inherit any --quiet --quick --eval) "
168
+ ssh -n > " ${out[t]} " 2> >( tr -d ' \r' > " ${err[t]} " ) \
169
+ -o " BatchMode yes" \
170
+ -o " ExitOnForwardFailure yes" \
171
+ -o " ServerAliveCountMax 3" \
172
+ -o " ServerAliveInterval 5" \
173
+ -p " $port " \
174
+ " ${arguments[@]} " " $host " ' while sleep 1; do printf .; done' &
175
+ state[t]=conn pid[t]=$!
176
+ ;;
177
+
178
+ http* )
179
+ curl -sSnfo - " $url " > " ${out[t]} " 2> " ${err[t]} " &
180
+ state[t]=conn pid[t]=$!
181
+ ;;
182
+
183
+ * )
184
+ unset ' out[t]' ' err[t]'
185
+ ;;
186
+ esac
163
187
done
164
188
165
189
sleep 1
0 commit comments