From 00dfe043a4f6a58a81e3e00738f30a97819b2176 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 9 Oct 2021 05:05:23 -0400 Subject: improve options considerably --- connect-vpn.sh | 192 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file 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 @@ #!/bin/bash -[ "$UID" = 0 ] || exec sudo -- "$0" "$@" || exit +set -e +[ "$UID" = 0 ] || exec sudo -- "$0" "$@" help() { @@ -10,9 +11,7 @@ help() Synopsis: -$prefix0 ...cryptonomic.net - -Synopsis: +$prefix0 $prefix0 --remote-ip \\ $prefix1 --remote-name @@ -28,74 +27,159 @@ $prefix1 [--local-key ] Options: - --remote-ip --remote-name - Remote IP and NAME are MANDATORY. + Specify the name that we give to the remote side. + + Remote name is mandatory, except that if a single non-option argument is + given, then it is treated as if it were the argument to --remote-name. + + --remote-ip - --remote-key + The IP specifies an IP to connect to. - Remote key, if specified, must be 'rsa'. + The name specifies a name we give to the remote side. + + If not specified, the hostname specified with the --remote-name option + will be resolved to obtain the IP. + + --remote-key-type + + The remote key will be fetched via the SSH protocol on port 22 on the + remote IP. This option specifies which server key type to request from + the server. + + If specified, it must be 'rsa'. --local-key - The specified key must be an RSA key. + This specifies the location of the private key file. The filename is considered relative to /etc/ssh if it has no slashes. The default is 'ssh_host_rsa_key'. + The key must be an RSA key. + EOF } -die() { printf 'Error: %s\n' "$*"; exit 1; } -REMOTE_IP=68.48.18.140 -REMOTE_NAME=andy + +# Default command line argument values. +NO_ACT=y REMOTE_KEY_TYPE=rsa LOCAL_KEY=ssh_host_rsa_key +# Hard-coded private key source and destinations. LOCAL_KEY_DEST_BASENAME=ssh_host_rsa_key LOCAL_PRIVATE_KEY_DEST=/etc/swanctl/private/$LOCAL_KEY_DEST_BASENAME LOCAL_PUBLIC_KEY_DEST=/etc/swanctl/pubkey/$LOCAL_KEY_DEST_BASENAME.pub -OPTS=$(getopt \ - --options 'h' \ - --longoptions 'help,remote-ip:,remote-name:,remote-key-type:,local-key:' \ - -n connect-vpn \ - -- "$@") -eval set -- "$OPTS" -unset OPTS - -while true -do - case "$1" in - -h|--help) help; exit;; - --remote-ip) REMOTE_IP=$2; shift 2;; - --remote-name) REMOTE_NAME=$2; shift 2;; - --remote-key-type) REMOTE_KEY_TYPE=$2; shift 2;; - --local-key) LOCAL_KEY=$2; shift 2;; - --) shift; break;; +die() { printf 'Error: %s\n' "$*" >&2; exit 1; } +warn() { printf 'Warning: %s\n' "$*" >&2; } + +parse_options() +{ + OPTS=$(getopt \ + --options 'hynf' \ + --longoptions 'help,yes-act,no-act,remote-ip:,remote-name:,remote-key-type:,local-key:' \ + -n connect-vpn \ + -- "$@") + eval set -- "$OPTS" + unset OPTS + + while true + do + case "$1" in + -h | --help ) help; exit;; + -y | --yes-act ) NO_ACT=;; + -n | --no-act ) NO_ACT=y;; + --remote-ip ) shift; REMOTE_IP=$1;; + --remote-name ) shift; REMOTE_NAME=$1;; + --remote-key-type ) shift; REMOTE_KEY_TYPE=$1;; + --local-key ) shift; LOCAL_KEY=$1;; + -- ) shift; break;; + esac + shift + done + + case "$# $1" in + 1\ *.*.*.cryptonomic.net) CRYPTONOMIC_DOMAIN=$1; shift ;; + 1\ *) REMOTE_NAME=$1; shift ;; esac - shift -done -if [ $# != 0 ] -then - help - exit 1 -fi + if [ "$CRYPTONOMIC_DOMAIN" ] + then + REMOTE_NAME=${CRYPTONOMIC_DOMAIN%%.*} + [ "$REMOTE_IP" ] || REMOTE_IP=$(resolve_domain_name "$REMOTE_NAME") + + elif [ $# != 0 ] + then + help + exit 1 + fi + + # The validation functions modify the values to normalize them. + validate_remote_ip || die 'invalid remote ip' + validate_remote_name || die "invalid remote name '$REMOTE_NAME'" + validate_remote_key_type || die 'invalid remote key type' + validate_local_key || die 'invalid local key' +} + +resolve_domain_name() +{ + normalize_address "$@" +} -[ "$REMOTE_IP" ] || die 'remote ip' # todo parse IP -[ "$REMOTE_NAME" ] || die 'remote name' # todo parse valid hostname -[ "$REMOTE_KEY_TYPE" = rsa ] +normalize_address() +{ + local IP + [ "$1" ] || return + IP=$(getent ahosts "$1") + IP=${IP%% *} + [ "$IP" ] || return + echo "$IP" +} -case "$LOCAL_KEY" in - */*) ;; - *) LOCAL_KEY=/etc/ssh/$LOCAL_KEY ;; -esac +validate_remote_ip() +{ + REMOTE_IP=$(normalize_address "${REMOTE_IP:-$REMOTE_NAME}") +} -[ -f "$LOCAL_KEY" -a -r "$LOCAL_KEY" ] || die "local key ($LOCAL_KEY)" +validate_remote_name() +{ + domain_name_regexp='^[[:alpha:]][-.[:alnum:]]*[[:alnum:]]*$' + [[ $REMOTE_NAME =~ $domain_name_regexp ]] +} +validate_remote_key_type() +{ + [ "$REMOTE_KEY_TYPE" = rsa ] +} + +validate_local_key() +{ + # TODO: check that it is RSA + case "$LOCAL_KEY" in + */*) ;; + *) LOCAL_KEY=/etc/ssh/$LOCAL_KEY ;; + esac + [ -f "$LOCAL_KEY" -a -r "$LOCAL_KEY" ] || die "local key ($LOCAL_KEY)" +} + +main() +{ + parse_options "$@" + if [ "$NO_ACT" ] + then + exec 2>&1 + keycopy + test_new_config + else + die unimplemented + fi + exit +} match_and_drop_first_word() { @@ -211,9 +295,10 @@ nocomments() config() { - local conn="$1" remote_addrs="$2" id="$3" + local conn="$1" remote_addrs="$2" local_key="$3" local public_key_file="$4" private_key_file="$5" local remote_ts=0::0/0 vips=:: + id=$(key_to_suffix "$local_key") || return sed -e 's/^ //' <&1 -set -e -keycopy -test_new_config +main "$@" + -- cgit v1.2.3