summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2021-10-09 05:05:23 -0400
committerAndrew Cady <d@jerkface.net>2021-10-09 05:05:23 -0400
commit00dfe043a4f6a58a81e3e00738f30a97819b2176 (patch)
treecb64fbc39263e123f714ffcc535387373d9096c2
parent1e20926763855b24f0474bdf65bf9b4a593eb731 (diff)
improve options considerably
-rwxr-xr-xconnect-vpn.sh192
1 files changed, 136 insertions, 56 deletions
diff --git a/connect-vpn.sh b/connect-vpn.sh
index 6292979..5e95558 100755
--- a/connect-vpn.sh
+++ b/connect-vpn.sh
@@ -1,5 +1,6 @@
1#!/bin/bash 1#!/bin/bash
2[ "$UID" = 0 ] || exec sudo -- "$0" "$@" || exit 2set -e
3[ "$UID" = 0 ] || exec sudo -- "$0" "$@"
3 4
4help() 5help()
5{ 6{
@@ -10,9 +11,7 @@ help()
10 11
11Synopsis: 12Synopsis:
12 13
13$prefix0 <hostname>.<keystring>.<keytype>.cryptonomic.net 14$prefix0 <hostname>
14
15Synopsis:
16 15
17$prefix0 --remote-ip <IP address> \\ 16$prefix0 --remote-ip <IP address> \\
18$prefix1 --remote-name <hostname> 17$prefix1 --remote-name <hostname>
@@ -28,74 +27,159 @@ $prefix1 [--local-key <filename>]
28 27
29Options: 28Options:
30 29
31 --remote-ip
32 --remote-name 30 --remote-name
33 31
34 Remote IP and NAME are MANDATORY. 32 Specify the name that we give to the remote side.
33
34 Remote name is mandatory, except that if a single non-option argument is
35 given, then it is treated as if it were the argument to --remote-name.
36
37 --remote-ip
35 38
36 --remote-key 39 The IP specifies an IP to connect to.
37 40
38 Remote key, if specified, must be 'rsa'. 41 The name specifies a name we give to the remote side.
42
43 If not specified, the hostname specified with the --remote-name option
44 will be resolved to obtain the IP.
45
46 --remote-key-type
47
48 The remote key will be fetched via the SSH protocol on port 22 on the
49 remote IP. This option specifies which server key type to request from
50 the server.
51
52 If specified, it must be 'rsa'.
39 53
40 --local-key 54 --local-key
41 55
42 The specified key must be an RSA key. 56 This specifies the location of the private key file.
43 57
44 The filename is considered relative to /etc/ssh if it has no slashes. 58 The filename is considered relative to /etc/ssh if it has no slashes.
45 59
46 The default is 'ssh_host_rsa_key'. 60 The default is 'ssh_host_rsa_key'.
47 61
62 The key must be an RSA key.
63
48EOF 64EOF
49} 65}
50die() { printf 'Error: %s\n' "$*"; exit 1; }
51 66
52REMOTE_IP=68.48.18.140 67
53REMOTE_NAME=andy 68# Default command line argument values.
69NO_ACT=y
54REMOTE_KEY_TYPE=rsa 70REMOTE_KEY_TYPE=rsa
55LOCAL_KEY=ssh_host_rsa_key 71LOCAL_KEY=ssh_host_rsa_key
56 72
73# Hard-coded private key source and destinations.
57LOCAL_KEY_DEST_BASENAME=ssh_host_rsa_key 74LOCAL_KEY_DEST_BASENAME=ssh_host_rsa_key
58LOCAL_PRIVATE_KEY_DEST=/etc/swanctl/private/$LOCAL_KEY_DEST_BASENAME 75LOCAL_PRIVATE_KEY_DEST=/etc/swanctl/private/$LOCAL_KEY_DEST_BASENAME
59LOCAL_PUBLIC_KEY_DEST=/etc/swanctl/pubkey/$LOCAL_KEY_DEST_BASENAME.pub 76LOCAL_PUBLIC_KEY_DEST=/etc/swanctl/pubkey/$LOCAL_KEY_DEST_BASENAME.pub
60 77
61OPTS=$(getopt \ 78die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
62 --options 'h' \ 79warn() { printf 'Warning: %s\n' "$*" >&2; }
63 --longoptions 'help,remote-ip:,remote-name:,remote-key-type:,local-key:' \ 80
64 -n connect-vpn \ 81parse_options()
65 -- "$@") 82{
66eval set -- "$OPTS" 83 OPTS=$(getopt \
67unset OPTS 84 --options 'hynf' \
68 85 --longoptions 'help,yes-act,no-act,remote-ip:,remote-name:,remote-key-type:,local-key:' \
69while true 86 -n connect-vpn \
70do 87 -- "$@")
71 case "$1" in 88 eval set -- "$OPTS"
72 -h|--help) help; exit;; 89 unset OPTS
73 --remote-ip) REMOTE_IP=$2; shift 2;; 90
74 --remote-name) REMOTE_NAME=$2; shift 2;; 91 while true
75 --remote-key-type) REMOTE_KEY_TYPE=$2; shift 2;; 92 do
76 --local-key) LOCAL_KEY=$2; shift 2;; 93 case "$1" in
77 --) shift; break;; 94 -h | --help ) help; exit;;
95 -y | --yes-act ) NO_ACT=;;
96 -n | --no-act ) NO_ACT=y;;
97 --remote-ip ) shift; REMOTE_IP=$1;;
98 --remote-name ) shift; REMOTE_NAME=$1;;
99 --remote-key-type ) shift; REMOTE_KEY_TYPE=$1;;
100 --local-key ) shift; LOCAL_KEY=$1;;
101 -- ) shift; break;;
102 esac
103 shift
104 done
105
106 case "$# $1" in
107 1\ *.*.*.cryptonomic.net) CRYPTONOMIC_DOMAIN=$1; shift ;;
108 1\ *) REMOTE_NAME=$1; shift ;;
78 esac 109 esac
79 shift
80done
81 110
82if [ $# != 0 ] 111 if [ "$CRYPTONOMIC_DOMAIN" ]
83then 112 then
84 help 113 REMOTE_NAME=${CRYPTONOMIC_DOMAIN%%.*}
85 exit 1 114 [ "$REMOTE_IP" ] || REMOTE_IP=$(resolve_domain_name "$REMOTE_NAME")
86fi 115
116 elif [ $# != 0 ]
117 then
118 help
119 exit 1
120 fi
121
122 # The validation functions modify the values to normalize them.
123 validate_remote_ip || die 'invalid remote ip'
124 validate_remote_name || die "invalid remote name '$REMOTE_NAME'"
125 validate_remote_key_type || die 'invalid remote key type'
126 validate_local_key || die 'invalid local key'
127}
128
129resolve_domain_name()
130{
131 normalize_address "$@"
132}
87 133
88[ "$REMOTE_IP" ] || die 'remote ip' # todo parse IP 134normalize_address()
89[ "$REMOTE_NAME" ] || die 'remote name' # todo parse valid hostname 135{
90[ "$REMOTE_KEY_TYPE" = rsa ] 136 local IP
137 [ "$1" ] || return
138 IP=$(getent ahosts "$1")
139 IP=${IP%% *}
140 [ "$IP" ] || return
141 echo "$IP"
142}
91 143
92case "$LOCAL_KEY" in 144validate_remote_ip()
93 */*) ;; 145{
94 *) LOCAL_KEY=/etc/ssh/$LOCAL_KEY ;; 146 REMOTE_IP=$(normalize_address "${REMOTE_IP:-$REMOTE_NAME}")
95esac 147}
96 148
97[ -f "$LOCAL_KEY" -a -r "$LOCAL_KEY" ] || die "local key ($LOCAL_KEY)" 149validate_remote_name()
150{
151 domain_name_regexp='^[[:alpha:]][-.[:alnum:]]*[[:alnum:]]*$'
152 [[ $REMOTE_NAME =~ $domain_name_regexp ]]
153}
98 154
155validate_remote_key_type()
156{
157 [ "$REMOTE_KEY_TYPE" = rsa ]
158}
159
160validate_local_key()
161{
162 # TODO: check that it is RSA
163 case "$LOCAL_KEY" in
164 */*) ;;
165 *) LOCAL_KEY=/etc/ssh/$LOCAL_KEY ;;
166 esac
167 [ -f "$LOCAL_KEY" -a -r "$LOCAL_KEY" ] || die "local key ($LOCAL_KEY)"
168}
169
170main()
171{
172 parse_options "$@"
173 if [ "$NO_ACT" ]
174 then
175 exec 2>&1
176 keycopy
177 test_new_config
178 else
179 die unimplemented
180 fi
181 exit
182}
99 183
100match_and_drop_first_word() 184match_and_drop_first_word()
101{ 185{
@@ -211,9 +295,10 @@ nocomments()
211 295
212config() 296config()
213{ 297{
214 local conn="$1" remote_addrs="$2" id="$3" 298 local conn="$1" remote_addrs="$2" local_key="$3"
215 local public_key_file="$4" private_key_file="$5" 299 local public_key_file="$4" private_key_file="$5"
216 local remote_ts=0::0/0 vips=:: 300 local remote_ts=0::0/0 vips=::
301 id=$(key_to_suffix "$local_key") || return
217 sed -e 's/^ //' <<END 302 sed -e 's/^ //' <<END
218 connections { 303 connections {
219 ${conn} { 304 ${conn} {
@@ -251,11 +336,10 @@ get_my_mac()
251 [ "$my_mac" ] 336 [ "$my_mac" ]
252} 337}
253 338
254crypto_get_my_mac() 339key_to_suffix()
255{ 340{
256 my_mac=$(ssh-keygen -r . -f "$LOCAL_KEY" | 341 local keytype=1 hashtype=2
257 sed -E -ne 's/^[^ ]+ IN SSHFP [^ ]+ 2 .{48}(.{4})(.{4})(.{4})(.{4})$/\1:\2:\3:\4/p') 342 ssh-keygen -r . -f "$1" | sed -E -ne 's/^. IN SSHFP '"$keytype $hashtype"' .{48}(.{4})(.{4})(.{4})(.{4})$/\1:\2:\3:\4/p'
258 [ "$my_mac" ]
259} 343}
260 344
261NO_ACT() 345NO_ACT()
@@ -265,12 +349,11 @@ NO_ACT()
265 349
266write_config() 350write_config()
267{ 351{
268 crypto_get_my_mac "$REMOTE_IP" || return
269 write_successfully /etc/swanctl/conf.d/"$REMOTE_NAME".conf -- \ 352 write_successfully /etc/swanctl/conf.d/"$REMOTE_NAME".conf -- \
270 config \ 353 config \
271 "$REMOTE_NAME" \ 354 "$REMOTE_NAME" \
272 "$REMOTE_IP" \ 355 "$REMOTE_IP" \
273 "$my_mac" \ 356 "$LOCAL_KEY" \
274 "$LOCAL_PUBLIC_KEY_DEST" \ 357 "$LOCAL_PUBLIC_KEY_DEST" \
275 "$LOCAL_PRIVATE_KEY_DEST" 358 "$LOCAL_PRIVATE_KEY_DEST"
276} 359}
@@ -288,8 +371,5 @@ test_new_config()
288 NO_ACT ipsec up "${REMOTE_NAME}" 371 NO_ACT ipsec up "${REMOTE_NAME}"
289} 372}
290 373
291NO_ACT=y 374main "$@"
292exec 2>&1 375
293set -e
294keycopy
295test_new_config