ficapy
12/19/2017 - 3:44 AM

对特定域名根据内网域名是否可以访问返回特定的ip

对特定域名根据内网域名是否可以访问返回特定的ip

package main

import (
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/miekg/dns"
)

const customeDomain = "xd"
const customeAddr = "10.17.1.71:22"
const targetIP = "8.8.8.8"

func main() {
	udpServer := &dns.Server{Addr: ":53", Net: "udp"}
	tcpServer := &dns.Server{Addr: ":53", Net: "tcp"}

	dns.HandleFunc(".", proxy)

	go func() {
		if err := udpServer.ListenAndServe(); err != nil {
			log.Fatal(err)
		}
	}()

	go func() {
		if err := tcpServer.ListenAndServe(); err != nil {
			log.Fatal(err)
		}
	}()

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	<-sigs

	udpServer.Shutdown()
	tcpServer.Shutdown()
}

func checkAddr(addr string, wait time.Duration) bool {
	d := net.Dialer{Timeout: wait}
	conn, err := d.Dial("tcp", addr)
	if err != nil {
		return false
	}
	defer conn.Close()
	return true
}

func proxy(writer dns.ResponseWriter, msg *dns.Msg) {
	var ip string
	domain := msg.Question[0].Name

	if domain == customeDomain+"." {
		if checkAddr(customeAddr, time.Second*1) {
			a, _ := net.ResolveTCPAddr("tcp", customeAddr)
			ip = a.IP.String()
		} else {
			ip = targetIP
		}
		m := new(dns.Msg)
		m.SetReply(msg)
		m.Authoritative = true
		rr1 := new(dns.A)
		rr1.Hdr = dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 1}
		rr1.A = net.ParseIP(ip)
		m.Answer = []dns.RR{rr1}
		writer.WriteMsg(m)
		return
	}

	c := &dns.Client{Net: "udp"}
	resp, _, err := c.Exchange(msg, "223.5.5.5:53")
	if err != nil {
		dns.HandleFailed(writer, msg)
		return
	}
	writer.WriteMsg(resp)
}