diff --git a/README.md b/README.md index ce4815c..eb967f2 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,16 @@ otherwise the configuration provided by this script will only work on domains that cannot be resolved by the currently configured DNS servers (i.e. they must fall back after trying the ones set by your LAN's DHCP server). -Finally, update your OpenVPN configuration file and set the `up` and `down-pre` -options: +Finally, update your OpenVPN configuration file and set the `up` and `down` +options to point to the script, and `down-pre` to ensure that the script is run +before the device is closed: ``` script-security 2 setenv PATH /usr/bin up /etc/openvpn/update-systemd-resolved -down-pre /etc/openvpn/update-systemd-resolved +down /etc/openvpn/update-systemd-resolved +down-pre ``` ## Usage @@ -63,7 +65,7 @@ OpenVPN, either through the server, or the client, configuration: | `DOMAIN` | `example.com` | The primary domain for this host. If set multiple times, the last provided is used. Will be the primary search domain for bare hostnames. All requests for this domain as well will be routed to the `DNS` servers provided on this link. | | `DOMAIN-SEARCH` | `example.com` | Secondary domains which will be used to search for bare hostnames (after any `DOMAIN`, if set) and in the order provided. All requests for this domain will be routed to the `DNS` servers provided on this link. | | `DOMAIN-ROUTE` | `example.com` | All requests for these domains will be routed to the `DNS` servers provided on this link. They will *not* be used to search for bare hostnames, only routed. | -| `DNSSEC` | `yes`
`no`
`default` | Control of DNSSEC should be enabled (`yes`) or disabled (`no`) for any queries over this link only, or use the system default (`default`). | +| `DNSSEC` | `yes`
`no`
`allow-downgrade`
`default` | Control of DNSSEC should be enabled (`yes`) or disabled (`no`), or `allow-downgrade` to switch off DNSSEC only if the server doesn't support it, for any queries over this link only, or use the system default (`default`). | *Note*: There are no local or system options to be configured. All configuration for this script is handled though OpenVPN, including, for example, the name of diff --git a/run-tests b/run-tests index b7a19bc..7d42cce 100755 --- a/run-tests +++ b/run-tests @@ -66,16 +66,11 @@ function busctl { ;; SetLinkDNSSEC) shift 2 - if [[ "${TEST_BUSCTL_DNSSEC}" == "" ]]; then - [[ "${ip_ifindex} ${TEST_BUSCTL_DNSSEC}" == "${@}" ]] || \ - _fail "SetLinkDNSSEC was called and should not be: '${@}'" - else - [[ "${ip_ifindex} ${TEST_BUSCTL_DNSSEC}" == "${@}" ]] && \ - _pass "SetLinkDNSSEC was called correctly" || \ - _fail "SetLinkDNSSEC was not given the correct arguments:\n" \ - " Expected: '${ip_ifindex} ${TEST_BUSCTL_DNSSEC}'\n" \ - " Received: '${@}'" - fi + [[ "${ip_ifindex} ${TEST_BUSCTL_DNSSEC}x" == "${@}x" ]] && \ + _pass "SetLinkDNSSEC was called correctly" || \ + _fail "SetLinkDNSSEC was not given the correct arguments:\n" \ + " Expected: '${ip_ifindex} ${TEST_BUSCTL_DNSSEC}'\n" \ + " Received: '${@}'" ;; *) _fail "Unknown command called on busctl: ${1}" diff --git a/tests/20_dnssec_only.sh b/tests/20_dnssec_only.sh index d2a56b9..80b8ee5 100644 --- a/tests/20_dnssec_only.sh +++ b/tests/20_dnssec_only.sh @@ -4,8 +4,8 @@ dev="tun20" TEST_BUSCTL_CALLED=1 declare -A test_options=( - ['default']='""' - ['Default']='""' + ['default']='' + ['Default']='' ['true']='yes' ['True']='yes' ['yes']='yes' diff --git a/update-systemd-resolved b/update-systemd-resolved index eda856e..422d105 100755 --- a/update-systemd-resolved +++ b/update-systemd-resolved @@ -18,10 +18,12 @@ # This script will parse DHCP options set via OpenVPN (dhcp-option) to update # systemd-resolved directly via DBus, instead of updating /etc/resolv.conf. To -# install, set as the 'up' and 'down-pre' script in your OpenVPN configuration file -# or command-line argument. For example: +# install, set as the 'up' and 'down' script in your OpenVPN configuration file +# or via the command-line arguments, alongside setting the 'down-pre' option to +# run the 'down' script before the device is closed. For example: # up /etc/openvpn/update-systemd-resolved -# down-pre /etc/openvpn/update-systemd-resolved +# down /etc/openvpn/update-systemd-resolved +# down-pre # Define what needs to be called via DBus DBUS_DEST="org.freedesktop.resolve1" @@ -46,7 +48,7 @@ busctl_call() { # Preserve busctl's exit status busctl call "$DBUS_DEST" "$DBUS_NODE" "${DBUS_DEST}.Manager" "$@" || { local -i status=$? - emerg "\`busctl' exited with status $status" + emerg "'busctl' exited with status $status" return $status } } @@ -76,7 +78,7 @@ up() { local if_index="$1" shift - info "Link \`$link' coming up" + info "Link '$link' coming up" # Preset values for processing -- will be altered in the various process_* # functions. @@ -94,7 +96,7 @@ up() { if declare -f "$process_setting_function" &>/dev/null; then "$process_setting_function" "$setting_value" || return $? else - warning "Not a recognized DHCP setting: \`${setting}'" + warning "Not a recognized DHCP setting: '${setting}'" fi done < <(dhcp_settings) @@ -125,12 +127,12 @@ up() { if [[ -n "${dns_sec}" ]]; then if [[ "${dns_sec}" == "default" ]]; then # We need to provide an empty string to use the default settings - busctl_params=("$if_index" '""') + info "SetLinkDNSSEC($if_index '')" + busctl_call SetLinkDNSSEC 'is' "$if_index" "" || return $? else - busctl_params=("$if_index" "${dns_sec}") + info "SetLinkDNSSEC($if_index ${dns_sec})" + busctl_call SetLinkDNSSEC 'is' "$if_index" "${dns_sec}" || return $? fi - info "SetLinkDNSSEC(${busctl_params[*]})" - busctl_call SetLinkDNSSEC 'is' "${busctl_params[@]}" || return $? fi } @@ -140,8 +142,13 @@ down() { local if_index="$1" shift - info "Link \`$link' going down" - busctl_call RevertLink i "$if_index" + info "Link '$link' going down" + if [[ "$(whoami 2>/dev/null)" != "root" ]]; then + # Cleanly handle the priviledge dropped case by not calling RevertLink + info "Priviledges dropped in the client: Cannot call RevertLink." + else + busctl_call RevertLink i "$if_index" + fi } process_dns() { @@ -153,7 +160,7 @@ process_dns() { elif looks_like_ipv4 "$address"; then process_dns_ipv4 "$address" || return $? else - err "Not a valid IPv6 or IPv4 address: \`$address'" + err "Not a valid IPv6 or IPv4 address: '$address'" return 1 fi } @@ -194,17 +201,17 @@ parse_ipv6() { local raw_address="$1" log_invalid_ipv6() { - local message="\`$raw_address' is not a valid IPv6 address" + local message="'$raw_address' is not a valid IPv6 address" emerg "${message}: $*" } trap -- 'unset -f log_invalid_ipv6' RETURN if [[ "$raw_address" == *::*::* ]]; then - log_invalid_ipv6 "address cannot contain more than one \`::'" + log_invalid_ipv6 "address cannot contain more than one '::'" return 1 elif [[ "$raw_address" =~ :0+:: ]] || [[ "$raw_address" =~ ::0+: ]]; then - log_invalid_ipv6 "address contains a 0-group adjacent to \`::' and is not maximally shortened" + log_invalid_ipv6 "address contains a 0-group adjacent to '::' and is not maximally shortened" return 1 fi @@ -269,7 +276,7 @@ parse_ipv6() { if [[ "$raw_address" == *::* ]]; then if (( ${#tokenized_segments[*]} == length )); then - log_invalid_ipv6 "single \`0' fields should not be compressed" + log_invalid_ipv6 "single '0' fields should not be compressed" return 1 else local -i largest_run_i=0 largest_run=0 @@ -366,7 +373,7 @@ process_dnssec() { allow-downgrade) setting="allow-downgrade" ;; *) - local message="\`$option' is not a valid DNSSEC option" + local message="'$option' is not a valid DNSSEC option" emerg "${message}" return 1 ;; esac @@ -388,11 +395,11 @@ main() { usage 'No device name specified' return 1 elif ! declare -f "${script_type}" &>/dev/null; then - usage "Invalid script type: \`${script_type}'" + usage "Invalid script type: '${script_type}'" return 1 else if ! read -r link if_index _ < <(get_link_info "$dev"); then - usage "Invalid device name: \`$dev'" + usage "Invalid device name: '$dev'" return 1 fi