diff --git a/NEWS.md b/NEWS.md index 991740d..e95ae2b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,30 @@ ucsf-vpn ======== +## Version 6.1.0 (2024-06-26) + +### Significant changes + + * Now `ucsf vpn` validates the VPN connection using a UCSF IT web + service hosted under `*.ucsf.edu`. Previously + was the default method. Note that `ucsf vpn + details` still uses ipinfo.io. + +### New Features + + * Now `ucsf vpn start --flavor=none` sets the default flavor. This + can be used to override environment variable `UCSF_VPN_FLAVOR`, + which may be preset in for instance `~/.config/ucsf-vpn/envs`. + + * Now `ucsf vpn routing` reports also on nameserver settings. + + * Now `ucsf vpn start --debug` and `ucsf vpn stop --debug` reports on + changes to your nameserver settings (`/etc/resolv.conf`). + + * Add support for `ucsf vpn status --validate=ucsfit`, which infers + VPN status from . + + ## Version 6.0.0 (2024-05-20) ### Significant changes diff --git a/README.md b/README.md index d29490c..5221642 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ WARNING: This action ('ucsf-vpn start') requires administrative ("sudo") rights. Enter the password for your account ('alice84') on your local computer ('alice-laptop'): Enter your UCSF Active Directory password: Enter 'push' (default), 'phone', 'sms', a 6 or 7 digit Duo token, or press your YubiKey: -OK: OpenConnect status: 'openconnect' process running (started 00h00m01s ago on 2024-05-13T09:05:20-07:00; PID=14549) +OK: OpenConnect status: 'openconnect' process running (started 00h00m01s ago on 2024-06-25T09:05:20-07:00; PID=14549) OK: IP routing tunnels: [n=1] tun0 -OK: Public IP information: ip=128.218.43.42, hostname=, org=AS5653 University of California San Francisco +OK: Public IP information (UCSF IT): public_ip=10.49.88.54, network='UCSF Network - Private Space' OK: Flavor: default OK: Connected to the VPN ``` @@ -47,7 +47,7 @@ To disconnect from the UCSF VPN, call: $ ucsf-vpn stop OK: OpenConnect status: No 'openconnect' process running OK: IP routing tunnels: none -OK: Public IP information: ip=123.145.254.42, hostname=123.145.254.42.fiber.dynamic.sonic.net, org=AS46375 Sonic Telecom LLC +OK: Public IP information (UCSF IT): public_ip=123.145.254.42, network='not UCSF' OK: Not connected to the VPN ``` @@ -58,9 +58,9 @@ To check whether you are connected to the UCSF VPN or not, call: ```sh $ ucsf-vpn status -OpenConnect status: 'openconnect' process running (started 08h31m27s ago on 2024-05-13T16:20:00-07:00; PID=17419) +OpenConnect status: 'openconnect' process running (started 08h31m27s ago on 2024-06-25T16:20:00-07:00; PID=17419) IP routing tunnels: [n=1] tun0 -Public IP information: ip=128.218.43.42, hostname=, org=AS5653 University of California San Francisco +OK: Public IP information (UCSF IT): public_ip=10.49.88.54, network='UCSF Network - Private Space' Flavor: default Connected to the VPN ``` @@ -70,7 +70,7 @@ To get full details of your current internet connection in JSON format, call: ```sh $ ucsf-vpn details { - "ip": "128.218.43.42", + "ip": "10.49.88.54", "city": "San Francisco", "region": "California", "country": "US", @@ -130,10 +130,10 @@ Options: --realm= VPN realm (default is 'Dual-Factor Pulse Clients') --url= VPN URL (default is https://{{server}}/pulse) --protocol= VPN protocol, e.g. 'nc' (default) and 'pulse' - --validate= One or more of 'ipinfo', 'iproute', and 'pid', e.g. - 'pid,iproute,ipinfo' (default) + --validate= One or more of 'ipinfo', 'iproute', 'pid', 'ucsfit', + e.g. 'pid,iproute,ucsfit' (default) --theme= Either 'cli' (default) or 'none' - --flavor= Use a customized flavor of the VPN + --flavor= Use a customized flavor of the VPN (default: 'none') Flags: --verbose More verbose output @@ -204,7 +204,7 @@ Useful resources: * UCSF Managing Your Passwords: - https://it.ucsf.edu/services/managing-your-passwords -Version: 6.0.0 +Version: 6.1.0 Copyright: Henrik Bengtsson (2016-2024) License: GPL (>= 2.1) [https://www.gnu.org/licenses/gpl.html] Source: https://github.com/HenrikBengtsson/ucsf-vpn @@ -221,7 +221,16 @@ The `uscf-vpn` tool requires: 3. Bash 4. Admin rights (sudo) -OpenConnect (>= 7.08) is available on for instance Ubuntu 18.04 LTS (Bionic Beaver), but not on older LTS version. For instance, Ubuntu 16.04 (Xenial Xerus) only provides OpenConnect 7.06, which [fails to connect with an error](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4). [There is a confirmed way to force install this](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4) on to Ubuntu 16.04 from the Ubuntu 17.04 (Zesty) distribution, but it is not clear whether such an installation leaves the system in a stable state or not. Moreover, due to library dependencies, it appears not possible to have OpenConnect 7.08 and Pulse Secure 5.3-3 installed at the same time. +OpenConnect (>= 7.08) is available on for instance Ubuntu 18.04 LTS +(Bionic Beaver), but not on older LTS version. For instance, Ubuntu +16.04 (Xenial Xerus) only provides OpenConnect 7.06, which +[fails to connect with an error](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4). +[There is a confirmed way to force install this](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4) +on to Ubuntu 16.04 from the Ubuntu 17.04 (Zesty) distribution, but it +is not clear whether such an installation leaves the system in a +stable state or not. Moreover, due to library dependencies, it +appears not possible to have OpenConnect 7.08 and Pulse Secure 5.3-3 +installed at the same time. ## Privacy @@ -245,15 +254,15 @@ credentials. ## Building from source The self-contained `bin/ucsf-vpn` script is generated from -`src/ucsf-vpn.sh` and `src/incl/*.sh`. The rebuild `bin/ucsf-vpn`, +`src/ucsf-vpn.sh` and `src/incl/*.sh`. To rebuild `bin/ucsf-vpn`, use: ```sh $ make build ./build.sh Building bin/ucsf-vpn from src/ucsf-vpn ... --rwxrwxr-x 1 alice alice May 20 07:34 bin/ucsf-vpn -Version built: 6.0.0 +-r-xr-xr-x 1 alice alice 58584 Jun 26 09:43 bin/ucsf-vpn +Version built: 6.1.0 Building bin/ucsf-vpn from src/ucsf-vpn ... done ``` diff --git a/README.md.tmpl b/README.md.tmpl index 3f7796e..de43b8f 100644 --- a/README.md.tmpl +++ b/README.md.tmpl @@ -21,9 +21,9 @@ WARNING: This action ('ucsf-vpn start') requires administrative ("sudo") rights. Enter the password for your account ('alice84') on your local computer ('alice-laptop'): Enter your UCSF Active Directory password: Enter 'push' (default), 'phone', 'sms', a 6 or 7 digit Duo token, or press your YubiKey: -OK: OpenConnect status: 'openconnect' process running (started 00h00m01s ago on 2024-05-13T09:05:20-07:00; PID=14549) +OK: OpenConnect status: 'openconnect' process running (started 00h00m01s ago on 2024-06-25T09:05:20-07:00; PID=14549) OK: IP routing tunnels: [n=1] tun0 -OK: Public IP information: ip=128.218.43.42, hostname=, org=AS5653 University of California San Francisco +OK: Public IP information (UCSF IT): public_ip=10.49.88.54, network='UCSF Network - Private Space' OK: Flavor: default OK: Connected to the VPN ``` @@ -47,7 +47,7 @@ To disconnect from the UCSF VPN, call: $ ucsf-vpn stop OK: OpenConnect status: No 'openconnect' process running OK: IP routing tunnels: none -OK: Public IP information: ip=123.145.254.42, hostname=123.145.254.42.fiber.dynamic.sonic.net, org=AS46375 Sonic Telecom LLC +OK: Public IP information (UCSF IT): public_ip=123.145.254.42, network='not UCSF' OK: Not connected to the VPN ``` @@ -58,9 +58,9 @@ To check whether you are connected to the UCSF VPN or not, call: ```sh $ ucsf-vpn status -OpenConnect status: 'openconnect' process running (started 08h31m27s ago on 2024-05-13T16:20:00-07:00; PID=17419) +OpenConnect status: 'openconnect' process running (started 08h31m27s ago on 2024-06-25T16:20:00-07:00; PID=17419) IP routing tunnels: [n=1] tun0 -Public IP information: ip=128.218.43.42, hostname=, org=AS5653 University of California San Francisco +OK: Public IP information (UCSF IT): public_ip=10.49.88.54, network='UCSF Network - Private Space' Flavor: default Connected to the VPN ``` @@ -70,7 +70,7 @@ To get full details of your current internet connection in JSON format, call: ```sh $ ucsf-vpn details { - "ip": "128.218.43.42", + "ip": "10.49.88.54", "city": "San Francisco", "region": "California", "country": "US", @@ -112,7 +112,16 @@ The `uscf-vpn` tool requires: 3. Bash 4. Admin rights (sudo) -OpenConnect (>= 7.08) is available on for instance Ubuntu 18.04 LTS (Bionic Beaver), but not on older LTS version. For instance, Ubuntu 16.04 (Xenial Xerus) only provides OpenConnect 7.06, which [fails to connect with an error](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4). [There is a confirmed way to force install this](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4) on to Ubuntu 16.04 from the Ubuntu 17.04 (Zesty) distribution, but it is not clear whether such an installation leaves the system in a stable state or not. Moreover, due to library dependencies, it appears not possible to have OpenConnect 7.08 and Pulse Secure 5.3-3 installed at the same time. +OpenConnect (>= 7.08) is available on for instance Ubuntu 18.04 LTS +(Bionic Beaver), but not on older LTS version. For instance, Ubuntu +16.04 (Xenial Xerus) only provides OpenConnect 7.06, which +[fails to connect with an error](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4). +[There is a confirmed way to force install this](https://github.com/HenrikBengtsson/ucsf-vpn/issues/4) +on to Ubuntu 16.04 from the Ubuntu 17.04 (Zesty) distribution, but it +is not clear whether such an installation leaves the system in a +stable state or not. Moreover, due to library dependencies, it +appears not possible to have OpenConnect 7.08 and Pulse Secure 5.3-3 +installed at the same time. ## Privacy @@ -136,15 +145,15 @@ credentials. ## Building from source The self-contained `bin/ucsf-vpn` script is generated from -`src/ucsf-vpn.sh` and `src/incl/*.sh`. The rebuild `bin/ucsf-vpn`, +`src/ucsf-vpn.sh` and `src/incl/*.sh`. To rebuild `bin/ucsf-vpn`, use: ```sh $ make build ./build.sh Building bin/ucsf-vpn from src/ucsf-vpn ... --rwxrwxr-x 1 alice alice May 20 07:34 bin/ucsf-vpn -Version built: 6.0.0 +-r-xr-xr-x 1 alice alice 58584 Jun 26 09:43 bin/ucsf-vpn +Version built: 6.1.0 Building bin/ucsf-vpn from src/ucsf-vpn ... done ``` diff --git a/WORDLIST b/WORDLIST index 3fe1f1d..48416d7 100644 --- a/WORDLIST +++ b/WORDLIST @@ -33,3 +33,6 @@ PID www YubiKey reconnection +io +ipinfo +nameserver diff --git a/bin/ucsf-vpn b/bin/ucsf-vpn index 536b1f4..0b205a6 100755 --- a/bin/ucsf-vpn +++ b/bin/ucsf-vpn @@ -34,10 +34,10 @@ ### --realm= VPN realm (default is 'Dual-Factor Pulse Clients') ### --url= VPN URL (default is https://{{server}}/pulse) ### --protocol= VPN protocol, e.g. 'nc' (default) and 'pulse' -### --validate= One or more of 'ipinfo', 'iproute', and 'pid', e.g. -### 'pid,iproute,ipinfo' (default) +### --validate= One or more of 'ipinfo', 'iproute', 'pid', 'ucsfit', +### e.g. 'pid,iproute,ucsfit' (default) ### --theme= Either 'cli' (default) or 'none' -### --flavor= Use a customized flavor of the VPN +### --flavor= Use a customized flavor of the VPN (default: 'none') ### ### Flags: ### --verbose More verbose output @@ -109,7 +109,7 @@ ### * UCSF Managing Your Passwords: ### - https://it.ucsf.edu/services/managing-your-passwords ### -### Version: 6.0.0 +### Version: 6.1.0 ### Copyright: Henrik Bengtsson (2016-2024) ### License: GPL (>= 2.1) [https://www.gnu.org/licenses/gpl.html] ### Source: https://github.com/HenrikBengtsson/ucsf-vpn @@ -289,6 +289,10 @@ function assert_sudo() { # ------------------------------------------------------------------------- # Connection, e.g. checking whether connected to the VPN or not # ------------------------------------------------------------------------- +function ucsf_it_network_info() { + curl --silent https://help.ucsf.edu/HelpApps/ipNetVerify.php | grep -E "(Connected to UCSF Network|IP Address|Network Location)" | sed 's/<\/td>/=/' | sed -E 's/<[^>]+>//g' | sed 's/.*Connected to UCSF Network/connected/' | sed 's/.*IP Address/public_ip/' | sed 's/.*Network Location/network/' | sed 's/=No/=false/' | sed 's/=Yes/=true/' | sed -E "s/network=(.*)/network='\1'/" | sort +} + function connection_details() { mdebug "connection_details()" if [[ ! -f "$pii_file" ]]; then @@ -342,8 +346,13 @@ function routing_details() { echo "Tunnel interfaces: none" fi + echo + echo "Nameserve configuration (/etc/resolv.conf):" + grep -v -E "^[[:space:]]*(#|$)" /etc/resolv.conf + mapfile -t ip_route < <(ip route show) - echo "IP routing table (${#ip_route[@]} entries):" + echo + echo "IP routing table (ip route show) [${#ip_route[@]} entries]:" for kk in "${!ip_route[@]}"; do row="${ip_route[${kk}]}" if $use_dig || $use_whois; then @@ -806,7 +815,7 @@ function openconnect_flavor() { mdebug "Flavor file exists: ${flavor_file}" res=$(cat "${flavor_file}") if [[ -z ${res} ]]; then - res="default" + res="none" fi echo "${res}" } @@ -880,7 +889,7 @@ function openconnect_start() { minfo "Preparing to connect to VPN server '$server'" - if [[ -n ${flavor} ]]; then + if [[ ${flavor} != "none" ]]; then ## Are vpnc generic hook scripts installed? if ! install_vpnc "check"; then if prompt_yesno "Do you want to install required ucsf-vpn hook scripts?"; then @@ -977,6 +986,9 @@ function openconnect_start() { ## Record IP routing table before connecting to the VPN ip route show > "${ip_route_novpn_file}" + ## Record hostname resolve file before connecting to the VPN + cat /etc/resolv.conf > "${resolv_novpn_file}" + log "ip route show:" ip route show >> "${log_file}" @@ -1060,16 +1072,26 @@ function openconnect_start() { ## Record IP routing table after having connected to the VPN ip route show > "${ip_route_vpn_file}" + ## Record hostname resolve file after having connected to the VPN + cat /etc/resolv.conf > "${resolv_vpn_file}" + default_route_after=$(grep -E '^default[[:space:]].*tun' "${ip_route_vpn_file}" | sed 's/default //' | sed -E 's/ +$//') mdebug "Default IP routing changed to: ${default_route_after}" if $debug; then - mdebug "Changes made to the IP routing table:" + mdebug "Changes made to the IP routing table (ip route show):" { _tput setaf 8 ## gray diff -u -w "${ip_route_novpn_file}" "${ip_route_vpn_file}" _tput sgr0 ## reset } 1>&2 + + mdebug "Changes made to /etc/resolv.conf:" + { + _tput setaf 8 ## gray + diff -u -w "${resolv_novpn_file}" "${resolv_vpn_file}" + _tput sgr0 ## reset + } 1>&2 fi if $verbose; then @@ -1107,6 +1129,9 @@ function openconnect_stop() { ## Record IP routing table while still connected to the VPN ip route show > "${ip_route_vpn_file}" + + ## Record hostname resolve file while still connected to the VPN + cat /etc/resolv.conf > "${resolv_vpn_file}" ## Signal SIGINT to terminate OpenConnect. If the first one fails, ## try another one @@ -1149,18 +1174,28 @@ function openconnect_stop() { ## Record IP routing table after being disconnected from the VPN ip route show > "${ip_route_novpn_file}" + + ## Record hostname resolve file after being disconnected from the VPN + cat /etc/resolv.conf > "${resolv_novpn_file}" default_route_after=$(grep -E '^default[[:space:]]' "${ip_route_novpn_file}" | sed 's/default //' | sed -E 's/ +$//') mdebug "Default IP routing changed to: ${default_route_after}" if $debug; then - mdebug "Changes made to the IP routing table:" + mdebug "Changes made to the IP routing table (ip route show):" { _tput setaf 8 ## gray diff -u -w "${ip_route_vpn_file}" "${ip_route_novpn_file}" _tput sgr0 ## reset } 1>&2 + + mdebug "Changes made to /etc/resolv.conf:" + { + _tput setaf 8 ## gray + diff -u -w "${resolv_vpn_file}" "${resolv_novpn_file}" + _tput sgr0 ## reset + } 1>&2 fi if $verbose; then @@ -1266,13 +1301,23 @@ function status() { msg="none" fi msgs+=("IP routing tunnels: ${msg}") + elif [[ $method == ucsfit ]]; then + mapfile -t info < <(ucsf_it_network_info) + if grep -q "connected=true" <<< "${info[0]}"; then + connected+=(true) + msg="yes (n=${#info[@]} ${info[*]})" + else + connected+=(false) + msg="no (n=${#info[@]} ${info[*]})" + fi + msgs+=("Public IP information (UCSF IT): ${info[2]}, ${info[1]}") elif [[ $method == ipinfo ]]; then if is_connected; then connected+=(true) else connected+=(false) fi - msgs+=("Public IP information: $(public_info)") + msgs+=("Public IP information (ipinfo.io): $(public_info)") else merror "Unknown --validate value: $method" fi @@ -1304,7 +1349,11 @@ function status() { "$mcmd" "${msg}" done if ${connected[0]}; then - "$mcmd" "Flavor: $(openconnect_flavor)" + msg="$(openconnect_flavor)" + if [[ ${msg} != "none" ]]; then + msg="${flavor} (${msg})" + fi + "$mcmd" "Flavor: ${msg}" msg="Connected to the VPN" else msg="Not connected to the VPN" @@ -1397,7 +1446,7 @@ function flavor_home() { local -i count ## No flavor specified - if [[ -z ${flavor} ]]; then + if [[ ${flavor} == "none" ]]; then echo return fi @@ -1523,6 +1572,8 @@ pid_file="$(xdg_state_path)/openconnect.pid" flavor_file="$(xdg_state_path)/openconnect.flavor" ip_route_novpn_file="$(xdg_state_path)/ip-route.novpn.out" ip_route_vpn_file="$(xdg_state_path)/ip-route.vpn.out" +resolv_novpn_file="$(xdg_state_path)/resolv.novpn.out" +resolv_vpn_file="$(xdg_state_path)/resolv.vpn.out" pii_file=$(make_pii_file) source_envs @@ -1548,7 +1599,7 @@ realm= extras=("${UCSF_VPN_EXTRAS[@]}") protocol=${UCSF_VPN_PROTOCOL:-nc} presudo=${UCSF_VPN_PRESUDO:-true} -flavor=${UCSF_VPN_FLAVOR} +flavor=${UCSF_VPN_FLAVOR:-none} ## User credentials user= @@ -1747,7 +1798,7 @@ fi ## Validate 'validate' if [[ -z $validate ]]; then - validate=${UCSF_VPN_VALIDATE:-pid,iproute,ipinfo} + validate=${UCSF_VPN_VALIDATE:-pid,iproute,ucsfit} fi diff --git a/build.sh b/build.sh index 498b91b..f3f2f12 100755 --- a/build.sh +++ b/build.sh @@ -26,8 +26,9 @@ grep -q -F 'source "${incl}/' "${tmpl}" fi done < "${tmpl}" } > "${target}.tmp" +chmod ugo-w "${target}.tmp" chmod ugo+x "${target}.tmp" -mv "${target}.tmp" "${target}" +mv -f "${target}.tmp" "${target}" ls -l "${target}" echo "Version built: $(bash "${target}" --version)" diff --git a/flavors/localdns/connect.sh b/flavors/localdns/connect.sh new file mode 100644 index 0000000..b2cbe85 --- /dev/null +++ b/flavors/localdns/connect.sh @@ -0,0 +1,28 @@ +#!/bin/sh +#################################################################### +# Tunnel only UCSF intranet +# +# Install: +# mkdir -p ~/.config/ucsf-vpn/flavors/localdns/ +# cp connect.sh ~/.config/ucsf-vpn/flavors/localdns/ +# +# Requires: +# https://github.com/HenrikBengtsson/ucsf-vpn +# +# Description: +# This script overrides parts of the default behavior of +# /usr/share/vpnc-scripts/vpnc-script. It's been verified to +# to work on Ubuntu 22.04. +# +# Authors: Henrik Bengtsson +# Version: 2024-05-22 +# License: GPL +#################################################################### + +#------------------------------------------------------------------- +# Tweak DNS lookup +#------------------------------------------------------------------- +# Tricks modify_resolvconf_generic() to prepend the local nameserver +# before the ones that the VPN server provides. +_nameservers_=$(grep "^nameserver[[:blank:]]" /etc/resolv.conf | sed -E 's/nameserver[[:blank:]]+//') +INTERNAL_IP4_DNS="${_nameservers_} $INTERNAL_IP4_DNS" diff --git a/src/incl/connections.sh b/src/incl/connections.sh index b672923..6a919d9 100755 --- a/src/incl/connections.sh +++ b/src/incl/connections.sh @@ -1,6 +1,10 @@ # ------------------------------------------------------------------------- # Connection, e.g. checking whether connected to the VPN or not # ------------------------------------------------------------------------- +function ucsf_it_network_info() { + curl --silent https://help.ucsf.edu/HelpApps/ipNetVerify.php | grep -E "(Connected to UCSF Network|IP Address|Network Location)" | sed 's/<\/td>/=/' | sed -E 's/<[^>]+>//g' | sed 's/.*Connected to UCSF Network/connected/' | sed 's/.*IP Address/public_ip/' | sed 's/.*Network Location/network/' | sed 's/=No/=false/' | sed 's/=Yes/=true/' | sed -E "s/network=(.*)/network='\1'/" | sort +} + function connection_details() { mdebug "connection_details()" if [[ ! -f "$pii_file" ]]; then @@ -54,8 +58,13 @@ function routing_details() { echo "Tunnel interfaces: none" fi + echo + echo "Nameserve configuration (/etc/resolv.conf):" + grep -v -E "^[[:space:]]*(#|$)" /etc/resolv.conf + mapfile -t ip_route < <(ip route show) - echo "IP routing table (${#ip_route[@]} entries):" + echo + echo "IP routing table (ip route show) [${#ip_route[@]} entries]:" for kk in "${!ip_route[@]}"; do row="${ip_route[${kk}]}" if $use_dig || $use_whois; then diff --git a/src/incl/openconnect.sh b/src/incl/openconnect.sh index 921658d..8a07a91 100755 --- a/src/incl/openconnect.sh +++ b/src/incl/openconnect.sh @@ -137,7 +137,7 @@ function openconnect_flavor() { mdebug "Flavor file exists: ${flavor_file}" res=$(cat "${flavor_file}") if [[ -z ${res} ]]; then - res="default" + res="none" fi echo "${res}" } @@ -211,7 +211,7 @@ function openconnect_start() { minfo "Preparing to connect to VPN server '$server'" - if [[ -n ${flavor} ]]; then + if [[ ${flavor} != "none" ]]; then ## Are vpnc generic hook scripts installed? if ! install_vpnc "check"; then if prompt_yesno "Do you want to install required ucsf-vpn hook scripts?"; then @@ -308,6 +308,9 @@ function openconnect_start() { ## Record IP routing table before connecting to the VPN ip route show > "${ip_route_novpn_file}" + ## Record hostname resolve file before connecting to the VPN + cat /etc/resolv.conf > "${resolv_novpn_file}" + log "ip route show:" ip route show >> "${log_file}" @@ -391,16 +394,26 @@ function openconnect_start() { ## Record IP routing table after having connected to the VPN ip route show > "${ip_route_vpn_file}" + ## Record hostname resolve file after having connected to the VPN + cat /etc/resolv.conf > "${resolv_vpn_file}" + default_route_after=$(grep -E '^default[[:space:]].*tun' "${ip_route_vpn_file}" | sed 's/default //' | sed -E 's/ +$//') mdebug "Default IP routing changed to: ${default_route_after}" if $debug; then - mdebug "Changes made to the IP routing table:" + mdebug "Changes made to the IP routing table (ip route show):" { _tput setaf 8 ## gray diff -u -w "${ip_route_novpn_file}" "${ip_route_vpn_file}" _tput sgr0 ## reset } 1>&2 + + mdebug "Changes made to /etc/resolv.conf:" + { + _tput setaf 8 ## gray + diff -u -w "${resolv_novpn_file}" "${resolv_vpn_file}" + _tput sgr0 ## reset + } 1>&2 fi if $verbose; then @@ -438,6 +451,9 @@ function openconnect_stop() { ## Record IP routing table while still connected to the VPN ip route show > "${ip_route_vpn_file}" + + ## Record hostname resolve file while still connected to the VPN + cat /etc/resolv.conf > "${resolv_vpn_file}" ## Signal SIGINT to terminate OpenConnect. If the first one fails, ## try another one @@ -480,18 +496,28 @@ function openconnect_stop() { ## Record IP routing table after being disconnected from the VPN ip route show > "${ip_route_novpn_file}" + + ## Record hostname resolve file after being disconnected from the VPN + cat /etc/resolv.conf > "${resolv_novpn_file}" default_route_after=$(grep -E '^default[[:space:]]' "${ip_route_novpn_file}" | sed 's/default //' | sed -E 's/ +$//') mdebug "Default IP routing changed to: ${default_route_after}" if $debug; then - mdebug "Changes made to the IP routing table:" + mdebug "Changes made to the IP routing table (ip route show):" { _tput setaf 8 ## gray diff -u -w "${ip_route_vpn_file}" "${ip_route_novpn_file}" _tput sgr0 ## reset } 1>&2 + + mdebug "Changes made to /etc/resolv.conf:" + { + _tput setaf 8 ## gray + diff -u -w "${resolv_vpn_file}" "${resolv_novpn_file}" + _tput sgr0 ## reset + } 1>&2 fi if $verbose; then diff --git a/src/ucsf-vpn.sh b/src/ucsf-vpn.sh index 02d2e52..12a66db 100755 --- a/src/ucsf-vpn.sh +++ b/src/ucsf-vpn.sh @@ -31,10 +31,10 @@ ### --realm= VPN realm (default is 'Dual-Factor Pulse Clients') ### --url= VPN URL (default is https://{{server}}/pulse) ### --protocol= VPN protocol, e.g. 'nc' (default) and 'pulse' -### --validate= One or more of 'ipinfo', 'iproute', and 'pid', e.g. -### 'pid,iproute,ipinfo' (default) +### --validate= One or more of 'ipinfo', 'iproute', 'pid', 'ucsfit', +### e.g. 'pid,iproute,ucsfit' (default) ### --theme= Either 'cli' (default) or 'none' -### --flavor= Use a customized flavor of the VPN +### --flavor= Use a customized flavor of the VPN (default: 'none') ### ### Flags: ### --verbose More verbose output @@ -106,7 +106,7 @@ ### * UCSF Managing Your Passwords: ### - https://it.ucsf.edu/services/managing-your-passwords ### -### Version: 6.0.0 +### Version: 6.1.0 ### Copyright: Henrik Bengtsson (2016-2024) ### License: GPL (>= 2.1) [https://www.gnu.org/licenses/gpl.html] ### Source: https://github.com/HenrikBengtsson/ucsf-vpn @@ -193,13 +193,23 @@ function status() { msg="none" fi msgs+=("IP routing tunnels: ${msg}") + elif [[ $method == ucsfit ]]; then + mapfile -t info < <(ucsf_it_network_info) + if grep -q "connected=true" <<< "${info[0]}"; then + connected+=(true) + msg="yes (n=${#info[@]} ${info[*]})" + else + connected+=(false) + msg="no (n=${#info[@]} ${info[*]})" + fi + msgs+=("Public IP information (UCSF IT): ${info[2]}, ${info[1]}") elif [[ $method == ipinfo ]]; then if is_connected; then connected+=(true) else connected+=(false) fi - msgs+=("Public IP information: $(public_info)") + msgs+=("Public IP information (ipinfo.io): $(public_info)") else merror "Unknown --validate value: $method" fi @@ -231,7 +241,11 @@ function status() { "$mcmd" "${msg}" done if ${connected[0]}; then - "$mcmd" "Flavor: $(openconnect_flavor)" + msg="$(openconnect_flavor)" + if [[ ${msg} != "none" ]]; then + msg="${flavor} (${msg})" + fi + "$mcmd" "Flavor: ${msg}" msg="Connected to the VPN" else msg="Not connected to the VPN" @@ -324,7 +338,7 @@ function flavor_home() { local -i count ## No flavor specified - if [[ -z ${flavor} ]]; then + if [[ ${flavor} == "none" ]]; then echo return fi @@ -410,6 +424,8 @@ pid_file="$(xdg_state_path)/openconnect.pid" flavor_file="$(xdg_state_path)/openconnect.flavor" ip_route_novpn_file="$(xdg_state_path)/ip-route.novpn.out" ip_route_vpn_file="$(xdg_state_path)/ip-route.vpn.out" +resolv_novpn_file="$(xdg_state_path)/resolv.novpn.out" +resolv_vpn_file="$(xdg_state_path)/resolv.vpn.out" pii_file=$(make_pii_file) source_envs @@ -435,7 +451,7 @@ realm= extras=("${UCSF_VPN_EXTRAS[@]}") protocol=${UCSF_VPN_PROTOCOL:-nc} presudo=${UCSF_VPN_PRESUDO:-true} -flavor=${UCSF_VPN_FLAVOR} +flavor=${UCSF_VPN_FLAVOR:-none} ## User credentials user= @@ -634,7 +650,7 @@ fi ## Validate 'validate' if [[ -z $validate ]]; then - validate=${UCSF_VPN_VALIDATE:-pid,iproute,ipinfo} + validate=${UCSF_VPN_VALIDATE:-pid,iproute,ucsfit} fi