Last active
February 25, 2021 15:03
-
-
Save nirui/d71791822c11b49191ab21afc49171d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This program and script allows you to map the dns request to [domain].<lan-hostname>.svc.lan to <lan-hostname>. | |
// | |
// 1. Setup the OpenWrt. File /etc/config/dhcp | |
// | |
// config dnsmasq | |
// .... | |
// list server '/svc.lan/127.0.0.1#5333' | |
// list rebind_domain 'svc.lan' | |
// | |
// 2. Init.d Script: /etc/init.d/dnsf.sh | |
// | |
// #!/bin/sh /etc/rc.common | |
// USE_PROCD=1 | |
// START=95 | |
// STOP=01 | |
// start_service() { | |
// procd_open_instance | |
// procd_set_param user nobody | |
// procd_set_param command /etc/dnsf | |
// procd_close_instance | |
// } | |
// | |
// 3. Compile: | |
// | |
// $ GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags="-s -w" | |
// $ upx dnsf | |
package main | |
import ( | |
"log" | |
"strings" | |
"sync" | |
"time" | |
"github.com/miekg/dns" | |
) | |
const listen = "127.0.0.1:5333" | |
const queryTimeout = 5 * time.Second | |
const upstream = "localhost:53" | |
const localDomain = ".svc.lan." | |
const localDomainSuffixLen = len(localDomain) - 1 | |
func handler(cli *dns.Client, w dns.ResponseWriter, m *dns.Msg) { | |
defer w.Close() | |
resultMap := make(map[string]string, len(m.Question)) | |
newm := m.Copy() | |
for i := range newm.Question { | |
newQName := newm.Question[i].Name | |
if !strings.HasSuffix(newQName, localDomain) { | |
continue | |
} | |
newQName = newQName[:len(newQName)-localDomainSuffixLen] | |
if len(newQName) <= 0 { | |
continue | |
} | |
lastDim := strings.LastIndex(newQName[:len(newQName)-1], ".") | |
if lastDim >= 0 { | |
newQName = newQName[lastDim+1:] | |
} | |
log.Printf( | |
"Transform domain %s to %s", | |
newm.Question[i].Name, | |
newQName, | |
) | |
resultMap[newQName] = newm.Question[i].Name | |
newm.Question[i].Name = newQName | |
} | |
respond, _, err := cli.Exchange(newm, upstream) | |
if err != nil { | |
log.Printf("Unable to query: %s", err) | |
return | |
} | |
for i := range respond.Question { | |
mapped, has := resultMap[respond.Question[i].Name] | |
if !has { | |
continue | |
} | |
respond.Question[i].Name = mapped | |
} | |
for i := range respond.Answer { | |
answer := respond.Answer[i] | |
answerHeader := answer.Header() | |
mapped, has := resultMap[answerHeader.Name] | |
if !has { | |
continue | |
} | |
answerHeader.Name = mapped | |
respond.Answer[i] = answer | |
} | |
err = w.WriteMsg(respond) | |
if err != nil { | |
log.Printf("Unable to reply: %s", err) | |
return | |
} | |
} | |
func main() { | |
cli := &dns.Client{ | |
Net: "udp", | |
Timeout: queryTimeout, | |
} | |
wg := sync.WaitGroup{} | |
wg.Add(2) | |
defer wg.Wait() | |
go func() { | |
defer wg.Done() | |
log.Print((&dns.Server{ | |
Addr: listen, | |
Net: "udp", | |
Handler: dns.HandlerFunc(func(rw dns.ResponseWriter, m *dns.Msg) { | |
handler(cli, rw, m) | |
}), | |
}).ListenAndServe()) | |
}() | |
go func() { | |
defer wg.Done() | |
log.Print((&dns.Server{ | |
Addr: listen, | |
Net: "tcp", | |
Handler: dns.HandlerFunc(func(rw dns.ResponseWriter, m *dns.Msg) { | |
handler(cli, rw, m) | |
}), | |
}).ListenAndServe()) | |
}() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment