Skip to content

Commit c564aba

Browse files
committed
add useSystemHosts
1 parent 67d0a2d commit c564aba

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

infra/conf/dns.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package conf
22

33
import (
4+
"bufio"
45
"encoding/json"
6+
"os"
7+
"path/filepath"
8+
"runtime"
59
"sort"
610
"strings"
711

@@ -192,6 +196,7 @@ type DNSConfig struct {
192196
DisableCache bool `json:"disableCache"`
193197
DisableFallback bool `json:"disableFallback"`
194198
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
199+
UseSystemHosts bool `json:"useSystemHosts"`
195200
}
196201

197202
type HostAddress struct {
@@ -413,6 +418,15 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
413418
}
414419
config.StaticHosts = append(config.StaticHosts, staticHosts...)
415420
}
421+
if c.UseSystemHosts {
422+
systemHosts, err := readSystemHosts()
423+
if err != nil {
424+
return nil, errors.New("failed to read system hosts").Base(err)
425+
}
426+
for domain, ips := range systemHosts {
427+
config.StaticHosts = append(config.StaticHosts, &dns.Config_HostMapping{Ip: ips, Domain: domain, Type: dns.DomainMatchingType_Full})
428+
}
429+
}
416430

417431
return config, nil
418432
}
@@ -431,3 +445,85 @@ func resolveQueryStrategy(queryStrategy string) dns.QueryStrategy {
431445
return dns.QueryStrategy_USE_IP
432446
}
433447
}
448+
449+
func readSystemHosts() (map[string][][]byte, error) {
450+
var hostsPath string
451+
switch runtime.GOOS {
452+
case "windows":
453+
hostsPath = filepath.Join(os.Getenv("SystemRoot"), "System32", "drivers", "etc", "hosts")
454+
default:
455+
hostsPath = "/etc/hosts"
456+
}
457+
458+
file, err := os.Open(hostsPath)
459+
if err != nil {
460+
return nil, err
461+
}
462+
defer file.Close()
463+
464+
hostsMap := make(map[string][][]byte)
465+
scanner := bufio.NewScanner(file)
466+
for scanner.Scan() {
467+
line := strings.TrimSpace(scanner.Text())
468+
if i := strings.IndexByte(line, '#'); i >= 0 {
469+
// Discard comments.
470+
line = line[0:i]
471+
}
472+
f := getFields(line)
473+
if len(f) < 2 {
474+
continue
475+
}
476+
addr := net.ParseAddress(f[0])
477+
if addr.Family().IsDomain() {
478+
continue
479+
}
480+
ip := addr.IP()
481+
for i := 1; i < len(f); i++ {
482+
domain := strings.TrimSuffix(f[i], ".")
483+
domain = strings.ToLower(domain)
484+
if v, ok := hostsMap[domain]; ok {
485+
hostsMap[domain] = append(v, ip)
486+
} else {
487+
hostsMap[domain] = [][]byte{ip}
488+
}
489+
}
490+
}
491+
if err := scanner.Err(); err != nil {
492+
return nil, err
493+
}
494+
return hostsMap, nil
495+
}
496+
497+
func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
498+
499+
// Count occurrences in s of any bytes in t.
500+
func countAnyByte(s string, t string) int {
501+
n := 0
502+
for i := 0; i < len(s); i++ {
503+
if strings.IndexByte(t, s[i]) >= 0 {
504+
n++
505+
}
506+
}
507+
return n
508+
}
509+
510+
// Split s at any bytes in t.
511+
func splitAtBytes(s string, t string) []string {
512+
a := make([]string, 1+countAnyByte(s, t))
513+
n := 0
514+
last := 0
515+
for i := 0; i < len(s); i++ {
516+
if strings.IndexByte(t, s[i]) >= 0 {
517+
if last < i {
518+
a[n] = s[last:i]
519+
n++
520+
}
521+
last = i + 1
522+
}
523+
}
524+
if last < len(s) {
525+
a[n] = s[last:]
526+
n++
527+
}
528+
return a[0:n]
529+
}

0 commit comments

Comments
 (0)