bedrocktool/utils/dns.go

106 lines
2.1 KiB
Go

//go:build false
package utils
import (
"fmt"
"net"
"github.com/bedrock-tool/bedrocktool/locale"
"github.com/miekg/dns"
"github.com/sirupsen/logrus"
)
var overrideDNS = map[string]bool{
"geo.hivebedrock.network.": true,
}
type DNSServer struct{}
func (d *DNSServer) answerQuery(remote net.Addr, req *dns.Msg) (reply *dns.Msg) {
reply = new(dns.Msg)
answered := false
for _, q := range req.Question {
switch q.Qtype {
case dns.TypeA:
logrus.Infof("Query for %s", q.Name)
if overrideDNS[q.Name] {
host, _, _ := net.SplitHostPort(remote.String())
remoteIP := net.ParseIP(host)
addrs, _ := net.InterfaceAddrs()
var ip string
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.Contains(remoteIP) {
ip = ipnet.IP.String()
}
}
}
if ip == "" {
logrus.Warn("query from outside of own network")
continue
}
rr, err := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, ip))
if err == nil {
reply.Answer = append(reply.Answer, rr)
answered = true
}
}
}
}
// forward to 1.1.1.1 if not intercepted
if !answered {
c, err := dns.DialWithTLS("tcp4", "1.1.1.1:853", nil)
if err != nil {
panic(err)
}
if err = c.WriteMsg(req); err != nil {
panic(err)
}
if reply, err = c.ReadMsg(); err != nil {
panic(err)
}
c.Close()
}
return reply
}
func (d *DNSServer) handler(w dns.ResponseWriter, req *dns.Msg) {
var reply *dns.Msg
switch req.Opcode {
case dns.OpcodeQuery:
reply = d.answerQuery(w.RemoteAddr(), req)
default:
reply = new(dns.Msg)
}
reply.SetReply(req)
w.WriteMsg(reply)
}
func InitDNS() {
if !Options.EnableDNS {
return
}
d := DNSServer{}
dns.HandleFunc(".", d.handler)
server := &dns.Server{Addr: ":53", Net: "udp"}
go func() {
logrus.Infof(locale.Loc("starting_dns", locale.Strmap{"Ip": GetLocalIP()}))
err := server.ListenAndServe()
defer server.Shutdown()
if err != nil {
logrus.Warnf(locale.Loc("failed_to_start_dns", locale.Strmap{"Err": err.Error()}))
logrus.Info(locale.Loc("suggest_bedrockconnect", nil))
}
}()
}