From patchwork Mon Jul 14 16:08:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4307 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:8e92:b0:671:5a2c:6455 with SMTP id kd18csp1431586mab; Mon, 14 Jul 2025 09:09:19 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCXJMiq/icCBAZ5M9LFfg0RQ8Gw3L3iJNNwJJyfsyK+9uShFMrBYuvii7+k+SuMMCoqtN52F5NG7Pag=@openvpn.net X-Google-Smtp-Source: AGHT+IGtGGfxywUdCwmnyu1wDzm6T+P2oUVNwka5QD934CRkEvKu2xOCTxUDqUeB97x9s2YwYv58 X-Received: by 2002:a05:6870:14c2:b0:2e8:f3b3:cdcf with SMTP id 586e51a60fabf-2ff2670de22mr9576248fac.4.1752509358767; Mon, 14 Jul 2025 09:09:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1752509358; cv=none; d=google.com; s=arc-20240605; b=JKRUlwle10J5e8pVm1d82n71zbn6JV7mJOiiBV0oVqCFkFiISjqhIJdN168BX1ggET 43RmKuS5889XKl/A2LQn/Oay86ATwrTksvcdmNfkO+yM35O3WqEes65TD0LkG3Vby3b1 7AWqbB0JPZ1J2TXfqv7oO9Ua3oF/oqx427PpmrUyANZ4xr05TdcL8jWUcbZVXq/BamdI ZMr0ShY2D7nJ5KlrX8IZBC+7eewhQ/jCcGzJNkjzc6RttpOF5eAktZ+VXk3T1trHqZV1 3hYfEJxUGsOBAVJVwfz8DyTdFXAVyaPJ3OtNKXxfRpZo3XjSFBjDQOC+hWdhs5J2XgXp W18g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=UA9m80OdZVSjX1esMtMOw8cdmJVtE9ks45egMNa6170=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=kS/nzpU27y9m5Ep5d7AQp0521ClY1EtsTGaoaX/3mCixOL+XlusvSSfgGO69aJH/27 mE6CKyymWk95USUW5fmlioZwu4Cib6piXMzHSrYH0U+iH6VHQLe/BIMPPg6vAmhL3Wnr LTzmVWAxMGXt9bXGndzGMRMgTzS9wXNBvaI1kZ/15wcfZRMR0Ai2C0iJzGyV8Mx7MZmY tg3vO4JV/AubiLlyl+xSnsyTgcbuEZSyOtqKaMDaQONtNr+sbgB+NUgO1mgpvCmg6zbK oWOsZQJV/hBcZlQuNNzTYs3WczUTKzmhEL5gIHVPH0QIqRl1r5dWC8U1qQJZfhunLQxR EYgg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=XaARqvjE; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=KO+f23Qv; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZMI70Rg2; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-2ff1119eb18si5498265fac.56.2025.07.14.09.09.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Jul 2025 09:09:18 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=XaARqvjE; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=KO+f23Qv; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZMI70Rg2; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=UA9m80OdZVSjX1esMtMOw8cdmJVtE9ks45egMNa6170=; b=XaARqvjEkfmfEn7zkL2kmCUT9g 6G/buW7Dnpnu/9BAR1Epj50WBMX8AJc+2rZCYbc/N7kEFUtL1zpFyQpzomPDXtECKjU1DMoUatVCa h157NL6gc/6WzdCYEPtH9/Sy751kFOgmwSxKWQG7JUWm/UstC3A7EXJKsDiuYdZ9p9yw=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1ubLju-0001dH-2C; Mon, 14 Jul 2025 16:09:14 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1ubLjs-0001d5-UO for openvpn-devel@lists.sourceforge.net; Mon, 14 Jul 2025 16:09:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=g1pixYM5saKPtJUcXrBwE6kLF2JpxGt3OTOXIOnXHgA=; b=KO+f23QvGrejgktcn4lWCH8kPs MxsWgZEyWFmz58AXqqye7Xpv39aN4kDXuoI6994zt+5Gj08g/mYzjTFAK7rXfmOvKdP60ly0ucZzt oN33wW9g1WnWaUVFGoPKQfhE9091OzlZAP1wR0YX0S5d4uWX8ilzRW89kL2Mm+Phum48=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=g1pixYM5saKPtJUcXrBwE6kLF2JpxGt3OTOXIOnXHgA=; b=ZMI70Rg2eYXYTcetMtKW/R6Hye UBRTptVrWo4xn5nqe41sL5cHY612VXfOtpkKJpctksMU0sHatwl061/echVaw8XzJa3WWu7ELFjX7 Z8YnzSPXChWqmKiO1M9lfLMB6Roo/V/HKzvqNoiYo/4/7rhvqjzFvgsdl7W2ZrvrFGY0=; Received: from [193.149.48.143] (helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1ubLjr-0004Hv-Fs for openvpn-devel@lists.sourceforge.net; Mon, 14 Jul 2025 16:09:12 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.17.1.9/8.17.1.9) with ESMTP id 56EG94Ok007641 for ; Mon, 14 Jul 2025 18:09:04 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 56EG94ib007640 for openvpn-devel@lists.sourceforge.net; Mon, 14 Jul 2025 18:09:04 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Mon, 14 Jul 2025 18:08:21 +0200 Message-ID: <20250714160903.7479-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Heiko Hund When connections go up and down there are situations where search domains of a split DNS connection are either lost, or survive the lifetime of the connction. This can happen when there is also a conn [...] Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1ubLjr-0004Hv-Fs Subject: [Openvpn-devel] [PATCH v3] prevent search domain races with macOS dns-updown X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1837639253305639154?= X-GMAIL-MSGID: =?utf-8?q?1837639253305639154?= From: Heiko Hund When connections go up and down there are situations where search domains of a split DNS connection are either lost, or survive the lifetime of the connction. This can happen when there is also a connection that modifies the global DNS setting. When it backs-up the global settings before modifying them, or when it restores the backup, the search domains could contain or miss VPN domains from other connections, leading to misconfiguration. The fix is to also update the backed-up search domains when a split DNS connection comes up or goes down. That way the backup is always up to date and restoring it will keep the global search domains as expected. Change-Id: Ide2cddad193c636eb440c9752751176dae0a6897 Signed-off-by: Heiko Hund Acked-by: Arne Schwabe --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1073 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Arne Schwabe diff --git a/distro/dns-scripts/macos-dns-updown.sh b/distro/dns-scripts/macos-dns-updown.sh index c15abaa..f0640ee 100644 --- a/distro/dns-scripts/macos-dns-updown.sh +++ b/distro/dns-scripts/macos-dns-updown.sh @@ -29,14 +29,49 @@ [ -z "${dns_vars_file}" ] || . "${dns_vars_file}" itf_dns_key="State:/Network/Service/openvpn-${dev}/DNS" -dns_backup_key="State:/Network/Service/openvpn-${dev}/DnsBackup" -dns_backup_key_pattern="State:/Network/Service/openvpn-.*/DnsBackup" function primary_dns_key { local uuid=$(echo "show State:/Network/Global/IPv4" | /usr/sbin/scutil | grep "PrimaryService" | cut -d: -f2 | xargs) echo "Setup:/Network/Service/${uuid}/DNS" } +function dns_backup_key { + local key="$(echo "list State:/Network/Service/openvpn-.*/DnsBackup" | /usr/sbin/scutil | cut -d= -f2 | xargs)" + if [[ "${key}" =~ no\ key ]]; then + echo "State:/Network/Service/openvpn-${dev}/DnsBackup" + else + echo "${key}" + fi +} + +function property_value { + local key="$1" + local prop="$2" + + [ -n "${key}" -a -n "${prop}" ] || return + + local match_prop="${prop} : (.*)" + local match_array_start="${prop} : " + local match_array_elem="[0-9]* : (.*)" + local match_array_end="}" + local in_array=false + local values="" + + echo "show ${key}" | /usr/sbin/scutil | while read line; do + if [ "${in_array}" = false ] && [[ "${line}" =~ "${match_array_start}" ]]; then + in_array=true + elif [ "${in_array}" = true ] && [[ "${line}" =~ ${match_array_elem} ]]; then + values+="${BASH_REMATCH[1]} " + elif [ "${in_array}" = true ] && [[ "${line}" =~ "${match_array_end}" ]]; then + echo "${values}" + break + elif [[ "${line}" =~ ${match_prop} ]]; then + echo "${BASH_REMATCH[1]}" + break + fi + done +} + function only_standard_server_ports { local i=1 while :; do @@ -73,42 +108,52 @@ } function get_search_domains { - local search_domains="" - local resolver=0 - /usr/sbin/scutil --dns | while read line; do - if [[ "$line" =~ resolver.# ]]; then - resolver=$((resolver+1)) - elif [ "$resolver" = 1 ] && [[ "$line" =~ search.domain ]]; then - search_domains+="$(echo $line | cut -d: -f2 | xargs) " - elif [ "$resolver" -gt 1 ]; then - echo "$search_domains" - break - fi - done + property_value State:/Network/Global/DNS SearchDomains } function set_search_domains { [ -n "$1" ] || return - dns_key=$(primary_dns_key) - search_domains="${1}$(get_search_domains)" + local dns_key=$(primary_dns_key) + local dns_backup_key="$(dns_backup_key)" + local search_domains="${1}$(get_search_domains)" local cmds="" cmds+="get ${dns_key}\n" cmds+="d.add SearchDomains * ${search_domains}\n" cmds+="set ${dns_key}\n" + + if ! [[ "${dns_backup_key}" =~ ${dev}/ ]]; then + # Add the domains to the backup in case the default goes down + local existing="$(property_value ${dns_backup_key} SearchDomains)" + cmds+="get ${dns_backup_key}\n" + cmds+="d.add SearchDomains * ${search_domains} ${existing}\n" + cmds+="set ${dns_backup_key}\n" + fi + echo -e "${cmds}" | /usr/sbin/scutil } function unset_search_domains { [ -n "$1" ] || return - dns_key=$(primary_dns_key) - search_domains="$(get_search_domains)" + local dns_key=$(primary_dns_key) + local dns_backup_key="$(dns_backup_key)" + local search_domains="$(get_search_domains)" search_domains=$(echo $search_domains | sed -e "s/$1//") local cmds="" cmds+="get ${dns_key}\n" cmds+="d.add SearchDomains * ${search_domains}\n" cmds+="set ${dns_key}\n" + + if ! [[ "${dns_backup_key}" =~ ${dev}/ ]]; then + # Remove the domains from the backup for when the default goes down + search_domains="$(property_value ${dns_backup_key} SearchDomains)" + search_domains=$(echo $search_domains | sed -e "s/$1//") + cmds+="get ${dns_backup_key}\n" + cmds+="d.add SearchDomains * ${search_domains}\n" + cmds+="set ${dns_backup_key}\n" + fi + echo -e "${cmds}" | /usr/sbin/scutil } @@ -167,7 +212,8 @@ echo -e "${cmds}" | /usr/sbin/scutil set_search_domains "$search_domains" else - echo list ${dns_backup_key_pattern} | /usr/sbin/scutil | grep -q 'no key' || { + local dns_backup_key="$(dns_backup_key)" + [[ "${dns_backup_key}" =~ ${dev}/ ]] || { echo "setting DNS failed, already redirecting to another tunnel" exit 1 } @@ -207,7 +253,8 @@ unset_search_domains "$search_domains" else # Do not unset if this tunnel did not set/backup DNS before - echo list ${dns_backup_key} | /usr/sbin/scutil | grep -qv 'no key' || return + local dns_backup_key="$(dns_backup_key)" + [[ "${dns_backup_key}" =~ ${dev}/ ]] || return local cmds="" cmds+="get ${dns_backup_key}\n"