4 Star 25 Fork 11

LingMax / LingMaxDns

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
main.go 16.10 KB
一键复制 编辑 原始数据 按行查看 历史
LingMax 提交于 2024-04-30 09:09 . 1
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
package main
// killall S999LingMaxDns;killall LingMaxDns_linux_mipsle;cd /etc/;wget -O LingMaxDns_linux_mipsle1 http://192.168.1.236/LingMaxDns_linux_mipsle ;mv LingMaxDns_linux_mipsle1 LingMaxDns_linux_mipsle ; chmod 777 LingMaxDns_linux_mipsle;/etc/LingMaxDns_linux_mipsle &
import (
"context"
"encoding/binary"
"log"
"math/rand"
"os"
"os/exec"
"runtime"
"sort"
"strings"
"sync"
"time"
"strconv"
"net"
"golang.org/x/net/dns/dnsmessage"
)
var fmt = log.New(os.Stderr, "", 0)
var logger = log.New(os.Stderr, "httpsproxy:", log.Llongfile|log.LstdFlags)
// 域名信息
type HostInfo struct {
ips map[string]int64 //ip数组ips
utime int64 //更新时间
ysip map[string]string //本地dns解析的ip
}
// IP信息
type DNSADDR struct {
buf *[]byte //FNS查询ID
addr *net.UDPAddr
}
// IP信息
type IpInfo struct {
tcpMs int64 //tcp响应时间
httpMs int64 //http响应时间
pingMs int64 //ping响应时间
ms int64 //最终响应时间
utime int64 //更新时间
}
type ipMs struct {
ip string //ip
ms int64 //响应时间
}
var HOST = map[string]*HostInfo{}
var IPS = map[string]*IpInfo{}
var lock = sync.Mutex{}
var DNSREQ = []*DNSADDR{}
var TCPDNS = map[string]string{
"208.67.222.222": "53",
"114.114.114.114": "53",
"223.5.5.5": "53",
"219.232.32.99": "53",
"222.18.224.1": "53",
"222.199.6.1": "53",
"168.95.192.1": "53",
"210.76.0.2": "53",
"60.10.57.234": "53",
"221.232.129.35": "53",
"218.69.96.12": "53",
"202.106.84.253": "53",
"219.222.48.5": "53",
"60.191.123.52": "53",
"211.161.103.214": "53",
"202.175.113.124": "53",
"202.180.160.1": "53",
"187.130.63.137": "53",
"137.82.1.1": "53",
"204.70.127.127": "53",
"205.171.2.65": "53",
"210.48.77.69": "53",
"212.77.217.193": "53",
"180.92.170.100": "53",
"202.248.20.133": "53",
"202.56.128.30": "53",
"219.252.0.1": "53",
"103.22.248.62": "53",
"183.78.169.111": "53",
"110.35.78.66": "53",
}
func main() {
runtime.GOMAXPROCS(6)
var all_port = 8287 //监听端口
Exedir, r2ee := os.Executable()
fmt = logger
logger.Println("启动..请稍候 -P53 指定使用53端口(默认8287)", Exedir)
for _, v := range os.Args {
if v == "-E" {
Exedir = ""
}
if v == "-P53" {
all_port = int(53)
}
//i = i
}
if r2ee == nil && Exedir != "" {
var cmd *exec.Cmd
for {
fmt.Println("-E 子进程启动中...", Exedir)
if all_port == 53 {
cmd = exec.Command(Exedir, "-E", "-P53")
} else {
cmd = exec.Command(Exedir, "-E")
}
cmd.Start()
cmd.Wait()
}
}
serverDNS, err2 := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: all_port})
if err2 != nil {
fmt.Println("端口监听失败", all_port, err2)
os.Exit(1)
}
defer serverDNS.Close()
etime := timems() + 1000*60*30
utime := timems() + 1000*10
for {
if etime < timems() {
os.Exit(1)
}
buf := make([]byte, 2048)
serverDNS.SetReadDeadline((time.Now().Add(1 * time.Millisecond)))
n, addr, errx := serverDNS.ReadFromUDP(buf)
if !(errx != nil || n < 3) {
buf = buf[:n]
go dnsmsg(buf, addr)
}
goc(func() {
for i := 0; i < len(DNSREQ); i++ {
serverDNS.WriteToUDP(*DNSREQ[i].buf, DNSREQ[i].addr)
}
DNSREQ = []*DNSADDR{}
})
if utime > timems() {
continue
}
goc(func() {
// 请求垃圾回收
runtime.GC()
tt := timems() + 1000*10
for ip, v := range IPS {
if v.utime+1000*60*30 < tt {
delete(IPS, ip)
}
}
for host, v1 := range HOST {
if v1.utime+1000*60*30 < tt {
delete(HOST, host)
} else {
for ip, v2 := range v1.ips {
if v2+1000*60*30 < tt {
delete(v1.ips, ip)
}
}
}
}
})
}
}
// 转发DNS请求
func dnsmsg(buf []byte, addr *net.UDPAddr) {
host := goDNS(buf) //解析DNS请求
dns119x, _ := net.ResolveUDPAddr("udp4", "119.29.29.29:53")
dns119server, err := net.ListenUDP("udp", &net.UDPAddr{}) // 本地随机端口
if err != nil {
return
}
defer dns119server.Close()
dns119server.WriteToUDP(buf, dns119x)
dns119server.SetReadDeadline((time.Now().Add(2 * 1000 * time.Millisecond)))
buf2 := make([]byte, 4096)
n, _, err := dns119server.ReadFromUDP(buf2)
if err != nil || n < 3 {
dns114, _ := net.ResolveUDPAddr("udp4", "8.8.8.8:53")
dns119server2, err2 := net.ListenUDP("udp", &net.UDPAddr{}) // 本地随机端口
if err2 != nil {
return
}
defer dns119server2.Close()
dns119server2.WriteToUDP(buf, dns114)
dns119server2.SetReadDeadline((time.Now().Add(4 * 1000 * time.Millisecond)))
buf2 = make([]byte, 4096)
n, _, err = dns119server2.ReadFromUDP(buf2)
if err != nil || n < 3 {
return
}
}
buf2 = buf2[:n]
go UnpackDNSMessage(host, buf2) //第一次查询也要测速
buf2 = replaceDns(host, buf2) //替换数据包
goc(func() {
DNSREQ = append(DNSREQ, &DNSADDR{buf: &buf2, addr: addr})
})
}
func localDns(host string) {
// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
// 创建一个 Resolver 对象
resolver := net.Resolver{}
// 使用 Resolver 对象进行主机名解析
ipsxx, err := resolver.LookupHost(ctx, host)
// ipsxx, errxx := net.LookupHost(host)
if err != nil {
return
}
ysip := map[string]string{}
for _, ipxx := range ipsxx {
ysip[ipxx] = ipxx
go checkIp(host, ipxx)
}
goc(func() {
sethost(host)
HOST[host].ysip = ysip
})
}
// 替换数据包
func replaceDns(host string, buf []byte) []byte {
ipv4x := ""
ht := int64(1)
for i := 0; i < 30; i++ { //10*50=500ms
goc(func() {
sethost(host)
if HOST[host].utime+1000*3 < timems() {
ht = HOST[host].utime
for _, ipxx := range HOST[host].ysip {
setips(ipxx)
if IPS[ipxx].ms > 0 && IPS[ipxx].ms < 53 {
ipv4x = ipxx //本地dns解析的ip 延迟低于53ms 直接返回 运营商优化过了的
break
}
}
}
})
if ipv4x != "" {
break
}
ipv4x = getHost2Ipv4(host)
if ipv4x != "" {
break
}
if ht == 0 { //首次需要等待
time.Sleep(10 * time.Millisecond)
} else {
break
}
}
goc(func() {
sethost(host)
if HOST[host].utime+1000*30 < timems() {
HOST[host].utime = timems()
if ipv4x == "" {
queryDns(host, buf)
} else {
go checkIp(host, ipv4x)
go localDns(host) //本地dns解析
}
}
})
var msg dnsmessage.Message
err := msg.Unpack(buf)
if err != nil {
return buf
}
// return buf
isIp := false
for i := 0; i < len(msg.Answers); i++ {
if dnsmessage.TypeA == msg.Answers[i].Header.Type && ipv4x != "" {
msg.Answers[i].Header.TTL = 10
msg.Answers[i].Header.Class = dnsmessage.ClassINET
msg.Answers[i].Body.(*dnsmessage.AResource).A = ipToByte(ipv4x)
// cname, cerr := dnsmessage.NewName(host)
// if cerr == nil {
// msg.Answers[i].Header.Name = cname
// }
isIp = true
// msg.Header.RecursionDesired = true // 设置RD标志,表示递归查询
// msg.Header.Questions = append(msg.Header.Questions, dnsmessage.Question{
// Name: dnsmessage.MustNewName(host),
// Type: dnsmessage.TypeA, // 设置查询类型为AAAA
// Class: dnsmessage.ClassINET,
// })
// msg.Answers = []dnsmessage.Resource{msg.Answers[i], msg.Answers[i]}
// break
}
}
if isIp {
buf3, err := msg.Pack()
if err != nil {
return buf
}
// goc(func() {
// setips(ipv4x)
// fmt.Println("解析成功:", host, ipv4x, "延迟", IPS[ipv4x].ms)
// })
return buf3 //只返回一个A记录
}
return buf
}
func ipToByte(ip string) [4]byte {
a := [4]byte{0, 0, 0, 0}
ips := strings.Split(ip, ".")
if len(ips) != 4 {
return a
}
for i := 0; i < len(ips); i++ {
xi, _ := strconv.Atoi(ips[i])
a[i] = byte(xi)
}
return a
}
// 解析DNS请求
func goDNS(buf []byte) string {
var msg dnsmessage.Message
err := msg.Unpack(buf)
if err != nil {
return ""
}
if len(msg.Questions) < 1 {
return ""
}
question := msg.Questions[0]
if dnsmessage.TypeA != question.Type {
return ""
}
host := question.Name.String()
if len(host) < 3 {
return ""
}
if string(host[0]) == "." {
host = host[1:]
}
if string(host[len(host)-1]) == "." {
host = host[:len(host)-1]
}
if len(host) < 3 {
return ""
}
goc(func() {
sethost(host)
if HOST[host].utime < 1 {
HOST[host].utime = timems()
queryDns(host, buf)
// go localDns(host) //本地dns解析
}
})
return host
}
func queryDns(host string, buf []byte) {
if len(buf) < 3 {
return
}
s0 := string(buf[0])
if s0 == "\x00" && s0 == "." {
return
}
sleep := 0
//UDP协议转TCP协议
bufLen := make([]byte, 2)
binary.BigEndian.PutUint16(bufLen, uint16(len(buf)))
tcpbuf := append(bufLen, buf...)
//万一以后不更新程序了 直接请求 我的服务器动态获取节点
go host2ipHttp(host, "", "alidns.lingmax.top", "80", sleep)
for ip, port := range TCPDNS {
sleep++
go TcpDNS(host, ip, port, tcpbuf, sleep)
go host2ipHttp(host, ip, "223.6.6.6", "80", sleep)
}
go localDns(host) //本地dns解析
// var ms runtime.MemStats
// runtime.ReadMemStats(&ms)
// mem := int((ms.Alloc/1024/1024)*10) / 10
// fmt.Println("查询DNS:", host, "当前协程数:", runtime.NumGoroutine(), "当前内存占用:", mem, "MB")
}
// DNS查询 内存查询
func getHost2Ipv4(host string) string {
if len(host) < 3 {
return ""
}
if string(host[0]) == "." {
host = host[1:]
}
if string(host[len(host)-1]) == "." {
host = host[:len(host)-1]
}
ipv4 := ""
goc(func() {
_, ok := HOST[host]
if !ok {
return
}
d1 := []ipMs{}
for ip, _ := range HOST[host].ips {
v, ok2 := IPS[ip]
if !ok2 || v.ms < 1 {
continue
}
d1 = append(d1, ipMs{ms: v.ms, ip: ip})
}
if len(d1) < 1 {
return
}
sort.Slice(d1, func(i, j int) bool {
return d1[i].ms < d1[j].ms
})
ipv4 = d1[0].ip
for _, vv := range d1 {
rand.Seed(time.Now().UnixNano()) //设置随机数种子
min := 1
max := 20
randomNum := rand.Intn(max-min) + min
if randomNum > 10 || vv.ip == ipv4 {
continue
}
if vv.ms < d1[0].ms+50 { //如果相差不超过50ms则随机安排
ipv4 = vv.ip
}
}
})
return ipv4
}
func setMs(v *IpInfo) int64 {
ms := int64(0)
if v.httpMs > 0 {
ms = v.httpMs //http优先
} else if v.tcpMs > 0 {
ms = v.tcpMs * 1 //tcp次之 2倍延迟
} else if v.pingMs > 0 {
ms = v.pingMs * 1 //ping最后 2倍延迟
}
v.ms = ms
return ms
}
// TCPDNS查询
func TcpDNS(host string, ip string, port string, tcpbuf []byte, sleep int) {
time.Sleep(time.Duration(sleep) * time.Nanosecond)
// return //暂时不用
conn, err := net.DialTimeout("tcp", ip+":"+port, 2*1000*time.Millisecond) // 3s timeout
if err != nil {
return
}
defer conn.Close()
conn.Write(tcpbuf)
conn.SetReadDeadline((time.Now().Add(2 * 1000 * time.Millisecond)))
buf := make([]byte, 2048)
len1, err := conn.Read(buf)
if err != nil || len1 < 3 {
return
}
buf = buf[:len1]
buf = buf[2:] // tcp包转UDP包
go UnpackDNSMessage(host, buf)
}
// 解析DNS结果
func UnpackDNSMessage(host string, buf []byte) {
var msg dnsmessage.Message
err := msg.Unpack(buf)
if err != nil {
return
}
ysip := map[string]string{}
for i := 0; i < len(msg.Answers); i++ {
if dnsmessage.TypeA != msg.Answers[i].Header.Type {
continue // 只处理A记录
}
b := msg.Answers[i].Body.(*dnsmessage.AResource).A
if len(b) < 4 {
continue // 无效的A记录
}
ipv4 := strconv.Itoa(int(b[0])) + "." + strconv.Itoa(int(b[1])) + "." + strconv.Itoa(int(b[2])) + "." + strconv.Itoa(int(b[3]))
go checkIp(host, ipv4)
ysip[ipv4] = ipv4
}
goc(func() {
sethost(host)
if len(HOST[host].ysip) < 1 {
HOST[host].ysip = ysip //设置默认原始ip
}
})
}
// 检查IP是否有效
func checkIp(host string, ip string) {
ipx := net.ParseIP(ip)
if ipx == nil || ipx.To4() == nil {
return // 解析失败,不是有效的 IP 地址
}
num, _ := strconv.Atoi(string(ip[0:1]))
if num < 1 {
return
}
if len(ip) < 7 || len(ip) > 15 {
return
}
//垃圾ip 卡死
if ip == "20.205.243.166" || ip == "175.178.31.156" || ip == "157.255.77.80" {
return
}
s3 := string(ip[0:3])
if s3 == "127" || s3 == "10." {
return
}
s7 := string(ip[0:7])
if s7 == "192.168" || s7 == "172.16." || s7 == "172.17." || s7 == "172.18." || s7 == "172.19." || s7 == "172.20." || s7 == "172.21." || s7 == "172.22." || s7 == "172.23." || s7 == "172.24." || s7 == "172.25." || s7 == "172.26." || s7 == "172.27." || s7 == "172.28." || s7 == "172.29." || s7 == "172.30." || s7 == "172.31." {
return
}
goc(func() {
setips(ip)
if IPS[ip].utime+1000*60*2 < timems() {
IPS[ip].utime = timems()
go httpHead(host, ip, 1000)
}
})
}
// ICMP ping
func ping(host string, ip string) {
ts := timems()
laddr := net.IPAddr{IP: net.ParseIP("0.0.0.0")} // 得到本机的IP地址结构
raddr, errxy := net.ResolveIPAddr("ip", ip) // 解析域名得到 IP 地址结构
if errxy != nil {
return
}
conn, err := net.DialIP("ip4:icmp", &laddr, raddr)
if err != nil {
return
}
defer conn.Close()
recv := make([]byte, 1024)
buf := []byte{8, 0, 247, 255, 0, 0, 0, 0}
conn.Write(buf)
conn.SetReadDeadline((time.Now().Add(1 * 1000 * time.Millisecond)))
_, err3 := conn.Read(recv)
pingMs := timems() - ts
if err3 != nil {
pingMs = 0
}
goc(func() {
//处理结果
setips(ip)
sethost(host)
IPS[ip].pingMs = pingMs
if pingMs > 0 {
HOST[host].ips[ip] = timems()
IPS[ip].utime = timems()
}
setMs(IPS[ip])
})
}
// http head
func httpHead(host string, ip string, timeout int64) {
// return //暂时不用
ts := timems()
conn, err := net.DialTimeout("tcp", ip+":80", time.Duration(timeout)*time.Millisecond) // timeout
tcpMs := timems() - ts
if err != nil {
if tcpMs > timeout-10 || tcpMs < 2 {
tcpMs = 0 //给了的时间 如果时间在前答复 证明服务器通信时间就是这个
go ping(host, ip) //重试Ping
}
} else {
defer conn.Close()
}
goc(func() {
//处理结果
setips(ip)
if tcpMs > 0 {
sethost(host)
HOST[host].ips[ip] = timems()
IPS[ip].utime = timems()
}
IPS[ip].tcpMs = tcpMs
setMs(IPS[ip])
})
return
conn.Write([]byte("HEAD / HTTP/1.1\r\nHost: " + host + "\r\nUser-Agent: Mozilla/5.0\r\nAccept: */*\r\nContent-Length: 0\r\n\r\n"))
conn.SetReadDeadline((time.Now().Add(time.Millisecond * 1000 * 16)))
buf := make([]byte, 1024)
len1, err := conn.Read(buf)
httpMs := timems() - ts
if err != nil || len1 < 4 || string(buf[:4]) != "HTTP" {
httpMs = 0
}
goc(func() {
//处理结果
setips(ip)
sethost(host)
if httpMs > 0 {
HOST[host].ips[ip] = timems()
IPS[ip].utime = timems()
}
IPS[ip].httpMs = httpMs
setMs(IPS[ip])
})
}
// 获取毫秒
func timems() int64 {
return time.Now().UnixNano() / 1e6
}
// 如果不存在则初始化
func sethost(host string) {
_, err := HOST[host]
if !err {
HOST[host] = &HostInfo{
ips: map[string]int64{},
utime: 0,
ysip: map[string]string{},
}
}
}
// 如果不存在则初始化
func setips(ip string) {
_, err := IPS[ip]
if !err {
IPS[ip] = &IpInfo{
tcpMs: 0,
httpMs: 0,
pingMs: 0,
ms: 0,
utime: 0,
}
}
}
// 给每个线程暴力加锁 保证线程安全
func goc(fun func()) {
//go (func() {
lock.Lock()
//defer lock.Unlock()
fun()
lock.Unlock()
//})()
}
// http域名解析"223.6.6.6","80"
func host2ipHttp(host string, ip string, dnshost string, dnsport string, sleep int) {
time.Sleep(time.Duration(sleep) * time.Nanosecond)
// return
//暂时不用
conn, err := net.DialTimeout("tcp", dnshost+":"+dnsport, 2*1000*time.Millisecond) // 3s timeout
if err != nil {
return
}
defer conn.Close()
strx := "GET /resolve?name=" + host + "&type=A&short=1&edns_client_subnet=" + ip + " HTTP/1.1\r\nHost: " + dnshost + "\r\nConnection:keep-alive\r\nUser-Agent: Mozilla/5.0\r\nAccept: */*\r\nContent-Length: 0\r\n\r\n"
_, err2 := conn.Write([]byte(strx))
if err2 != nil {
return
}
conn.SetReadDeadline((time.Now().Add(time.Millisecond * 1000 * 2)))
body := make([]byte, 2048)
len1, err := conn.Read(body)
if err != nil || len1 < 3 {
return
}
body = body[:len1]
ss := string(body)
ret := strings.Split(ss, "\r\n\r\n")
if len(ret) < 2 {
return
}
ss = ret[1]
ss = strings.Replace(ss, "\"", "", -1)
if len(ss) < 5 {
return
}
ss = ss[1 : len(ss)-1]
ips := strings.Split(ss, ",")
for i := 0; i < len(ips); i++ {
go checkIp(host, ips[i])
}
}
Go
1
https://gitee.com/xhxx/LingMaxDns.git
git@gitee.com:xhxx/LingMaxDns.git
xhxx
LingMaxDns
LingMaxDns
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891