mirror of
https://github.com/netbirdio/netbird.git
synced 2024-12-01 20:43:43 +01:00
db69a0cf9d
Most host managers doesn't support using custom DNS ports. We are now disabling setting it up to avoid unwanted results
161 lines
4.9 KiB
Go
161 lines
4.9 KiB
Go
package dns
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
fileGeneratedResolvConfContentHeader = "# Generated by NetBird"
|
|
fileGeneratedResolvConfSearchBeginContent = "search "
|
|
fileGeneratedResolvConfContentFormat = fileGeneratedResolvConfContentHeader +
|
|
"\n# If needed you can restore the original file by copying back %s\n\nnameserver %s\n" +
|
|
fileGeneratedResolvConfSearchBeginContent + "%s\n"
|
|
)
|
|
|
|
const (
|
|
fileDefaultResolvConfBackupLocation = defaultResolvConfPath + ".original.netbird"
|
|
fileMaxLineCharsLimit = 256
|
|
fileMaxNumberOfSearchDomains = 6
|
|
)
|
|
|
|
var fileSearchLineBeginCharCount = len(fileGeneratedResolvConfSearchBeginContent)
|
|
|
|
type fileConfigurator struct {
|
|
originalPerms os.FileMode
|
|
}
|
|
|
|
func newFileConfigurator() (hostManager, error) {
|
|
return &fileConfigurator{}, nil
|
|
}
|
|
|
|
func (f *fileConfigurator) supportCustomPort() bool {
|
|
return false
|
|
}
|
|
|
|
func (f *fileConfigurator) applyDNSConfig(config hostDNSConfig) error {
|
|
backupFileExist := false
|
|
_, err := os.Stat(fileDefaultResolvConfBackupLocation)
|
|
if err == nil {
|
|
backupFileExist = true
|
|
}
|
|
|
|
if !config.routeAll {
|
|
if backupFileExist {
|
|
err = f.restore()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to configure DNS for this peer using file manager without a Primary nameserver group. Restoring the original file return err: %s", err)
|
|
}
|
|
}
|
|
return fmt.Errorf("unable to configure DNS for this peer using file manager without a nameserver group with all domains configured")
|
|
}
|
|
managerType, err := getOSDNSManagerType()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch managerType {
|
|
case fileManager, netbirdManager:
|
|
if !backupFileExist {
|
|
err = f.backup()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to backup the resolv.conf file")
|
|
}
|
|
}
|
|
default:
|
|
// todo improve this and maybe restart DNS manager from scratch
|
|
return fmt.Errorf("something happened and file manager is not your prefered host dns configurator, restart the agent")
|
|
}
|
|
|
|
var searchDomains string
|
|
appendedDomains := 0
|
|
for _, dConf := range config.domains {
|
|
if dConf.matchOnly || dConf.disabled {
|
|
continue
|
|
}
|
|
if appendedDomains >= fileMaxNumberOfSearchDomains {
|
|
// lets log all skipped domains
|
|
log.Infof("already appended %d domains to search list. Skipping append of %s domain", fileMaxNumberOfSearchDomains, dConf.domain)
|
|
continue
|
|
}
|
|
if fileSearchLineBeginCharCount+len(searchDomains) > fileMaxLineCharsLimit {
|
|
// lets log all skipped domains
|
|
log.Infof("search list line is larger than %d characters. Skipping append of %s domain", fileMaxLineCharsLimit, dConf.domain)
|
|
continue
|
|
}
|
|
|
|
searchDomains += " " + dConf.domain
|
|
appendedDomains++
|
|
}
|
|
content := fmt.Sprintf(fileGeneratedResolvConfContentFormat, fileDefaultResolvConfBackupLocation, config.serverIP, searchDomains)
|
|
err = writeDNSConfig(content, defaultResolvConfPath, f.originalPerms)
|
|
if err != nil {
|
|
err = f.restore()
|
|
if err != nil {
|
|
log.Errorf("attempt to restore default file failed with error: %s", err)
|
|
}
|
|
return err
|
|
}
|
|
log.Infof("created a NetBird managed %s file with your DNS settings. Added %d search domains. Search list: %s", defaultResolvConfPath, appendedDomains, searchDomains)
|
|
return nil
|
|
}
|
|
|
|
func (f *fileConfigurator) restoreHostDNS() error {
|
|
return f.restore()
|
|
}
|
|
|
|
func (f *fileConfigurator) backup() error {
|
|
stats, err := os.Stat(defaultResolvConfPath)
|
|
if err != nil {
|
|
return fmt.Errorf("got an error while checking stats for %s file. Error: %s", defaultResolvConfPath, err)
|
|
}
|
|
|
|
f.originalPerms = stats.Mode()
|
|
|
|
err = copyFile(defaultResolvConfPath, fileDefaultResolvConfBackupLocation)
|
|
if err != nil {
|
|
return fmt.Errorf("got error while backing up the %s file. Error: %s", defaultResolvConfPath, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (f *fileConfigurator) restore() error {
|
|
err := copyFile(fileDefaultResolvConfBackupLocation, defaultResolvConfPath)
|
|
if err != nil {
|
|
return fmt.Errorf("got error while restoring the %s file from %s. Error: %s", defaultResolvConfPath, fileDefaultResolvConfBackupLocation, err)
|
|
}
|
|
|
|
return os.RemoveAll(fileDefaultResolvConfBackupLocation)
|
|
}
|
|
|
|
func writeDNSConfig(content, fileName string, permissions os.FileMode) error {
|
|
log.Debugf("creating managed file %s", fileName)
|
|
var buf bytes.Buffer
|
|
buf.WriteString(content)
|
|
err := os.WriteFile(fileName, buf.Bytes(), permissions)
|
|
if err != nil {
|
|
return fmt.Errorf("got an creating resolver file %s. Error: %s", fileName, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func copyFile(src, dest string) error {
|
|
stats, err := os.Stat(src)
|
|
if err != nil {
|
|
return fmt.Errorf("got an error while checking stats for %s file when copying it. Error: %s", src, err)
|
|
}
|
|
|
|
bytesRead, err := os.ReadFile(src)
|
|
if err != nil {
|
|
return fmt.Errorf("got an error while reading the file %s file for copy. Error: %s", src, err)
|
|
}
|
|
|
|
err = os.WriteFile(dest, bytesRead, stats.Mode())
|
|
if err != nil {
|
|
return fmt.Errorf("got an writing the destination file %s for copy. Error: %s", dest, err)
|
|
}
|
|
return nil
|
|
}
|