mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-02-03 20:39:40 -05:00
dns: apply settings via script on unixoid systems
This introduces a new script hook, the dns-updown, and implements such a command script for a few popular systems (and a default for the not so popular ones). Like the name suggests this hook is soleley for dealing with modifying how names are resolved when the VPN pushes some --dns settings. The default dns updown command is part of the distribution and is installed with openvpn. You can change the path the command is located at as a compile time option, defaults to libexecdir. You can compile-time disable that the default dns-updown hook is run by passing --disable-dns-updown-by-default to configure or ccmake ENABLE_DNS_UPDOWN_BY_DEFAULT to OFF. There's also a new runtime option --dns-updown, which can run a custom command, force running the default when disabled or disable execution of the dns-updown altogether. Change-Id: Ifbe4ffb44d3bfcaa50adb38cacb3436fcdc71b10 Signed-off-by: Heiko Hund <heiko@ist.eigentlich.net> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <20250514135334.14377-1-gert@greenie.muc.de> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31639.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
ad7a694514
commit
fef5c4b4e8
15 changed files with 707 additions and 10 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -49,6 +49,7 @@ doc/openvpn.8.html
|
|||
/doc/doxygen/latex/
|
||||
/doc/doxygen/openvpn.doxyfile
|
||||
distro/systemd/*.service
|
||||
distro/dns-scripts/dns-updown
|
||||
sample/sample-keys/sample-ca/
|
||||
vendor/cmocka_build
|
||||
vendor/dist
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ option(ENABLE_PKCS11 "BUILD with pkcs11-helper" ON)
|
|||
option(USE_WERROR "Treat compiler warnings as errors (-Werror)" ON)
|
||||
option(FAKE_ANDROID "Target Android but do not use actual cross compile/Android cmake to build for simple compile checks on Linux")
|
||||
|
||||
set(PLUGIN_DIR /usr/local/lib/openvpn/plugins CACHE FILEPATH "Location of the plugin directory")
|
||||
option(ENABLE_DNS_UPDOWN_BY_DEFAULT "Run --dns-updown hook by default" ON)
|
||||
set(DNS_UPDOWN_PATH "${CMAKE_INSTALL_PREFIX}/libexec/openvpn/dns-updown" CACHE STRING "Default location for the DNS up/down script")
|
||||
|
||||
set(PLUGIN_DIR "${CMAKE_INSTALL_PREFIX}/lib/openvpn/plugins" CACHE FILEPATH "Location of the plugin directory")
|
||||
|
||||
# Create machine readable compile commands
|
||||
option(ENABLE_COMPILE_COMMANDS "Generate compile_commands.json and a symlink for clangd to find it" OFF)
|
||||
|
|
@ -601,6 +604,8 @@ add_executable(openvpn ${SOURCE_FILES})
|
|||
|
||||
add_library_deps(openvpn)
|
||||
|
||||
target_compile_options(openvpn PRIVATE -DDEFAULT_DNS_UPDOWN=\"${DNS_UPDOWN_PATH}\")
|
||||
|
||||
if(MINGW)
|
||||
target_compile_options(openvpn PRIVATE -municode -UUNICODE)
|
||||
target_link_options(openvpn PRIVATE -municode)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@
|
|||
/* Enable LZO compression library */
|
||||
#cmakedefine ENABLE_LZO
|
||||
|
||||
/* Enable dns-updown script hook */
|
||||
#cmakedefine ENABLE_DNS_UPDOWN
|
||||
|
||||
/* Enable NTLMv2 proxy support */
|
||||
#define ENABLE_NTLM 1
|
||||
|
||||
|
|
|
|||
34
configure.ac
34
configure.ac
|
|
@ -95,6 +95,13 @@ AC_ARG_ENABLE(
|
|||
[enable_x509_alt_username="no"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[dns-updown-by-default],
|
||||
[AS_HELP_STRING([--disable-dns-updown-by-default], [disable running --dns-updown by default @<:@default=yes@:>@])],
|
||||
,
|
||||
[enable_dns_updown_by_default="yes"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[ntlm],
|
||||
[AS_HELP_STRING([--disable-ntlm], [disable NTLMv2 proxy support @<:@default=yes@:>@])],
|
||||
|
|
@ -315,37 +322,50 @@ else
|
|||
plugindir="\${libdir}/openvpn/plugins"
|
||||
fi
|
||||
|
||||
AC_ARG_VAR([SCRIPTDIR], [Path of script directory @<:@default=PKGLIBEXECDIR@:>@])
|
||||
if test -n "${SCRIPTDIR}"; then
|
||||
scriptdir="${SCRIPTDIR}"
|
||||
else
|
||||
scriptdir="\${pkglibexecdir}"
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED([TARGET_ALIAS], ["${host}"], [A string representing our host])
|
||||
AM_CONDITIONAL([TARGET_LINUX], [false])
|
||||
AM_CONDITIONAL([ENABLE_DNS_UPDOWN],[true])
|
||||
case "$host" in
|
||||
*-*-linux*)
|
||||
AC_DEFINE([TARGET_LINUX], [1], [Are we running on Linux?])
|
||||
AM_CONDITIONAL([TARGET_LINUX], [true])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["L"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["systemd"])
|
||||
have_sitnl="yes"
|
||||
pkg_config_required="yes"
|
||||
;;
|
||||
*-*-solaris*)
|
||||
AC_DEFINE([TARGET_SOLARIS], [1], [Are we running on Solaris?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["S"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"])
|
||||
CPPFLAGS="$CPPFLAGS -D_XPG4_2"
|
||||
test -x /bin/bash && SHELL="/bin/bash"
|
||||
;;
|
||||
*-*-openbsd*)
|
||||
AC_DEFINE([TARGET_OPENBSD], [1], [Are we running on OpenBSD?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["O"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"])
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
AC_DEFINE([TARGET_FREEBSD], [1], [Are we running on FreeBSD?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["F"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"])
|
||||
;;
|
||||
*-*-netbsd*)
|
||||
AC_DEFINE([TARGET_NETBSD], [1], [Are we running NetBSD?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["N"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"])
|
||||
;;
|
||||
*-*-darwin*)
|
||||
AC_DEFINE([TARGET_DARWIN], [1], [Are we running on Mac OS X?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["M"], [Target prefix])
|
||||
AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"])
|
||||
have_tap_header="yes"
|
||||
ac_cv_type_struct_in_pktinfo=no
|
||||
;;
|
||||
|
|
@ -353,6 +373,8 @@ case "$host" in
|
|||
AC_DEFINE([TARGET_WIN32], [1], [Are we running WIN32?])
|
||||
AC_DEFINE([ENABLE_DCO], [1], [DCO is always enabled on Windows])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["W"], [Target prefix])
|
||||
AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["windows"])
|
||||
CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN"
|
||||
CPPFLAGS="${CPPFLAGS} -DNTDDI_VERSION=NTDDI_VISTA -D_WIN32_WINNT=_WIN32_WINNT_VISTA"
|
||||
WIN32=yes
|
||||
|
|
@ -360,10 +382,12 @@ case "$host" in
|
|||
*-*-dragonfly*)
|
||||
AC_DEFINE([TARGET_DRAGONFLY], [1], [Are we running on DragonFlyBSD?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["D"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"])
|
||||
;;
|
||||
*-aix*)
|
||||
AC_DEFINE([TARGET_AIX], [1], [Are we running AIX?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["A"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"])
|
||||
ROUTE="/usr/sbin/route"
|
||||
have_tap_header="yes"
|
||||
ac_cv_header_net_if_h="no" # exists, but breaks things
|
||||
|
|
@ -371,10 +395,12 @@ case "$host" in
|
|||
*-*-haiku*)
|
||||
AC_DEFINE([TARGET_HAIKU], [1], [Are we running Haiku?])
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["H"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["haikuos_file"])
|
||||
LIBS="${LIBS} -lnetwork"
|
||||
;;
|
||||
*)
|
||||
AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["X"], [Target prefix])
|
||||
AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"])
|
||||
have_tap_header="yes"
|
||||
;;
|
||||
esac
|
||||
|
|
@ -1317,7 +1343,7 @@ test "${enable_debug}" = "yes" && AC_DEFINE([ENABLE_DEBUG], [1], [Enable debuggi
|
|||
test "${enable_small}" = "yes" && AC_DEFINE([ENABLE_SMALL], [1], [Enable smaller executable size])
|
||||
test "${enable_fragment}" = "yes" && AC_DEFINE([ENABLE_FRAGMENT], [1], [Enable internal fragmentation support])
|
||||
test "${enable_port_share}" = "yes" && AC_DEFINE([ENABLE_PORT_SHARE], [1], [Enable TCP Server port sharing])
|
||||
|
||||
test "${enable_dns_updown_by_default}" = "yes" && AC_DEFINE([ENABLE_DNS_UPDOWN_BY_DEFAULT], [1], [Enable dns-updown hook by default])
|
||||
test "${enable_ntlm}" = "yes" && AC_DEFINE([ENABLE_NTLM], [1], [Enable NTLMv2 proxy support])
|
||||
test "${enable_crypto_ofb_cfb}" = "yes" && AC_DEFINE([ENABLE_OFB_CFB_MODE], [1], [Enable OFB and CFB cipher modes])
|
||||
if test "${have_export_keying_material}" = "yes"; then
|
||||
|
|
@ -1505,6 +1531,7 @@ AM_CONDITIONAL([OPENSSL_ENGINE], [test "${have_openssl_engine}" = "yes"])
|
|||
|
||||
sampledir="\$(docdir)/sample"
|
||||
AC_SUBST([plugindir])
|
||||
AC_SUBST([scriptdir])
|
||||
AC_SUBST([sampledir])
|
||||
|
||||
AC_SUBST([systemdunitdir])
|
||||
|
|
@ -1541,6 +1568,7 @@ AC_CONFIG_FILES([
|
|||
Makefile
|
||||
distro/Makefile
|
||||
distro/systemd/Makefile
|
||||
distro/dns-scripts/Makefile
|
||||
doc/Makefile
|
||||
doc/doxygen/Makefile
|
||||
doc/doxygen/openvpn.doxyfile
|
||||
|
|
|
|||
|
|
@ -13,3 +13,7 @@ MAINTAINERCLEANFILES = \
|
|||
$(srcdir)/Makefile.in
|
||||
|
||||
SUBDIRS = systemd
|
||||
|
||||
if ENABLE_DNS_UPDOWN
|
||||
SUBDIRS += dns-scripts
|
||||
endif
|
||||
|
|
|
|||
29
distro/dns-scripts/Makefile.am
Normal file
29
distro/dns-scripts/Makefile.am
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# OpenVPN -- An application to securely tunnel IP networks
|
||||
# over a single UDP port, with support for SSL/TLS-based
|
||||
# session authentication and key exchange,
|
||||
# packet encryption, packet authentication, and
|
||||
# packet compression.
|
||||
#
|
||||
# Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
|
||||
#
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
$(srcdir)/Makefile.in
|
||||
|
||||
EXTRA_DIST = \
|
||||
systemd-dns-updown.sh \
|
||||
openresolv-dns-updown.sh \
|
||||
haikuos_file-dns-updown.sh \
|
||||
resolvconf_file-dns-updown.sh
|
||||
|
||||
script_SCRIPTS = \
|
||||
dns-updown
|
||||
|
||||
CLEANFILES = $(script_SCRIPTS)
|
||||
|
||||
dns-updown: @DNS_UPDOWN_TYPE@-dns-updown.sh
|
||||
cp ${srcdir}/@DNS_UPDOWN_TYPE@-dns-updown.sh $@
|
||||
chmod +x $@
|
||||
|
||||
all: $(script_SCRIPTS)
|
||||
85
distro/dns-scripts/haikuos_file-dns-updown.sh
Normal file
85
distro/dns-scripts/haikuos_file-dns-updown.sh
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Simple OpenVPN up/down script for modifying Haiku OS resolv.conf
|
||||
# (C) Copyright 2024 OpenVPN Inc <sales@openvpn.net>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Example env from openvpn (most are not applied):
|
||||
#
|
||||
# dev tun0
|
||||
# script_type dns-up
|
||||
# dns_search_domain_1 mycorp.in
|
||||
# dns_search_domain_2 eu.mycorp.com
|
||||
# dns_server_1_address_1 192.168.99.254
|
||||
# dns_server_1_address_2 fd00::99:53
|
||||
# dns_server_1_port_1 53
|
||||
# dns_server_1_port_2 53
|
||||
# dns_server_1_resolve_domain_1 mycorp.in
|
||||
# dns_server_1_resolve_domain_2 eu.mycorp.com
|
||||
# dns_server_1_dnssec true
|
||||
# dns_server_1_transport DoH
|
||||
# dns_server_1_sni dns.mycorp.in
|
||||
#
|
||||
|
||||
set -e +u
|
||||
|
||||
conly_standard_server_ports() {
|
||||
i=1
|
||||
while true; do
|
||||
eval addr=\"\$dns_server_${n}_address_${i}\"
|
||||
[ -n "$addr" ] || return 0
|
||||
|
||||
eval port=\"\$dns_server_${n}_port_${i}\"
|
||||
[ -z "$port" -o "$port" = "53" ] || return 1
|
||||
|
||||
i=$(expr $i + 1)
|
||||
done
|
||||
}
|
||||
|
||||
onf=/boot/system/settings/network/resolv.conf
|
||||
test -e "$conf" || exit 1
|
||||
case "${script_type}" in
|
||||
dns-up)
|
||||
n=1
|
||||
while :; do
|
||||
eval addr=\"\$dns_server_${n}_address_1\"
|
||||
[ -n "$addr" ] || {
|
||||
echo "setting DNS failed, no compatible server profile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Skip server profiles which require DNSSEC,
|
||||
# secure transport or use a custom port
|
||||
eval dnssec=\"\$dns_server_${n}_dnssec\"
|
||||
eval transport=\"\$dns_server_${n}_transport\"
|
||||
[ -z "$transport" -o "$transport" = "plain" ] \
|
||||
&& [ -z "$dnssec" -o "$dnssec" = "no" ] \
|
||||
&& only_standard_server_ports && break
|
||||
|
||||
n=$(expr $n + 1)
|
||||
done
|
||||
|
||||
eval addr1=\"\$dns_server_${n}_address_1\"
|
||||
eval addr2=\"\$dns_server_${n}_address_2\"
|
||||
eval addr3=\"\$dns_server_${n}_address_3\"
|
||||
text="### openvpn ${dev} begin ###\n"
|
||||
text="${text}nameserver $addr1\n"
|
||||
test -z "$addr2" || text="${text}nameserver $addr2\n"
|
||||
test -z "$addr3" || text="${text}nameserver $addr3\n"
|
||||
|
||||
test -z "$dns_search_domain_1" || {
|
||||
for i in $(seq 1 6); do
|
||||
eval domains=\"$domains\$dns_search_domain_${i} \" || break
|
||||
done
|
||||
text="${text}search $domains\n"
|
||||
}
|
||||
text="${text}### openvpn ${dev} end ###"
|
||||
text="${text}\n$(cat ${conf})"
|
||||
|
||||
echo "${text}" > "${conf}"
|
||||
;;
|
||||
dns-down)
|
||||
sed -i'' -e "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf"
|
||||
;;
|
||||
esac
|
||||
89
distro/dns-scripts/openresolv-dns-updown.sh
Normal file
89
distro/dns-scripts/openresolv-dns-updown.sh
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Simple OpenVPN up/down script for openresolv integration
|
||||
# (C) Copyright 2016 Baptiste Daroussin
|
||||
# 2024 OpenVPN Inc <sales@openvpn.net>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Example env from openvpn (most are not applied):
|
||||
#
|
||||
# dev tun0
|
||||
# script_type dns-up
|
||||
# dns_search_domain_1 mycorp.in
|
||||
# dns_search_domain_2 eu.mycorp.com
|
||||
# dns_server_1_address_1 192.168.99.254
|
||||
# dns_server_1_address_2 fd00::99:53
|
||||
# dns_server_1_port_1 53
|
||||
# dns_server_1_port_2 53
|
||||
# dns_server_1_resolve_domain_1 mycorp.in
|
||||
# dns_server_1_resolve_domain_2 eu.mycorp.com
|
||||
# dns_server_1_dnssec true
|
||||
# dns_server_1_transport DoH
|
||||
# dns_server_1_sni dns.mycorp.in
|
||||
#
|
||||
|
||||
set -e +u
|
||||
|
||||
only_standard_server_ports() {
|
||||
i=1
|
||||
while true; do
|
||||
eval addr=\"\$dns_server_${n}_address_${i}\"
|
||||
[ -n "$addr" ] || return 0
|
||||
|
||||
eval port=\"\$dns_server_${n}_port_${i}\"
|
||||
[ -z "$port" -o "$port" = "53" ] || return 1
|
||||
|
||||
i=$(expr $i + 1)
|
||||
done
|
||||
}
|
||||
|
||||
: ${script_type:=dns-down}
|
||||
case "${script_type}" in
|
||||
dns-up)
|
||||
n=1
|
||||
while :; do
|
||||
eval addr=\"\$dns_server_${n}_address_1\"
|
||||
[ -n "$addr" ] || {
|
||||
echo "setting DNS failed, no compatible server profile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Skip server profiles which require DNSSEC,
|
||||
# secure transport or use a custom port
|
||||
eval dnssec=\"\$dns_server_${n}_dnssec\"
|
||||
eval transport=\"\$dns_server_${n}_transport\"
|
||||
[ -z "$transport" -o "$transport" = "plain" ] \
|
||||
&& [ -z "$dnssec" -o "$dnssec" = "no" ] \
|
||||
&& only_standard_server_ports && break
|
||||
|
||||
n=$(expr $n + 1)
|
||||
done
|
||||
|
||||
{
|
||||
i=1
|
||||
maxns=3
|
||||
while :; do
|
||||
maxns=$((maxns - 1))
|
||||
[ $maxns -gt 0 ] || break
|
||||
eval option=\"\$dns_server_${n}_address_${i}\" || break
|
||||
[ "${option}" ] || break
|
||||
i=$((i + 1))
|
||||
echo "nameserver ${option}"
|
||||
done
|
||||
i=1
|
||||
maxdom=6
|
||||
while :; do
|
||||
maxdom=$((maxdom - 1))
|
||||
[ $maxdom -gt 0 ] || break
|
||||
eval option=\"\$dns_search_domain_${i}\" || break
|
||||
[ "${option}" ] || break
|
||||
i=$((i + 1))
|
||||
echo "search ${option}"
|
||||
done
|
||||
} | /sbin/resolvconf -a "${dev}"
|
||||
;;
|
||||
dns-down)
|
||||
/sbin/resolvconf -d "${dev}" -f
|
||||
;;
|
||||
esac
|
||||
85
distro/dns-scripts/resolvconf_file-dns-updown.sh
Normal file
85
distro/dns-scripts/resolvconf_file-dns-updown.sh
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Simple OpenVPN up/down script for modifying /etc/resolv.conf
|
||||
# (C) Copyright 2024 OpenVPN Inc <sales@openvpn.net>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Example env from openvpn (most are not applied):
|
||||
#
|
||||
# dev tun0
|
||||
# script_type dns-up
|
||||
# dns_search_domain_1 mycorp.in
|
||||
# dns_search_domain_2 eu.mycorp.com
|
||||
# dns_server_1_address_1 192.168.99.254
|
||||
# dns_server_1_address_2 fd00::99:53
|
||||
# dns_server_1_port_1 53
|
||||
# dns_server_1_port_2 53
|
||||
# dns_server_1_resolve_domain_1 mycorp.in
|
||||
# dns_server_1_resolve_domain_2 eu.mycorp.com
|
||||
# dns_server_1_dnssec true
|
||||
# dns_server_1_transport DoH
|
||||
# dns_server_1_sni dns.mycorp.in
|
||||
#
|
||||
|
||||
set -e +u
|
||||
|
||||
only_standard_server_ports() {
|
||||
i=1
|
||||
while true; do
|
||||
eval addr=\"\$dns_server_${n}_address_${i}\"
|
||||
[ -n "$addr" ] || return 0
|
||||
|
||||
eval port=\"\$dns_server_${n}_port_${i}\"
|
||||
[ -z "$port" -o "$port" = "53" ] || return 1
|
||||
|
||||
i=$(expr $i + 1)
|
||||
done
|
||||
}
|
||||
|
||||
conf=/etc/resolv.conf
|
||||
test -e "$conf" || exit 1
|
||||
case "${script_type}" in
|
||||
dns-up)
|
||||
n=1
|
||||
while :; do
|
||||
eval addr=\"\$dns_server_${n}_address_1\"
|
||||
[ -n "$addr" ] || {
|
||||
echo "setting DNS failed, no compatible server profile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Skip server profiles which require DNSSEC,
|
||||
# secure transport or use a custom port
|
||||
eval dnssec=\"\$dns_server_${n}_dnssec\"
|
||||
eval transport=\"\$dns_server_${n}_transport\"
|
||||
[ -z "$transport" -o "$transport" = "plain" ] \
|
||||
&& [ -z "$dnssec" -o "$dnssec" = "no" ] \
|
||||
&& only_standard_server_ports && break
|
||||
|
||||
n=$(expr $n + 1)
|
||||
done
|
||||
|
||||
eval addr1=\"\$dns_server_${n}_address_1\"
|
||||
eval addr2=\"\$dns_server_${n}_address_2\"
|
||||
eval addr3=\"\$dns_server_${n}_address_3\"
|
||||
text="### openvpn ${dev} begin ###\n"
|
||||
text="${text}nameserver $addr1\n"
|
||||
test -z "$addr2" || text="${text}nameserver $addr2\n"
|
||||
test -z "$addr3" || text="${text}nameserver $addr3\n"
|
||||
|
||||
test -z "$dns_search_domain_1" || {
|
||||
for i in $(seq 1 6); do
|
||||
eval domains=\"$domains\$dns_search_domain_${i} \" || break
|
||||
done
|
||||
text="${text}search $domains\n"
|
||||
}
|
||||
text="${text}### openvpn ${dev} end ###"
|
||||
text="${text}\n$(cat ${conf})"
|
||||
|
||||
echo "${text}" > "${conf}"
|
||||
;;
|
||||
dns-down)
|
||||
sed -i'' -e "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf"
|
||||
;;
|
||||
esac
|
||||
240
distro/dns-scripts/systemd-dns-updown.sh
Normal file
240
distro/dns-scripts/systemd-dns-updown.sh
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# dns-updown - add/remove openvpn provided DNS information
|
||||
#
|
||||
# Copyright (C) 2024 OpenVPN Inc <sales@openvpn.net>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Add/remove openvpn DNS settings from the env into/from
|
||||
# the system. Supported backends in this order:
|
||||
#
|
||||
# * systemd-resolved
|
||||
# * resolvconf
|
||||
# * /etc/resolv.conf file
|
||||
#
|
||||
# Example env from openvpn (not all are always applied):
|
||||
#
|
||||
# dev tun0
|
||||
# script_type dns-up
|
||||
# dns_search_domain_1 mycorp.in
|
||||
# dns_search_domain_2 eu.mycorp.com
|
||||
# dns_server_1_address_1 192.168.99.254
|
||||
# dns_server_1_address_2 fd00::99:53
|
||||
# dns_server_1_port_1 53
|
||||
# dns_server_1_port_2 53
|
||||
# dns_server_1_resolve_domain_1 mycorp.in
|
||||
# dns_server_1_resolve_domain_2 eu.mycorp.com
|
||||
# dns_server_1_dnssec true
|
||||
# dns_server_1_transport DoH
|
||||
# dns_server_1_sni dns.mycorp.in
|
||||
#
|
||||
|
||||
function do_resolved_servers {
|
||||
local sni=""
|
||||
local transport_var=dns_server_${n}_transport
|
||||
local sni_var=dns_server_${n}_sni
|
||||
[ "${!transport_var}" = "DoT" ] && sni="#${!sni_var}"
|
||||
|
||||
local i=1
|
||||
local addrs=""
|
||||
while :; do
|
||||
local addr_var=dns_server_${n}_address_${i}
|
||||
local addr="${!addr_var}"
|
||||
[ -n "$addr" ] || break
|
||||
|
||||
local port_var=dns_server_${n}_port_${i}
|
||||
if [ -n "${!port_var}" ]; then
|
||||
if [[ "$addr" =~ : ]]; then
|
||||
addr="[$addr]"
|
||||
fi
|
||||
addrs+="${addr}:${!port_var}${sni} "
|
||||
else
|
||||
addrs+="${addr}${sni} "
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
|
||||
resolvectl dns "$dev" $addrs
|
||||
}
|
||||
|
||||
function do_resolved_domains {
|
||||
local list=""
|
||||
for domain_var in ${!dns_search_domain_*}; do
|
||||
list+="${!domain_var} "
|
||||
done
|
||||
local domain_var=dns_server_${n}_resolve_domain_1
|
||||
if [ -z "${!domain_var}" ]; then
|
||||
resolvectl default-route "$dev" true
|
||||
list+="~."
|
||||
else
|
||||
resolvectl default-route "$dev" false
|
||||
local i=1
|
||||
while :; do
|
||||
domain_var=dns_server_${n}_resolve_domain_${i}
|
||||
[ -n "${!domain_var}" ] || break
|
||||
# Add as split domain (~ prefix), if it doesn't already exist
|
||||
[[ "$list" =~ (^| )"${!domain_var}"( |$) ]] \
|
||||
|| list+="~${!domain_var} "
|
||||
i=$((i+1))
|
||||
done
|
||||
fi
|
||||
|
||||
resolvectl domain "$dev" $list
|
||||
}
|
||||
|
||||
function do_resolved_dnssec {
|
||||
local dnssec_var=dns_server_${n}_dnssec
|
||||
if [ "${!dnssec_var}" = "optional" ]; then
|
||||
resolvectl dnssec "$dev" allow-downgrade
|
||||
elif [ "${!dnssec_var}" = "yes" ]; then
|
||||
resolvectl dnssec "$dev" true
|
||||
else
|
||||
resolvectl dnssec "$dev" false
|
||||
fi
|
||||
}
|
||||
|
||||
function do_resolved_dnsovertls {
|
||||
local transport_var=dns_server_${n}_transport
|
||||
if [ "${!transport_var}" = "DoT" ]; then
|
||||
resolvectl dnsovertls "$dev" true
|
||||
else
|
||||
resolvectl dnsovertls "$dev" false
|
||||
fi
|
||||
}
|
||||
|
||||
function do_resolved {
|
||||
[[ "$(readlink /etc/resolv.conf)" =~ systemd ]] || return 1
|
||||
|
||||
n=1
|
||||
while :; do
|
||||
local addr_var=dns_server_${n}_address_1
|
||||
[ -n "${!addr_var}" ] || {
|
||||
echo "setting DNS failed, no compatible server profile"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Skip server profiles which require DNS-over-HTTPS
|
||||
local transport_var=dns_server_${n}_transport
|
||||
[ -n "${!transport_var}" -a "${!transport_var}" = "DoH" ] || break
|
||||
|
||||
n=$((n+1))
|
||||
done
|
||||
|
||||
if [ "$script_type" = "dns-up" ]; then
|
||||
echo "setting DNS using resolvectl"
|
||||
do_resolved_servers
|
||||
do_resolved_domains
|
||||
do_resolved_dnssec
|
||||
do_resolved_dnsovertls
|
||||
else
|
||||
echo "unsetting DNS using resolvectl"
|
||||
resolvectl revert "$dev"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function only_standard_server_ports {
|
||||
local i=1
|
||||
while :; do
|
||||
local addr_var=dns_server_${n}_address_${i}
|
||||
[ -n "${!addr_var}" ] || return 0
|
||||
|
||||
local port_var=dns_server_${n}_port_${i}
|
||||
[ -z "${!port_var}" -o "${!port_var}" = "53" ] || return 1
|
||||
|
||||
i=$((i+1))
|
||||
done
|
||||
}
|
||||
|
||||
function resolv_conf_compat_profile {
|
||||
local n=1
|
||||
while :; do
|
||||
local server_addr_var=dns_server_${n}_address_1
|
||||
[ -n "${!server_addr_var}" ] || {
|
||||
echo "setting DNS failed, no compatible server profile"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Skip server profiles which require DNSSEC,
|
||||
# secure transport or use a custom port
|
||||
local dnssec_var=dns_server_${n}_dnssec
|
||||
local transport_var=dns_server_${n}_transport
|
||||
[ -z "${!transport_var}" -o "${!transport_var}" = "plain" ] \
|
||||
&& [ -z "${!dnssec_var}" -o "${!dnssec_var}" = "no" ] \
|
||||
&& only_standard_server_ports && break
|
||||
|
||||
n=$((n+1))
|
||||
done
|
||||
return $n
|
||||
}
|
||||
|
||||
function do_resolvconf {
|
||||
[ -x /sbin/resolvconf ] || return 1
|
||||
|
||||
resolv_conf_compat_profile
|
||||
local n=$?
|
||||
|
||||
if [ "$script_type" = "dns-up" ]; then
|
||||
echo "setting DNS using resolvconf"
|
||||
local domains=""
|
||||
for domain_var in ${!dns_search_domain_*}; do
|
||||
domains+="${!domain_var} "
|
||||
done
|
||||
{
|
||||
local maxns=3
|
||||
local server_var=dns_server_${n}_address_*
|
||||
for addr_var in ${!server_var}; do
|
||||
[ $((maxns--)) -gt 0 ] || break
|
||||
echo "nameserver ${!addr_var}"
|
||||
done
|
||||
[ -z "$domains" ] || echo "search $domains"
|
||||
} | /sbin/resolvconf -a "$dev"
|
||||
else
|
||||
echo "unsetting DNS using resolvconf"
|
||||
/sbin/resolvconf -d "$dev"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function do_resolv_conf_file {
|
||||
conf=/etc/resolv.conf
|
||||
test -e "$conf" || exit 1
|
||||
|
||||
resolv_conf_compat_profile
|
||||
local n=$?
|
||||
|
||||
if [ "$script_type" = "dns-up" ]; then
|
||||
echo "setting DNS using resolv.conf file"
|
||||
|
||||
local addr1_var=dns_server_${n}_address_1
|
||||
local addr2_var=dns_server_${n}_address_2
|
||||
local addr3_var=dns_server_${n}_address_3
|
||||
text="### openvpn ${dev} begin ###\n"
|
||||
text="${text}nameserver ${!addr1_var}\n"
|
||||
test -z "${!addr2_var}" || text="${text}nameserver ${!addr2_var}\n"
|
||||
test -z "${!addr3_var}" || text="${text}nameserver ${!addr3_var}\n"
|
||||
|
||||
test -z "$dns_search_domain_1" || {
|
||||
for i in $(seq 1 6); do
|
||||
eval domains=\"$domains\$dns_search_domain_${i} \" || break
|
||||
done
|
||||
text="${text}search $domains\n"
|
||||
}
|
||||
text="${text}### openvpn ${dev} end ###"
|
||||
|
||||
sed -i "1i${text}" "$conf"
|
||||
else
|
||||
echo "unsetting DNS using resolv.conf file"
|
||||
sed -i "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
do_resolved || do_resolvconf || do_resolv_conf_file || {
|
||||
echo "setting DNS failed, no method succeeded"
|
||||
exit 1
|
||||
}
|
||||
|
|
@ -8,9 +8,13 @@ the OpenVPN process.
|
|||
Script Order of Execution
|
||||
-------------------------
|
||||
|
||||
#. ``--dns-updown``
|
||||
|
||||
Executed after TCP/UDP socket bind and TUN/TAP open, before ``--up``.
|
||||
|
||||
#. ``--up``
|
||||
|
||||
Executed after TCP/UDP socket bind and TUN/TAP open.
|
||||
Executed after TCP/UDP socket bind and TUN/TAP open, after ``--dns-updown``.
|
||||
|
||||
#. ``--tls-verify``
|
||||
|
||||
|
|
@ -38,9 +42,13 @@ Script Order of Execution
|
|||
|
||||
Executed in ``--mode server`` mode on client instance shutdown.
|
||||
|
||||
#. ``--dns-updown``
|
||||
|
||||
Executed before TCP/UDP and TUN/TAP close, before ``--down``.
|
||||
|
||||
#. ``--down``
|
||||
|
||||
Executed after TCP/UDP and TUN/TAP close.
|
||||
Executed after TCP/UDP and TUN/TAP close, after ``--dns-updown``.
|
||||
|
||||
#. ``--learn-address``
|
||||
|
||||
|
|
@ -171,7 +179,7 @@ SCRIPT HOOKS
|
|||
client-crresponse cmd
|
||||
|
||||
OpenVPN will write the response of the client into a temporary file.
|
||||
The filename will be passed as an argument to ``cmd``, and the file will be
|
||||
The filename will be passed as an argument to ``cmd``, and the file will
|
||||
automatically deleted by OpenVPN after the script returns.
|
||||
|
||||
The response is passed as is from the client. The script needs to check
|
||||
|
|
@ -233,6 +241,31 @@ SCRIPT HOOKS
|
|||
The ``--client-disconnect`` command is not passed any extra arguments
|
||||
(only those arguments specified in cmd, if any).
|
||||
|
||||
--dns-updown cmd
|
||||
Run command ``cmd``, instead of the default DNS up/down command that comes
|
||||
with openvpn. If ``cmd`` is ``disable`` the ``--dns-updown`` command is not run.
|
||||
|
||||
If you write your own command, please make sure to ignore ``--dns``
|
||||
server profiles that cannot be applied. Port, DNSSEC and secure transport
|
||||
settings need to be adhered to. If split DNS is not possible a full redirect
|
||||
can be used as a fallback. If not all of the server addresses or search domains
|
||||
can be configured, apply them in the order they are listed in.
|
||||
|
||||
Note that ``--dns-updown`` is not supported on all platforms. On Windows DNS
|
||||
will always be set by the service. On Android DNS will be passed via management
|
||||
interface.
|
||||
|
||||
Note that DNS-related ``--dhcp-option``\ s might be converted so that they are
|
||||
available to this hook if no ``--dns`` options exist. If any ``--dns server``
|
||||
option is present, DNS-related ``--dhcp-option``\ s will always be ignored.
|
||||
If an ``--up`` script is defined, foreign_option env vars will be generated
|
||||
from ``--dns`` options and passed to the script. The default ``--dns-updown``
|
||||
command is not run if an ``--up`` script is defined. Both is done for backward
|
||||
compatibility. In case you want to run the ``--dns-updown`` command even if
|
||||
there is an ``--up`` defined, you can define a custom command or use ``force``
|
||||
as ``cmd`` to run the default command. No DNS env vars will be passed to ``--up``
|
||||
in this case.
|
||||
|
||||
--down cmd
|
||||
Run command ``cmd`` after TUN/TAP device close (post ``--user`` UID
|
||||
change and/or ``--chroot`` ). ``cmd`` consists of a path to script (or
|
||||
|
|
@ -659,7 +692,7 @@ instances.
|
|||
names). Set prior to ``--up`` or ``--down`` script execution.
|
||||
|
||||
:code:`dns_*`
|
||||
The ``--dns`` configuration options will be made available to script
|
||||
The ``--dns`` configuration options will be made available to ``--dns-updown``
|
||||
execution through this set of environment variables. Variables appear
|
||||
only if the corresponding option has a value assigned. For the semantics
|
||||
of each individual variable, please refer to the documentation for ``--dns``.
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ AM_CFLAGS = \
|
|||
$(OPTIONAL_LZ4_CFLAGS) \
|
||||
$(OPTIONAL_PKCS11_HELPER_CFLAGS) \
|
||||
$(OPTIONAL_INOTIFY_CFLAGS) \
|
||||
-DPLUGIN_LIBDIR=\"${plugindir}\"
|
||||
-DPLUGIN_LIBDIR=\"${plugindir}\" \
|
||||
-DDEFAULT_DNS_UPDOWN=\"${scriptdir}/dns-updown\"
|
||||
|
||||
if WIN32
|
||||
# we want unicode entry point but not the macro
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "dns.h"
|
||||
#include "socket.h"
|
||||
#include "options.h"
|
||||
#include "run_command.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "win32.h"
|
||||
|
|
@ -262,6 +263,8 @@ clone_dns_options(const struct dns_options *o, struct gc_arena *gc)
|
|||
clone.search_domains = clone_dns_domains(o->search_domains, gc);
|
||||
clone.servers = clone_dns_servers(o->servers, gc);
|
||||
clone.servers_prepull = clone_dns_servers(o->servers_prepull, gc);
|
||||
clone.updown = o->updown;
|
||||
clone.user_set_updown = o->user_set_updown;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
|
@ -548,6 +551,54 @@ run_up_down_service(bool add, const struct options *o, const struct tuntap *tt)
|
|||
send_msg_iservice(o->msg_channel, &nrpt, sizeof(nrpt), &ack, "DNS");
|
||||
}
|
||||
|
||||
#else /* ifdef _WIN32 */
|
||||
|
||||
static void
|
||||
updown_env_set(bool up, const struct dns_options *o, const struct tuntap *tt, struct env_set *es)
|
||||
{
|
||||
setenv_str(es, "dev", tt->actual_name);
|
||||
setenv_str(es, "script_type", up ? "dns-up" : "dns-down");
|
||||
setenv_dns_options(o, es);
|
||||
}
|
||||
|
||||
static int
|
||||
do_run_up_down_command(bool up, const struct dns_options *o, const struct tuntap *tt)
|
||||
{
|
||||
struct gc_arena gc = gc_new();
|
||||
struct argv argv = argv_new();
|
||||
struct env_set *es = env_set_create(&gc);
|
||||
|
||||
updown_env_set(up, o, tt, es);
|
||||
|
||||
argv_printf(&argv, "%s", o->updown);
|
||||
argv_msg(M_INFO, &argv);
|
||||
int res;
|
||||
if (o->user_set_updown)
|
||||
{
|
||||
res = openvpn_run_script(&argv, es, S_EXITCODE, "dns updown");
|
||||
}
|
||||
else
|
||||
{
|
||||
res = openvpn_execve_check(&argv, es, S_EXITCODE, "WARNING: Failed running dns updown");
|
||||
}
|
||||
argv_free(&argv);
|
||||
gc_free(&gc);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
run_up_down_command(bool up, struct options *o, const struct tuntap *tt)
|
||||
{
|
||||
if (!o->dns_options.updown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int status;
|
||||
status = do_run_up_down_command(up, &o->dns_options, tt);
|
||||
msg(M_INFO, "dns %s command exited with status %d", up ? "up" : "down", status);
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
void
|
||||
|
|
@ -666,5 +717,7 @@ run_dns_up_down(bool up, struct options *o, const struct tuntap *tt)
|
|||
|
||||
#ifdef _WIN32
|
||||
run_up_down_service(up, o, tt);
|
||||
#else
|
||||
run_up_down_command(up, o, tt);
|
||||
#endif /* ifdef _WIN32 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ struct dns_options {
|
|||
struct dns_server *servers_prepull;
|
||||
struct dns_server *servers;
|
||||
struct gc_arena gc;
|
||||
const char *updown;
|
||||
bool user_set_updown;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -526,10 +526,12 @@ static const char usage_message[] =
|
|||
" address <addr[:port]> [addr[:port] ...] : server addresses 4/6\n"
|
||||
" resolve-domains <domain> [domain ...] : split domains\n"
|
||||
" dnssec <yes|no|optional> : option to use DNSSEC\n"
|
||||
" type <DoH|DoT> : query server over HTTPS / TLS\n"
|
||||
" transport <DoH|DoT> : query server over HTTPS / TLS\n"
|
||||
" sni <domain> : DNS server name indication\n"
|
||||
"--dns search-domains <domain> [domain ...]:\n"
|
||||
" Add domains to DNS domain search list\n"
|
||||
"--dns-updown cmd|force|disable : Run cmd as user defined dns config command,\n"
|
||||
" force running the default script or disable running it.\n"
|
||||
"--auth-retry t : How to handle auth failures. Set t to\n"
|
||||
" none (default), interact, or nointeract.\n"
|
||||
"--static-challenge t e [<scrv1|concat>]: Enable static challenge/response protocol using\n"
|
||||
|
|
@ -918,6 +920,10 @@ init_options(struct options *o, const bool init_gc)
|
|||
#ifndef ENABLE_DCO
|
||||
o->disable_dco = true;
|
||||
#endif /* ENABLE_DCO */
|
||||
|
||||
#ifdef ENABLE_DNS_UPDOWN_BY_DEFAULT
|
||||
o->dns_options.updown = DEFAULT_DNS_UPDOWN;
|
||||
#endif /* ENABLE_DNS_UPDOWN_BY_DEFAULT */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -8046,6 +8052,39 @@ add_option(struct options *options,
|
|||
to->ip_win32_defined = true;
|
||||
}
|
||||
#endif /* ifdef _WIN32 */
|
||||
else if (streq(p[0], "dns-updown") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION(OPT_P_SCRIPT);
|
||||
if (!no_more_than_n_args(msglevel, p, 2, NM_QUOTE_HINT))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
struct dns_options *dns = &options->dns_options;
|
||||
if (streq(p[1], "disable"))
|
||||
{
|
||||
dns->updown = NULL;
|
||||
dns->user_set_updown = false;
|
||||
}
|
||||
else if (streq(p[1], "force"))
|
||||
{
|
||||
/* force dns-updown run, even if a --up script is defined */
|
||||
if (dns->user_set_updown == false)
|
||||
{
|
||||
dns->updown = DEFAULT_DNS_UPDOWN;
|
||||
dns->user_set_updown = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (streq(dns->updown, DEFAULT_DNS_UPDOWN))
|
||||
{
|
||||
/* Unset the default command to prevent warnings */
|
||||
dns->updown = NULL;
|
||||
}
|
||||
set_user_script(options, &dns->updown, p[1], p[0], false);
|
||||
dns->user_set_updown = true;
|
||||
}
|
||||
}
|
||||
else if (streq(p[0], "dns") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION(OPT_P_DHCPDNS);
|
||||
|
|
|
|||
Loading…
Reference in a new issue