Skip to content

Commit 038b2ef

Browse files
CopilotDerLinkman
andauthored
Add MTA-STS support for alias domains (#6972)
* Initial plan * Add MTA-STS support for alias domains Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> * Improve domain normalization and code style in mta-sts.php Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> * Add error handling for idn_to_ascii in mta-sts.php Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> * Add database error handling for alias domain query Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> * Add ACME certificate support for MTA-STS on alias domains Query alias_domain table to find aliases with MTA-STS enabled target domains and request certificates for mta-sts.<alias-domain> subdomains. Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> * compose: bump image tag to 1.95 * Add MTA-STS DNS records display for alias domains in UI When viewing an alias domain's DNS diagnostics, check if the target domain has MTA-STS enabled and display the required DNS records for the alias domain. Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> Co-authored-by: DerLinkman <niklas.meyer@servercow.de>
1 parent 1fe4cd0 commit 038b2ef

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

data/Dockerfiles/acme/acme.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ while true; do
246246
done
247247
VALIDATED_CONFIG_DOMAINS+=("${VALIDATED_CONFIG_DOMAINS_SUBDOMAINS[*]}")
248248
done
249+
250+
# Fetch alias domains where target domain has MTA-STS enabled
251+
if [[ ${AUTODISCOVER_SAN} == "y" ]]; then
252+
SQL_ALIAS_DOMAINS=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT ad.alias_domain FROM alias_domain ad INNER JOIN mta_sts m ON ad.target_domain = m.domain WHERE ad.active = 1 AND m.active = 1" -Bs)
253+
if [[ $? -eq 0 ]]; then
254+
while read alias_domain; do
255+
if [[ -z "${alias_domain}" ]]; then
256+
# ignore empty lines
257+
continue
258+
fi
259+
# Only add mta-sts subdomain for alias domains
260+
if [[ "mta-sts.${alias_domain}" != "${MAILCOW_HOSTNAME}" ]]; then
261+
if check_domain "mta-sts.${alias_domain}"; then
262+
VALIDATED_CONFIG_DOMAINS+=("mta-sts.${alias_domain}")
263+
fi
264+
fi
265+
done <<< "${SQL_ALIAS_DOMAINS}"
266+
fi
267+
fi
249268
fi
250269

251270
if check_domain ${MAILCOW_HOSTNAME}; then

data/web/inc/ajax/dns_diagnostics.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,16 @@
129129
);
130130
}
131131

132-
$mta_sts = mailbox('get', 'mta_sts', $domain);
132+
// Check if domain is an alias domain and get target domain's MTA-STS
133+
$alias_domain_details = mailbox('get', 'alias_domain_details', $domain);
134+
$mta_sts_domain = $domain;
135+
136+
if ($alias_domain_details !== false && !empty($alias_domain_details['target_domain'])) {
137+
// This is an alias domain, check target domain for MTA-STS
138+
$mta_sts_domain = $alias_domain_details['target_domain'];
139+
}
140+
141+
$mta_sts = mailbox('get', 'mta_sts', $mta_sts_domain);
133142
if (count($mta_sts) > 0 && $mta_sts['active'] == 1) {
134143
if (!in_array($domain, $alias_domains)) {
135144
$records[] = array(

data/web/mta-sts.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,30 @@
77
}
88

99
$host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
10-
$domain = str_replace('mta-sts.', '', $host);
10+
$domain = idn_to_ascii(strtolower(str_replace('mta-sts.', '', $host)), 0, INTL_IDNA_VARIANT_UTS46);
11+
12+
// Validate domain or return 404 on error
13+
if ($domain === false || empty($domain)) {
14+
http_response_code(404);
15+
exit;
16+
}
17+
18+
// Check if domain is an alias domain and resolve to target domain
19+
try {
20+
$stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain");
21+
$stmt->execute(array(':domain' => $domain));
22+
$alias_row = $stmt->fetch(PDO::FETCH_ASSOC);
23+
24+
if ($alias_row !== false && !empty($alias_row['target_domain'])) {
25+
// This is an alias domain, use the target domain for MTA-STS lookup
26+
$domain = $alias_row['target_domain'];
27+
}
28+
} catch (PDOException $e) {
29+
// On database error, return 404
30+
http_response_code(404);
31+
exit;
32+
}
33+
1134
$mta_sts = mailbox('get', 'mta_sts', $domain);
1235

1336
if (count($mta_sts) == 0 ||

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ services:
465465
condition: service_started
466466
unbound-mailcow:
467467
condition: service_healthy
468-
image: ghcr.io/mailcow/acme:1.94
468+
image: ghcr.io/mailcow/acme:1.95
469469
dns:
470470
- ${IPV4_NETWORK:-172.22.1}.254
471471
environment:

0 commit comments

Comments
 (0)