-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsshswitch
More file actions
executable file
·131 lines (106 loc) · 3.75 KB
/
Copy pathsshswitch
File metadata and controls
executable file
·131 lines (106 loc) · 3.75 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
#!/usr/bin/env bash
sshswitch_usage() {
mdformat <<EOusage | ${PAGER:-cat}
**NAME**
${0##*/} - select ssh connection method based on availability
**SYNOPSIS**
${0##*/} [**-dn**] _hostname_
${0##*/} [**-dn**] _host_ ["_command line_"]
**DESCRIPTION**
This is a ProxyCommand helper.
In the first usage, _hostname_ is a name found in /etc/ethers,
whose MAC address will be looked up in the local ARP cache
(after 1 ping if required). This allows you to ssh to hosts
whose IP addresses change, but whose (static) ethernet address
is known, without configuring dynamic DNS in your DHCP server.
In the second usage, the first option is the name or IP address
you're trying to reach. It may be an IP wildcard pattern (for
example "192.168.1.*"). If the first option is a hostname, then
the IP is looked up in /etc/ethers. If the IP is local (i.e. in
the ARP cache after 1 ping), we connect to it directly, as with
the first usage. However, if that fails, we execute the
remaining options as a command line to establish the connection.
The **-d** option causes extra debugging information to be sent to
stderr. The **-n** option causes ${0##*/} to print the
commands it would run instead of actually running them.
**EXAMPLES**
The following might be used if you sometimes connect to the
192.168.2.0/24 network, which has a gateway on its .1 IP, and
that gateway is perhaps accessible from some other host via an
SSH tunnel or VPN.
**host gw 192.168.2.1**
**ProxyCommand ~/bin/sshswitch 192.168.2.1 ssh -xaqW10.0.0.2:22 foo**
Note that quotes aroung the command are optional.
**host bar 192.168.2.***
**ProxyCommand ~/bin/sshswitch %h "ssh -xaqW%h:22 gw"**
The following could be used for any host that might get a
dynamic IP address, for example, from a DHCP server.
The following might be used to connect to hosts with dynamic
(DHCP-assigned) IP addresses on the local network, without the
need to use a DHCP-controlled DNS zone. In this case, the only
thing static is the MAC address.
~/.ssh/config:
**host flarn spoo rpi**
**ProxyCommand ~/bin/sshswitch %h**
/etc/ethers:
**dc:a9:04:03:02:01 flarn**
**dc:a9:04:03:02:03 spoo**
**b8:27:eb:03:02:01 rpi**
$ arp -an
? (192.168.1.2) at dc:a9:04:03:02:01 on em0 ifscope [ethernet]
EOusage
}
mdformat() {
local md so us mr me
if $topt; then
md=$(tput md) # bold
so=$(tput so) # standout (inverse?)
us=$(tput us) # underline
mr=$(tput mr) # reverse
me=$(tput me) # exit attributes
fi
sed -E \
-e "s/\*\*([^*]+)\*\*/$md\1$me/g" \
-e "s/\*([^*]+)\*/$us\1$me/g" \
-e "s/_([^_]+)_/$us\1$me/g" \
-e "s/^#+ *(.+)/$so\1$me/g" \
-e "s/#([^#]+)#/$mr\1$me/g"
}
if [ -t 1 ]; then
topt=true
else
topt=false
fi
dopt=false; nopt=false
while getopts dn opt; do
case "$opt" in
d) dopt=true ;;
n) nopt=true ;;
*) sshswitch_usage; exit ;;
esac
done
shift $((OPTIND - 1))
# Populate ARP cache
ping -t 1 -c 1 "$1" >/dev/null 2>/dev/null &
sleep 0.25 2>/dev/null || sleep 1
if [ $# -eq 0 ]; then
sshswitch_usage
elif [ $# -eq 1 ] && grep -qw "$1" /etc/ethers; then
$dopt && echo nc "$(arp -an | awk -v h="$1" 'NR==FNR{a[$1]=$2;next} a[$4]==h{gsub(/[()]/,"",$2);print $2;exit}' /etc/ethers -)" 22
$nopt || nc "$(arp -an | awk -v h="$1" 'NR==FNR{a[$1]=$2;next} a[$4]==h{gsub(/[()]/,"",$2);print $2;exit}' /etc/ethers -)" 22
elif [ $# -eq 1 ]; then
printf 'ERROR: host not found\n' >&2
exit 68
elif arp -an | awk -v h="$1" '$2=="("h")" && $4~/[0-9a-f]+:/{r=0} END{exit r}' r=1 -; then
# If the IP in $1 is local, connect directly
case "$1" in
*:*) $dopt && echo nc "${1%:*}" "${1#*}" ;
$nopt || nc "${1%:*}" "${1#*}" ;;
*) $dopt && echo nc "$1" 22 ;
$nopt || nc "$1" 22 ;;
esac
else
# If the IP is not local, run a command.
shift
$*
fi