Pull request 2382: AGDNS-2714-tls-config

Merge in DNS/adguard-home from AGDNS-2714-tls-config to master

Squashed commit of the following:

commit 073e5ec367db02690e9527602a1da6bfd29321a0
Merge: 18f38c9d4 4d258972d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Apr 16 18:25:23 2025 +0300

    Merge branch 'master' into AGDNS-2714-tls-config

commit 18f38c9d44337752c6d0f09142658f374de0979f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Apr 11 15:02:00 2025 +0300

    dnsforward: imp docs

commit ed56d3c2bc239bdc9af000d847721c4c43d173a3
Merge: 3ef281ea2 1cc6c00e4
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Apr 10 17:25:08 2025 +0300

    Merge branch 'master' into AGDNS-2714-tls-config

commit 3ef281ea28dc1fcab0a1291fb3221e6324077a10
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Apr 10 17:24:29 2025 +0300

    all: imp docs

commit b75f2874a816d4814d218c3b062d532f02e26ca5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Apr 7 17:16:59 2025 +0300

    dnsforward: imp code

commit 8ab17b96bca957a172062faaa23b72d5c7ed4d0d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Apr 4 21:26:37 2025 +0300

    all: imp code

commit 1abce97b50fe0406dd1ec85b96a0f99b633325cc
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Apr 2 18:22:15 2025 +0300

    home: imp code

commit debf710f4ebbdfe3e4d2f15b1adcf6b86f8dfc0d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Apr 1 14:52:21 2025 +0300

    home: imp code

commit 4aa26f15b721f2a3f32da29b3f664a02bc5a8608
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Apr 1 14:16:16 2025 +0300

    all: imp code

commit 1a3e72f7a1276f9f797caf9b615f8a552cc9e988
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 31 21:22:40 2025 +0300

    all: imp code

commit 776ab824aef18ea27b59c02ebfc8620c715a867e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Mar 27 14:00:33 2025 +0300

    home: tls config mu

commit 9ebf912f530181043df5c583e82291484996429a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Mar 26 18:58:47 2025 +0300

    all: tls config
This commit is contained in:
Stanislav Chzhen
2025-04-16 18:57:04 +03:00
parent 4d258972d1
commit 3521e8ed9f
21 changed files with 412 additions and 293 deletions

View File

@@ -6,6 +6,7 @@ import (
"net/netip"
"os"
"path/filepath"
"slices"
"sync"
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
@@ -23,6 +24,7 @@ import (
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/timeutil"
"github.com/google/go-cmp/cmp"
"github.com/google/renameio/v2/maybe"
yaml "gopkg.in/yaml.v3"
)
@@ -263,28 +265,116 @@ type dnsConfig struct {
HostsFileEnabled bool `yaml:"hostsfile_enabled"`
}
// tlsConfigSettings is the TLS configuration for DNS-over-TLS, DNS-over-QUIC,
// and HTTPS. When adding new properties, update the [tlsConfigSettings.clone]
// and [tlsConfigSettings.setPrivateFieldsAndCompare] methods as necessary.
type tlsConfigSettings struct {
Enabled bool `yaml:"enabled" json:"enabled"` // Enabled is the encryption (DoT/DoH/HTTPS) status
ServerName string `yaml:"server_name" json:"server_name,omitempty"` // ServerName is the hostname of your HTTPS/TLS server
ForceHTTPS bool `yaml:"force_https" json:"force_https"` // ForceHTTPS: if true, forces HTTP->HTTPS redirect
PortHTTPS uint16 `yaml:"port_https" json:"port_https,omitempty"` // HTTPS port. If 0, HTTPS will be disabled
PortDNSOverTLS uint16 `yaml:"port_dns_over_tls" json:"port_dns_over_tls,omitempty"` // DNS-over-TLS port. If 0, DoT will be disabled
PortDNSOverQUIC uint16 `yaml:"port_dns_over_quic" json:"port_dns_over_quic,omitempty"` // DNS-over-QUIC port. If 0, DoQ will be disabled
// Enabled indicates whether encryption (DoT/DoH/HTTPS) is enabled.
Enabled bool `yaml:"enabled" json:"enabled"`
// PortDNSCrypt is the port for DNSCrypt requests. If it's zero,
// DNSCrypt is disabled.
// ServerName is the hostname of the HTTPS/TLS server.
ServerName string `yaml:"server_name" json:"server_name,omitempty"`
// ForceHTTPS, if true, forces an HTTP to HTTPS redirect.
ForceHTTPS bool `yaml:"force_https" json:"force_https"`
// PortHTTPS is the HTTPS port. If 0, HTTPS will be disabled.
PortHTTPS uint16 `yaml:"port_https" json:"port_https,omitempty"`
// PortDNSOverTLS is the DNS-over-TLS port. If 0, DoT will be disabled.
PortDNSOverTLS uint16 `yaml:"port_dns_over_tls" json:"port_dns_over_tls,omitempty"`
// PortDNSOverQUIC is the DNS-over-QUIC port. If 0, DoQ will be disabled.
PortDNSOverQUIC uint16 `yaml:"port_dns_over_quic" json:"port_dns_over_quic,omitempty"`
// PortDNSCrypt is the port for DNSCrypt requests. If it's zero, DNSCrypt
// is disabled.
PortDNSCrypt uint16 `yaml:"port_dnscrypt" json:"port_dnscrypt"`
// DNSCryptConfigFile is the path to the DNSCrypt config file. Must be
// set if PortDNSCrypt is not zero.
// DNSCryptConfigFile is the path to the DNSCrypt config file. Must be set
// if PortDNSCrypt is not zero.
//
// See https://github.com/AdguardTeam/dnsproxy and
// https://github.com/ameshkov/dnscrypt.
DNSCryptConfigFile string `yaml:"dnscrypt_config_file" json:"dnscrypt_config_file"`
// Allow DoH queries via unencrypted HTTP (e.g. for reverse proxying)
// AllowUnencryptedDoH allows DoH queries via unencrypted HTTP (e.g. for
// reverse proxying).
//
// TODO(s.chzhen): Add this option into the Web UI.
AllowUnencryptedDoH bool `yaml:"allow_unencrypted_doh" json:"allow_unencrypted_doh"`
dnsforward.TLSConfig `yaml:",inline" json:",inline"`
// CertificateChain is the PEM-encoded certificate chain. Must be empty if
// [tlsConfigSettings.CertificatePath] is provided.
CertificateChain string `yaml:"certificate_chain" json:"certificate_chain"`
// PrivateKey is the PEM-encoded private key. Must be empty if
// [tlsConfigSettings.PrivateKeyPath] is provided.
PrivateKey string `yaml:"private_key" json:"private_key"`
// CertificatePath is the path to the certificate file. Must be empty if
// [tlsConfigSettings.CertificateChain] is provided.
CertificatePath string `yaml:"certificate_path" json:"certificate_path"`
// PrivateKeyPath is the path to the private key file. Must be empty if
// [tlsConfigSettings.PrivateKey] is provided.
PrivateKeyPath string `yaml:"private_key_path" json:"private_key_path"`
// OverrideTLSCiphers, when set, contains the names of the cipher suites to
// use. If the slice is empty, the default safe suites are used.
OverrideTLSCiphers []string `yaml:"override_tls_ciphers,omitempty" json:"-"`
// CertificateChainData is the PEM-encoded byte data for the certificate
// chain.
CertificateChainData []byte `yaml:"-" json:"-"`
// PrivateKeyData is the PEM-encoded byte data for the private key.
PrivateKeyData []byte `yaml:"-" json:"-"`
// StrictSNICheck controls if the connections with SNI mismatching the
// certificate's ones should be rejected.
StrictSNICheck bool `yaml:"strict_sni_check" json:"-"`
}
// clone returns a deep copy of c.
func (c *tlsConfigSettings) clone() (clone *tlsConfigSettings) {
clone = &tlsConfigSettings{}
*clone = *c
clone.OverrideTLSCiphers = slices.Clone(c.OverrideTLSCiphers)
clone.CertificateChainData = slices.Clone(c.CertificateChainData)
clone.PrivateKeyData = slices.Clone(c.PrivateKeyData)
return clone
}
// setPrivateFieldsAndCompare sets any missing properties in conf to match those
// in c and returns true if TLS configurations are equal. conf must not be be
// nil.
// It sets the following properties because these are not accepted from the
// frontend:
//
// [tlsConfigSettings.AllowUnencryptedDoH]
// [tlsConfigSettings.DNSCryptConfigFile]
// [tlsConfigSettings.OverrideTLSCiphers]
// [tlsConfigSettings.PortDNSCrypt]
//
// The following properties are skipped as they are set by
// [tlsManager.loadTLSConfig]:
//
// [tlsConfigSettings.CertificateChainData]
// [tlsConfigSettings.PrivateKeyData]
func (c *tlsConfigSettings) setPrivateFieldsAndCompare(conf *tlsConfigSettings) (equal bool) {
conf.OverrideTLSCiphers = slices.Clone(c.OverrideTLSCiphers)
// TODO(s.chzhen): Remove this once the frontend supports it.
conf.AllowUnencryptedDoH = c.AllowUnencryptedDoH
conf.DNSCryptConfigFile = c.DNSCryptConfigFile
conf.PortDNSCrypt = c.PortDNSCrypt
// TODO(a.garipov): Define a custom comparer.
return cmp.Equal(c, conf)
}
type queryLogConfig struct {
@@ -649,9 +739,8 @@ func (c *configuration) write(tlsMgr *tlsManager) (err error) {
}
if tlsMgr != nil {
tlsConf := tlsConfigSettings{}
tlsMgr.WriteDiskConfig(&tlsConf)
config.TLS = tlsConf
tlsConf := tlsMgr.config()
config.TLS = *tlsConf
}
if globalContext.stats != nil {