Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ The new policy can be used by setting the environment variable
- node FQDNs in the netmap will now contain a dot (".") at the end. This aligns
with behaviour of tailscale.com
[#2503](https://github.com/juanfont/headscale/pull/2503)
- Restore support for "Override local DNS"
[#2438](https://github.com/juanfont/headscale/pull/2438)

## 0.25.1 (2025-02-25)

Expand Down
4 changes: 4 additions & 0 deletions config-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,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:
Expand Down
17 changes: 15 additions & 2 deletions hscontrol/types/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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", true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think https://github.com/juanfont/headscale/pull/2438/files#r2046953908 is correct. I also just ran into this and needed to turn local dns override off.

viper.SetDefault("dns.nameservers.global", []string{})
viper.SetDefault("dns.nameservers.split", map[string]string{})
viper.SetDefault("dns.search_domains", []string{})
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -417,6 +419,12 @@ func validateServerConfig() error {
)
}

if viper.GetBool("dns.override_local_dns") {
if global := viper.GetStringSlice("dns.nameservers.global"); len(global) == 0 {
errorText += "Fatal config error: dns.nameservers.global must be set when dns.override_local_dns is true\n"
}
}

if errorText != "" {
// nolint
return errors.New(strings.TrimSuffix(errorText, "\n"))
Expand Down Expand Up @@ -616,6 +624,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")
Expand Down Expand Up @@ -721,7 +730,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
Expand Down
57 changes: 48 additions & 9 deletions hscontrol/types/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -34,8 +35,9 @@ func TestReadConfig(t *testing.T) {
return dns, nil
},
want: DNSConfig{
MagicDNS: true,
BaseDomain: "example.com",
MagicDNS: true,
BaseDomain: "example.com",
OverrideLocalDNS: false,
Nameservers: Nameservers{
Global: []string{
"1.1.1.1",
Expand Down Expand Up @@ -70,7 +72,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"},
Expand Down Expand Up @@ -99,8 +101,9 @@ func TestReadConfig(t *testing.T) {
return dns, nil
},
want: DNSConfig{
MagicDNS: false,
BaseDomain: "example.com",
MagicDNS: false,
BaseDomain: "example.com",
OverrideLocalDNS: false,
Nameservers: Nameservers{
Global: []string{
"1.1.1.1",
Expand Down Expand Up @@ -135,7 +138,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"},
Expand Down Expand Up @@ -181,6 +184,40 @@ func TestReadConfig(t *testing.T) {
},
wantErr: "",
},
{
name: "dns-override-true-errors",
configPath: "testdata/dns-override-true-error.yaml",
setup: func(t *testing.T) (any, error) {
return LoadServerConfig()
},
wantErr: "Fatal config error: dns.nameservers.global must be set when dns.override_local_dns is true",
},
{
name: "dns-override-true",
configPath: "testdata/dns-override-true.yaml",
setup: func(t *testing.T) (any, error) {
_, err := LoadServerConfig()
if err != nil {
return nil, err
}

dns, err := dns()
if err != nil {
return nil, err
}

return dnsToTailcfgDNS(dns), nil
},
want: &tailcfg.DNSConfig{
Proxied: true,
Domains: []string{"derp2.no"},
Routes: map[string][]*dnstype.Resolver{},
Resolvers: []*dnstype.Resolver{
{Addr: "1.1.1.1"},
{Addr: "1.0.0.1"},
},
},
},
{
name: "policy-path-is-loaded",
configPath: "testdata/policy-path-is-loaded.yaml",
Expand Down Expand Up @@ -254,6 +291,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",

Expand All @@ -272,8 +310,9 @@ func TestReadConfigFromEnv(t *testing.T) {
return dns, nil
},
want: DNSConfig{
MagicDNS: true,
BaseDomain: "example.com",
MagicDNS: true,
BaseDomain: "example.com",
OverrideLocalDNS: false,
Nameservers: Nameservers{
Global: []string{"1.1.1.1", "8.8.8.8"},
Split: map[string][]string{
Expand Down Expand Up @@ -301,7 +340,7 @@ func TestReadConfigFromEnv(t *testing.T) {
conf, err := tt.setup(t)
require.NoError(t, err)

if diff := cmp.Diff(tt.want, conf); diff != "" {
if diff := cmp.Diff(tt.want, conf, cmpopts.EquateEmpty()); diff != "" {
t.Errorf("ReadConfig() mismatch (-want +got):\n%s", diff)
}
})
Expand Down
1 change: 1 addition & 0 deletions hscontrol/types/testdata/base-domain-in-server-url.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ server_url: "https://server.derp.no"
dns:
magic_dns: true
base_domain: derp.no
override_local_dns: false
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ server_url: "https://derp.no"
dns:
magic_dns: true
base_domain: clients.derp.no
override_local_dns: false
16 changes: 16 additions & 0 deletions hscontrol/types/testdata/dns-override-true-error.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
noise:
private_key_path: "private_key.pem"

prefixes:
v6: fd7a:115c:a1e0::/48
v4: 100.64.0.0/10

database:
type: sqlite3

server_url: "https://server.derp.no"

dns:
magic_dns: true
base_domain: derp.no
override_local_dns: true
20 changes: 20 additions & 0 deletions hscontrol/types/testdata/dns-override-true.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
noise:
private_key_path: "private_key.pem"

prefixes:
v6: fd7a:115c:a1e0::/48
v4: 100.64.0.0/10

database:
type: sqlite3

server_url: "https://server.derp.no"

dns:
magic_dns: true
base_domain: derp2.no
override_local_dns: true
nameservers:
global:
- 1.1.1.1
- 1.0.0.1
1 change: 1 addition & 0 deletions hscontrol/types/testdata/dns_full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dns:
magic_dns: true
base_domain: example.com

override_local_dns: false
nameservers:
global:
- 1.1.1.1
Expand Down
1 change: 1 addition & 0 deletions hscontrol/types/testdata/dns_full_no_magic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dns:
magic_dns: false
base_domain: example.com

override_local_dns: false
nameservers:
global:
- 1.1.1.1
Expand Down
4 changes: 3 additions & 1 deletion hscontrol/types/testdata/policy-path-is-loaded.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ policy:
type: file
path: "/etc/policy.hujson"

dns.magic_dns: false
dns:
magic_dns: false
override_local_dns: false
1 change: 1 addition & 0 deletions integration/hsic/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading