Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- #DEBUG=; set -x # comment/uncomment to disable/enable debug mode
- # name: importvpncl.sh
- # version: 0.6.1 beta, 15-sep-2024, by eibgrad and egc
- # changes: added tls-crypt-v2
- # purpose: configure openvpn client from imported config file
- # script type: standalone
- # 1. enable jffs2 (administration->jffs2)
- # 2. use shell (telnet/ssh) to execute one of the following commands:
- # curl -kLs bit.ly/ddwrt-installer|tr -d '\r'|sh -s 2gg5ZdRY
- # or
- # wget -qO - bit.ly/ddwrt-installer|tr -d '\r'|sh -s 2gg5ZdRY
- # limitations:
- # - requires dd-wrt build 49838 or later
- LOG="$([ ${DEBUG+x} ] && \
- echo /tmp/$(basename $0 .${0##*.})_$(date +'%Y-%m-%d-%H%M%S')_$$.log || \
- echo /dev/null)"
- # function usage()
- usage() {
- echo 'Usage: importvpncl.sh [options] [config-file]'
- echo
- echo ' Configure OpenVPN client from imported config file.'
- echo
- echo ' Options:'
- echo ' --nocommit do NOT issue nvram commit after changes'
- echo ' -h,--help this usage information'
- echo
- echo ' # e.g., configure from specified config file'
- echo ' importvpncl.sh /tmp/vpnupload.conf'
- echo
- echo ' # e.g., configure from default config file (/tmp/vpnupload.conf)'
- echo ' importvpncl.sh'
- echo
- echo ' # e.g., reset openvpn client to defaults'
- echo ' importvpncl.sh /dev/null'
- echo
- }
- # handle help/usage requests
- for opt; do case $opt in -h|--help) usage; exit 0;; esac; done
- # process command line options/arguments
- while [ $# -gt 0 ]; do
- case $1 in
- '--nocommit') nocommit=;;
- *) if echo "$1" | grep -q '^-'; then
- echo "error: unknown option: $1"; exit 1
- else
- break 2
- fi;;
- esac
- shift
- done
- {
- # -------------------------- BEGIN GLOBAL CONSTANTS -------------------------- #
- # openvpn client-specific nvram variables and default values
- # generated by: nvram show 2>/dev/null | grep -E '^openvpncl_[^=]*=' | sort
- VAR_LIST='
- openvpncl_adv=0
- openvpncl_auth=none
- openvpncl_blockmulticast=0
- openvpncl_bridge=0
- openvpncl_ca=
- openvpncl_certtype=0
- openvpncl_cipher=
- openvpncl_client=
- openvpncl_config=
- openvpncl_dc1=CHACHA20-POLY1305
- openvpncl_dc2=AES-128-GCM
- openvpncl_dc3=AES-256-GCM
- openvpncl_enable=0
- openvpncl_fragment=
- openvpncl_fw=1
- openvpncl_ip=
- openvpncl_key=
- openvpncl_killswitch=0
- openvpncl_lzo=off
- openvpncl_mask=
- openvpncl_mit=1
- openvpncl_mssfix=0
- openvpncl_mtu=1400
- openvpncl_multirem=0
- openvpncl_nat=1
- openvpncl_pkcs12=
- openvpncl_proto=udp4
- openvpncl_randomsrv=0
- openvpncl_remoteip=0.0.0.0
- openvpncl_remoteport=1194
- openvpncl_route=
- openvpncl_scramble=off
- openvpncl_scrmblpw=o54a72ReutDK
- openvpncl_spbr=0
- openvpncl_splitdns=0
- openvpncl_tls_btn=3
- openvpncl_tlsauth=
- openvpncl_tlscip=0
- openvpncl_tuntap=tun
- openvpncl_upauth=0
- openvpncl_wdog=0
- openvpncl_wdog_pingip=8.8.8.8
- openvpncl_wdog_sleept=30
- '
- # dynamically generated nvram variables (deleted on reset)
- UNVAR_LIST='
- openvpncl_pass
- openvpncl_remoteip2
- openvpncl_remoteip3
- openvpncl_remoteip4
- openvpncl_remoteip5
- openvpncl_remoteport2
- openvpncl_remoteport3
- openvpncl_remoteport4
- openvpncl_remoteport5
- openvpncl_static
- openvpncl_user
- '
- PROTOCOL_LIST='udp udp4 udp6 tcp tcp4 tcp6 tcp-client tcp4-client tcp6-client'
- CIPHER_LIST='
- CHACHA20-POLY1305
- AES-256-GCM
- AES-192-GCM
- AES-128-GCM
- AES-256-CBC
- AES-192-CBC
- AES-128-CBC
- '
- AUTH_LIST='sha512 sha256 sha1 md5 md4 none'
- COMP_LZO_LIST='yes adaptive no'
- COMPRESS_LIST='lz4 lz4-v2'
- # handled directives (all others are ignored)
- HANDLED_DIR_LIST='
- <ca>
- <cert>
- <key>
- <pkcs12>
- <secret>
- <tls-auth>
- <tls-crypt>
- <tls-crypt-v2>
- <auth-user-pass>
- auth
- auth-user-pass
- cipher
- comp-lzo
- compress
- data-ciphers
- dev
- fragment
- key-direction
- mmsfix
- ncp-ciphers
- ns-cert-type
- pkcs12
- port
- proto
- remote
- remote-cert-tls
- tls-auth
- tls-crypt
- tls-crypt-v2
- verify-x509-name
- '
- # data cipher fields supported by gui
- DC_FIELDS='1 2 3'
- # maximum number of remote directives supported by gui
- MAX_REMOTES=5
- # temp file for additional config
- ADDN_CONFIG="/tmp/$(basename $0 .${0##*.}).$$.tmp"
- # --------------------------- END GLOBAL CONSTANTS --------------------------- #
- # -------------------------- BEGIN GLOBAL VARIABLES -------------------------- #
- # track number of remote directives added to gui
- total_remotes=0
- # default port (updated w/ port directive if present)
- default_port='1194'
- # default protocol (updated w/ proto directive if present)
- default_proto='udp4'
- # --------------------------- END GLOBAL VARIABLES --------------------------- #
- # ----------------------------- BEGIN UTILITIES ------------------------------ #
- # function to_lower( string [string ...] )
- to_lower() { echo "$@" | awk '{print tolower($0)}'; }
- # function to_upper( string [string ...] )
- to_upper() { echo "$@" | awk '{print toupper($0)}'; }
- # function get_field( num )
- get_field() { echo $line | awk "{print \$$1}"; }
- # function get_textblock( directive )
- get_textblock() {
- sed -ne "/<$1>/,/<\/$1/{/<$1>/!{/<\/$1>/!p;};}" "$CONFIG_FILE" | \
- sed -r '/^[[:space:]]*(#|;|$)/d'
- }
- # function steer_protocol( protocol )
- steer_protocol() {
- echo "$1" | \
- # steer udp/tcp/tcp-client to udp4/tcp4/tcp4-client
- sed -r 's/^(udp|tcp)$/\14/;s/^tcp-/tcp4-/' |
- # convert tcp/tcp4/tcp6 to tcp-client/tcp4-client/tcp6-client
- sed -r 's/^(tcp(|4|6))$/\1-client/'
- }
- # function write_addn_config( [string ...] )
- write_addn_config() {
- { [ "$@" ] && echo "$@" || echo "$line"; } >> $ADDN_CONFIG
- }
- # function reset_nvram()
- reset_nvram() {
- local i
- # reset static nvram variables to their default values
- for i in $VAR_LIST; do nvram set "$i"; done
- # remove dynamically generated nvram variables
- for i in $UNVAR_LIST; do nvram unset "$i"; done
- # commit changes
- [ ${nocommit+x} ] || nvram commit &>/dev/null
- }
- # ------------------------------ END UTILITIES ------------------------------- #
- # ------------------------------ BEGIN HANDLERS ------------------------------ #
- # function handle_auth()
- handle_auth() {
- local auth="$(to_lower $(get_field 2))"
- [ "$auth" ] || return
- # only update on exact match
- if echo $AUTH_LIST | grep -q "\\b$auth\\b"; then
- nvram set openvpncl_auth="$auth"
- else
- write_addn_config
- fi
- }
- # function handle_auth_user_pass()
- handle_auth_user_pass() {
- if [ "$(get_field 2)" ]; then
- write_addn_config
- else
- nvram set openvpncl_upauth='1'
- fi
- }
- # function handle_cipher()
- handle_cipher() {
- local i cipher="$(to_upper $(get_field 2))"
- [ "$cipher" ] || return
- # check for disabled cipher
- if [ "$cipher" == 'NONE' ]; then
- nvram set openvpncl_cipher='none'
- nvram set openvpncl_dc1='none'
- # only update on exact match
- elif echo $CIPHER_LIST | grep -q "\\b$cipher\\b"; then
- nvram set openvpncl_cipher="$cipher"
- nvram set openvpncl_dc1="$cipher"
- else
- write_addn_config
- fi
- }
- # function handle_comp_lzo()
- handle_comp_lzo() {
- local comp_lzo="$(to_lower $(get_field 2))"
- # unspecified type means default (adaptive)
- if [ ! "$comp_lzo" ]; then
- nvram set openvpncl_lzo='adaptive'
- # else only update on exact match
- elif echo $COMP_LZO_LIST | grep -q "\\b$comp_lzo\\b"; then
- nvram set openvpncl_lzo="$comp_lzo"
- else
- write_addn_config
- fi
- }
- # function handle_compress()
- handle_compress() {
- local compress="$(to_lower $(get_field 2))"
- # unspecified type means compression is off, but packet framing is
- # still enabled allowing a different setting to be pushed later
- if [ ! "$compress" ]; then
- nvram set openvpncl_lzo='compress'
- # else only update on exact match
- elif echo $COMPRESS_LIST | grep -q "\\b$compress\\b"; then
- nvram set openvpncl_lzo="compress $compress"
- else
- write_addn_config
- fi
- }
- # function handle_data_ciphers()
- handle_data_ciphers() {
- local i cipher cipher_found
- local ciphers="$(to_upper $(get_field 2 | tr ':' ' '))"
- [ "$ciphers" ] || return
- # check for disabled data ciphers
- [ "$ciphers" == 'NONE' ] && { nvram set openvpncl_dc1='none'; return; }
- # update individual data cipher fields
- for i in $DC_FIELDS; do
- for cipher in $ciphers; do
- # only update on exact match
- if echo $CIPHER_LIST | grep -q "\\b$cipher\\b"; then
- nvram set openvpncl_dc${i}="$cipher"
- # eliminate this cipher from further consideration
- ciphers="$(echo $ciphers | sed s/\\b$cipher\\b//g)"
- cipher_found=
- continue 2
- fi
- done
- # if we never found a match, there's no point continuing
- break
- done
- [ ${cipher_found+x} ] || write_addn_config
- }
- # function handle_dev()
- handle_dev() {
- local dev="$(to_lower $(get_field 2))"
- if [ "${dev:0:3}" == 'tun' ]; then
- nvram set openvpncl_tuntap='tun'
- elif [ "${dev:0:3}" == 'tap' ]; then
- nvram set openvpncl_tuntap='tap'
- # bridge tunnel (tap) to private network (br0)
- nvram set openvpncl_bridge='1'
- # disable nat
- nvram set openvpncl_nat='0'
- fi
- }
- # function handle_fragment()
- handle_fragment() { nvram set openvpncl_fragment="$(get_field 2)"; }
- # function handle_key_direction()
- handle_key_direction() {
- local key_direction="$(get_field 2)"
- [ "$key_direction" ] || return
- # key direction default is 1; only need directive if something else
- [ "$key_direction" != '1' ] && write_addn_config
- }
- # function handle_mssfix()
- handle_mssfix() { nvram set openvpncl_mssfix='1'; }
- # function handle_ncp_ciphers()
- handle_ncp_ciphers() { [ "$(get_field 2)" ] && write_addn_config; }
- # function handle_ns_cert_type()
- handle_ns_cert_type() { handle_remote_cert_tls; }
- # function handle_pkcs12()
- handle_pkcs12() { [ "$(get_field 2)" ] && write_addn_config; }
- # function handle_port()
- handle_port() { [ "$(get_field 2)" ] && default_port="$(get_field 2)"; }
- # function handle_proto()
- handle_proto() {
- local proto="$(to_lower $(get_field 2))"
- [ "$proto" ] || return
- # only update on exact match
- if echo $PROTOCOL_LIST | grep -q "\\b$proto\\b"; then
- default_proto="$(steer_protocol $proto)"
- else
- write_addn_config
- fi
- }
- # function handle_remote()
- handle_remote() {
- local ip="$(get_field 2)"
- local port="$(get_field 3)"
- local proto="$(to_lower $(get_field 4))"
- [ "$ip" ] || return
- [ "$port" ] || port="$default_port"
- [ "$proto" ] || proto="$default_proto"
- proto="$(steer_protocol $proto)"
- if [ $((total_remotes)) -lt $MAX_REMOTES ]; then
- if [ $total_remotes -eq 0 ]; then
- let $total_remotes++
- nvram set openvpncl_remoteip="$ip"
- nvram set openvpncl_remoteport="$port"
- nvram set openvpncl_proto="$proto"
- elif [ "$proto" == "$(nvram get openvpncl_proto)" ]; then
- let total_remotes++
- nvram set openvpncl_remoteip${total_remotes}="$ip"
- nvram set openvpncl_remoteport${total_remotes}="$port"
- nvram set openvpncl_multirem='1'
- nvram set openvpncl_randomsrv='1'
- fi
- elif [ "$proto" == "$(nvram get openvpncl_proto)" ]; then
- write_addn_config \
- "$(echo remote $ip $port $proto | sed 's/[[:space:]]*$//g')"
- fi
- }
- # function handle_remote_cert_tls()
- handle_remote_cert_tls() {
- if [ "$(to_lower $(get_field 2))" == 'server' ]; then
- nvram set openvpncl_certtype='1'
- fi
- }
- # function handle_tls_auth()
- handle_tls_auth() { [ "$(get_field 2)" ] && write_addn_config; }
- # function handle_tls_crypt()
- handle_tls_crypt() { [ "$(get_field 2)" ] && write_addn_config; }
- # function handle_tls_crypt_v2()
- handle_tls_crypt_v2() { [ "$(get_field 2)" ] && write_addn_config; }
- # function handle_verify_x509_name()
- handle_verify_x509_name() { [ "$(get_field 2)" ] && write_addn_config; }
- # ------------------------------- END HANDLERS ------------------------------- #
- # ----------------------- BEGIN PROCESSING CONFIG FILE ----------------------- #
- # if no user-provided config file, assume default
- [ "$1" ] && CONFIG_FILE="$1" || CONFIG_FILE='/tmp/vpnupload.conf'
- if [[ "$CONFIG_FILE" != '/dev/null' && ! -f "$CONFIG_FILE" ]]; then
- echo "error: file not found: $CONFIG_FILE"
- exit 1
- fi
- # reset nvram variables to defaults
- reset_nvram
- # no need to go any further if config file is empty
- [ -s "$CONFIG_FILE" ] || exit 0
- # convert config file from dos to linux file format (as necessary)
- grep -q '\r' "$CONFIG_FILE" && sed -i 's/\r//g' "$CONFIG_FILE"
- # enable openvpn client
- nvram set openvpncl_enable='1'
- # reconfigure openvpn client defaults to comply w/ openvpn defaults
- nvram set openvpncl_auth=
- for i in $DC_FIELDS; do nvram set openvpncl_dc${i}=; done
- # identify handled directives from config file
- lines="$(sed -rn \
- "s/^(|--)(($(echo $HANDLED_DIR_LIST | tr ' ' '|'))([[:space:]].*|$))/\2/p" \
- "$CONFIG_FILE")"
- OIFS="$IFS"; IFS=$'\n'
- for line in $lines; do
- IFS="$OIFS"
- # isolate directive from arguments (if any)
- dir="${line%%[[:space:]]*}"
- # these directive *must* be processed first!
- case $dir in 'cipher'|'port'|'proto') handle_${dir//-/_};; esac
- IFS=$'\n'
- done
- for line in $lines; do
- IFS="$OIFS"
- # isolate directive from arguments (if any)
- dir="${line%%[[:space:]]*}"
- case $dir in
- # ignore previously processed directives
- 'cipher'|'port'|'proto') ;;
- # handle multi-line directives
- '<ca>') nvram set openvpncl_ca="$(get_textblock ca)";;
- '<cert>') nvram set openvpncl_client="$(get_textblock cert)";;
- '<key>') nvram set openvpncl_key="$(get_textblock key)";;
- '<pkcs12>') nvram set openvpncl_pkcs12="$(get_textblock pkcs12)";;
- '<secret>') nvram set openvpncl_static="$(get_textblock secret)"
- nvram set openvpncl_tls_btn='2';;
- '<tls-auth>') nvram set openvpncl_tlsauth="$(get_textblock tls-auth)"
- nvram set openvpncl_tls_btn='0';;
- '<tls-crypt>') nvram set openvpncl_tlsauth="$(get_textblock tls-crypt)"
- nvram set openvpncl_tls_btn='1';;
- '<tls-crypt-v2>') nvram set openvpncl_tlsauth="$(get_textblock tls-crypt-v2)"
- nvram set openvpncl_tls_btn='4';;
- '<auth-user-pass>') up="$(get_textblock auth-user-pass)"
- nvram set openvpncl_user=$(echo -e "$up" | awk 'NR==1{print $1}')
- nvram set openvpncl_pass=$(echo -e "$up" | awk 'NR==2{print $1}')
- nvram set openvpncl_upauth='1';;
- # handle single-line directives
- *) handle_${dir//-/_};;
- esac
- IFS=$'\n'
- done
- IFS="$OIFS"
- # ignore ipv6 pushed routes when using ipv4 protocols
- if echo "$(nvram get openvpncl_proto)" | grep -Eq '^(udp|tcp)4'; then
- write_addn_config 'pull-filter ignore ifconfig-ipv6'
- write_addn_config 'pull-filter ignore route-ipv6'
- write_addn_config 'block-ipv6'
- fi
- # save additional config (if any)
- [ -s $ADDN_CONFIG ] && nvram set openvpncl_config="$(cat $ADDN_CONFIG)"
- # commit changes
- [ ${nocommit+x} ] || nvram commit &>/dev/null
- # cleanup
- rm -f $ADDN_CONFIG
- # ------------------------ END PROCESSING CONFIG FILE ------------------------ #
- # debug: dump config file and updated nvram variables for review
- if [ ${DEBUG+x} ]; then
- set +x
- echo '<input>'
- cat "$CONFIG_FILE"
- echo '</input>'
- echo '<output>'
- nvram show 2>/dev/null | grep -E '^openvpncl_[^=]*=' | sort
- echo '</output>'
- set -x
- fi
- exit 0
- } &>$LOG
Add Comment
Please, Sign In to add comment