mirror of
https://github.com/tailscale/tailscale.git
synced 2024-12-04 15:35:38 +00:00
411c6c316c
Currently only search domains are stored. This was an oversight (under?) on my part. As things are now, when MagicDNS is on and "Override local DNS" is off, the dns forwarder has to timeout before names resolve. This introduces a pretty annoying lang that makes everything feel extremely slow. You will also see an error: "upstream nameservers not set". I tested with "Override local DNS" on and off. In both situations things seem to function as expected (and quickly). Signed-off-by: Aaron Bieber <aaron@bolddaemon.com>
162 lines
3.5 KiB
Go
162 lines
3.5 KiB
Go
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build openbsd
|
|
// +build openbsd
|
|
|
|
package dns
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"inet.af/netaddr"
|
|
"tailscale.com/types/logger"
|
|
"tailscale.com/util/dnsname"
|
|
)
|
|
|
|
func newResolvdManager(logf logger.Logf, interfaceName string) (*resolvdManager, error) {
|
|
return &resolvdManager{
|
|
logf: logf,
|
|
ifName: interfaceName,
|
|
fs: directFS{},
|
|
}, nil
|
|
}
|
|
|
|
// resolvdManager is an OSConfigurator which uses route(1) to teach OpenBSD's
|
|
// resolvd(8) about DNS servers.
|
|
type resolvdManager struct {
|
|
logf logger.Logf
|
|
ifName string
|
|
fs directFS
|
|
}
|
|
|
|
func (m *resolvdManager) SetDNS(config OSConfig) error {
|
|
args := []string{
|
|
"nameserver",
|
|
m.ifName,
|
|
}
|
|
|
|
origResolv, err := m.readAndCopy(resolvConf, backupConf, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
newResolvConf := removeSearchLines(origResolv)
|
|
|
|
for _, ns := range config.Nameservers {
|
|
args = append(args, ns.String())
|
|
}
|
|
|
|
var newSearch = []string{
|
|
"search",
|
|
}
|
|
for _, s := range config.SearchDomains {
|
|
newSearch = append(newSearch, s.WithoutTrailingDot())
|
|
}
|
|
|
|
newResolvConf = append(newResolvConf, []byte(strings.Join(newSearch, " "))...)
|
|
|
|
err = m.fs.WriteFile(resolvConf, newResolvConf, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd := exec.Command("/sbin/route", args...)
|
|
return cmd.Run()
|
|
}
|
|
|
|
func (m *resolvdManager) SupportsSplitDNS() bool {
|
|
return false
|
|
}
|
|
|
|
func (m *resolvdManager) GetBaseConfig() (OSConfig, error) {
|
|
cfg, err := m.readResolvConf()
|
|
if err != nil {
|
|
return OSConfig{}, err
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func (m *resolvdManager) Close() error {
|
|
// resolvd handles teardown of nameservers so we only need to write back the original
|
|
// config and be done.
|
|
|
|
_, err := m.readAndCopy(backupConf, resolvConf, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return m.fs.Remove(backupConf)
|
|
}
|
|
|
|
func (m *resolvdManager) readAndCopy(a, b string, mode os.FileMode) ([]byte, error) {
|
|
orig, err := m.fs.ReadFile(a)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = m.fs.WriteFile(b, orig, mode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return orig, nil
|
|
}
|
|
|
|
func (m resolvdManager) readResolvConf() (config OSConfig, err error) {
|
|
b, err := m.fs.ReadFile(resolvConf)
|
|
if err != nil {
|
|
return OSConfig{}, err
|
|
}
|
|
|
|
scanner := bufio.NewScanner(bytes.NewReader(b))
|
|
for scanner.Scan() {
|
|
line := strings.TrimSpace(scanner.Text())
|
|
|
|
// resolvd manages "nameserver" lines, we only need to handle
|
|
// "search".
|
|
if strings.HasPrefix(line, "search") {
|
|
domain := strings.TrimPrefix(line, "search")
|
|
domain = strings.TrimSpace(domain)
|
|
fqdn, err := dnsname.ToFQDN(domain)
|
|
if err != nil {
|
|
return OSConfig{}, fmt.Errorf("parsing search domains %q: %w", line, err)
|
|
}
|
|
config.SearchDomains = append(config.SearchDomains, fqdn)
|
|
continue
|
|
}
|
|
|
|
if strings.HasPrefix(line, "nameserver") {
|
|
s := strings.TrimPrefix(line, "nameserver")
|
|
parts := strings.Split(s, " # ")
|
|
if len(parts) == 0 {
|
|
return OSConfig{}, err
|
|
}
|
|
nameserver := strings.TrimSpace(parts[0])
|
|
ip, err := netaddr.ParseIP(nameserver)
|
|
if err != nil {
|
|
return OSConfig{}, err
|
|
}
|
|
config.Nameservers = append(config.Nameservers, ip)
|
|
continue
|
|
}
|
|
}
|
|
|
|
if err = scanner.Err(); err != nil {
|
|
return OSConfig{}, err
|
|
}
|
|
|
|
return config, nil
|
|
}
|
|
|
|
func removeSearchLines(orig []byte) []byte {
|
|
re := regexp.MustCompile(`(?m)^search\s+.+$`)
|
|
return re.ReplaceAll(orig, []byte(""))
|
|
}
|