1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-07-27 13:48:02 +02:00

Restore support for "Override local DNS"

Tailscale allows to override the local DNS settings of a node via
"Override local DNS" [1]. Restore this flag with the same config setting
name `dns.override_local_dns` but disable it by default to align it with
Tailscale's default behaviour.

Tested with Tailscale 1.80.2 and systemd-resolved on Debian 12.

With `dns.override_local_dns: false`:

```
Link 12 (tailscale0)
Current Scopes: DNS
     Protocols: -DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
   DNS Servers: 100.100.100.100
    DNS Domain: tn.example.com ~0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa [snip]
```

With `dns.override_local_dns: true`:

```
Link 12 (tailscale0)
Current Scopes: DNS
     Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
   DNS Servers: 100.100.100.100
    DNS Domain: tn.example.com ~.
```

[1] https://tailscale.com/kb/1054/dns#override-local-dns

Fixes: #2256
This commit is contained in:
Florian Preinstorfer 2025-02-20 16:25:11 +01:00
parent 7891378f57
commit 3367193782
7 changed files with 24 additions and 4 deletions

View File

@ -43,6 +43,8 @@ Note that if an exit route is approved (0.0.0.0/0 or ::/0), both IPv4 and IPv6 w
- It is now possible to inspect running goroutines and take profiles
- View of config, policy, filter, ssh policy per node, connected nodes and
DERPmap
- Restore support for "Override local DNS"
[#2438](https://github.com/juanfont/headscale/pull/2438)
## 0.25.1 (2025-02-25)

View File

@ -274,6 +274,10 @@ dns:
# `hostname.base_domain` (e.g., _myhost.example.com_).
base_domain: example.com
# Whether to use the local DNS settings of a node (default) or override the
# local DNS settings and force the use of Headscale's DNS configuration.
override_local_dns: false
# List of DNS servers to expose to clients.
nameservers:
global:

View File

@ -102,6 +102,7 @@ type Config struct {
type DNSConfig struct {
MagicDNS bool `mapstructure:"magic_dns"`
BaseDomain string `mapstructure:"base_domain"`
OverrideLocalDNS bool `mapstructure:"override_local_dns"`
Nameservers Nameservers
SearchDomains []string `mapstructure:"search_domains"`
ExtraRecords []tailcfg.DNSRecord `mapstructure:"extra_records"`
@ -287,6 +288,7 @@ func LoadConfig(path string, isFile bool) error {
viper.SetDefault("dns.magic_dns", true)
viper.SetDefault("dns.base_domain", "")
viper.SetDefault("dns.override_local_dns", false)
viper.SetDefault("dns.nameservers.global", []string{})
viper.SetDefault("dns.nameservers.split", map[string]string{})
viper.SetDefault("dns.search_domains", []string{})
@ -351,9 +353,9 @@ func validateServerConfig() error {
depr.fatalIfNewKeyIsNotUsed("policy.path", "acl_policy_path")
// Move dns_config -> dns
depr.warn("dns_config.override_local_dns")
depr.fatalIfNewKeyIsNotUsed("dns.magic_dns", "dns_config.magic_dns")
depr.fatalIfNewKeyIsNotUsed("dns.base_domain", "dns_config.base_domain")
depr.fatalIfNewKeyIsNotUsed("dns.override_local_dns", "dns_config.override_local_dns")
depr.fatalIfNewKeyIsNotUsed("dns.nameservers.global", "dns_config.nameservers")
depr.fatalIfNewKeyIsNotUsed("dns.nameservers.split", "dns_config.restricted_nameservers")
depr.fatalIfNewKeyIsNotUsed("dns.search_domains", "dns_config.domains")
@ -616,6 +618,7 @@ func dns() (DNSConfig, error) {
dns.MagicDNS = viper.GetBool("dns.magic_dns")
dns.BaseDomain = viper.GetString("dns.base_domain")
dns.OverrideLocalDNS = viper.GetBool("dns.override_local_dns")
dns.Nameservers.Global = viper.GetStringSlice("dns.nameservers.global")
dns.Nameservers.Split = viper.GetStringMapStringSlice("dns.nameservers.split")
dns.SearchDomains = viper.GetStringSlice("dns.search_domains")
@ -721,7 +724,11 @@ func dnsToTailcfgDNS(dns DNSConfig) *tailcfg.DNSConfig {
cfg.Proxied = dns.MagicDNS
cfg.ExtraRecords = dns.ExtraRecords
cfg.Resolvers = dns.globalResolvers()
if dns.OverrideLocalDNS {
cfg.Resolvers = dns.globalResolvers()
} else {
cfg.FallbackResolvers = dns.globalResolvers()
}
routes := dns.splitResolvers()
cfg.Routes = routes

View File

@ -36,6 +36,7 @@ func TestReadConfig(t *testing.T) {
want: DNSConfig{
MagicDNS: true,
BaseDomain: "example.com",
OverrideLocalDNS: false,
Nameservers: Nameservers{
Global: []string{
"1.1.1.1",
@ -70,7 +71,7 @@ func TestReadConfig(t *testing.T) {
want: &tailcfg.DNSConfig{
Proxied: true,
Domains: []string{"example.com", "test.com", "bar.com"},
Resolvers: []*dnstype.Resolver{
FallbackResolvers: []*dnstype.Resolver{
{Addr: "1.1.1.1"},
{Addr: "1.0.0.1"},
{Addr: "2606:4700:4700::1111"},
@ -101,6 +102,7 @@ func TestReadConfig(t *testing.T) {
want: DNSConfig{
MagicDNS: false,
BaseDomain: "example.com",
OverrideLocalDNS: false,
Nameservers: Nameservers{
Global: []string{
"1.1.1.1",
@ -135,7 +137,7 @@ func TestReadConfig(t *testing.T) {
want: &tailcfg.DNSConfig{
Proxied: false,
Domains: []string{"example.com", "test.com", "bar.com"},
Resolvers: []*dnstype.Resolver{
FallbackResolvers: []*dnstype.Resolver{
{Addr: "1.1.1.1"},
{Addr: "1.0.0.1"},
{Addr: "2606:4700:4700::1111"},
@ -254,6 +256,7 @@ func TestReadConfigFromEnv(t *testing.T) {
configEnv: map[string]string{
"HEADSCALE_DNS_MAGIC_DNS": "true",
"HEADSCALE_DNS_BASE_DOMAIN": "example.com",
"HEADSCALE_DNS_OVERRIDE_LOCAL_DNS": "false",
"HEADSCALE_DNS_NAMESERVERS_GLOBAL": `1.1.1.1 8.8.8.8`,
"HEADSCALE_DNS_SEARCH_DOMAINS": "test.com bar.com",
@ -274,6 +277,7 @@ func TestReadConfigFromEnv(t *testing.T) {
want: DNSConfig{
MagicDNS: true,
BaseDomain: "example.com",
OverrideLocalDNS: false,
Nameservers: Nameservers{
Global: []string{"1.1.1.1", "8.8.8.8"},
Split: map[string][]string{

View File

@ -7,6 +7,7 @@ dns:
magic_dns: true
base_domain: example.com
override_local_dns: false
nameservers:
global:
- 1.1.1.1

View File

@ -7,6 +7,7 @@ dns:
magic_dns: false
base_domain: example.com
override_local_dns: false
nameservers:
global:
- 1.1.1.1

View File

@ -23,6 +23,7 @@ func DefaultConfigEnv() map[string]string {
"HEADSCALE_PREFIXES_V6": "fd7a:115c:a1e0::/48",
"HEADSCALE_DNS_BASE_DOMAIN": "headscale.net",
"HEADSCALE_DNS_MAGIC_DNS": "true",
"HEADSCALE_DNS_OVERRIDE_LOCAL_DNS": "false",
"HEADSCALE_DNS_NAMESERVERS_GLOBAL": "127.0.0.11 1.1.1.1",
"HEADSCALE_PRIVATE_KEY_PATH": "/tmp/private.key",
"HEADSCALE_NOISE_PRIVATE_KEY_PATH": "/tmp/noise_private.key",