package main

import ( "fmt" "net" )

func main() { fmt.Println("DNS中转服务已启动...")

// 监听本地53端口
pc, err := net.ListenPacket("udp", "0.0.0.0:53")
if err != nil {
	fmt.Println("监听53端口失败:", err)
	return
}
defer pc.Close()

for {
	// 接收DNS请求
	buf := make([]byte, 1024)
	n, addr, err := pc.ReadFrom(buf)
	if err != nil {
		fmt.Println("读取DNS请求失败:", err)
		continue
	}

	// 解析DNS请求
	msg := &dnsMsg{}
	if err := msg.unmarshal(buf[:n]); err != nil {
		fmt.Println("解析DNS请求失败:", err)
		continue
	}

	// 转发DNS请求
	resp, err := forwardDNSRequest(msg)
	if err != nil {
		fmt.Println("转发DNS请求失败:", err)
		continue
	}

	// 发送DNS响应
	if _, err := pc.WriteTo(resp.marshal(), addr); err != nil {
		fmt.Println("发送DNS响应失败:", err)
		continue
	}
}

}

// dnsMsg 表示DNS消息 type dnsMsg struct { ID uint16 Flags uint16 QDCount uint16 ANCount uint16 NSCount uint16 ARCount uint16 Quest []dnsQuestion Answer []dnsRR Auth []dnsRR Extra []dnsRR }

// dnsQuestion 表示DNS查询 type dnsQuestion struct { Name string Type uint16 Class uint16 }

// dnsRR 表示DNS资源记录 type dnsRR struct { Name string Type uint16 Class uint16 TTL uint32 RDLength uint16 Data string }

// unmarshal 从二进制数据中解析DNS消息 func (msg *dnsMsg) unmarshal(data []byte) error { // 解析消息头 msg.ID = (uint16(data[0]) << 8) | uint16(data[1]) msg.Flags = (uint16(data[2]) << 8) | uint16(data[3]) msg.QDCount = (uint16(data[4]) << 8) | uint16(data[5]) msg.ANCount = (uint16(data[6]) << 8) | uint16(data[7]) msg.NSCount = (uint16(data[8]) << 8) | uint16(data[9]) msg.ARCount = (uint16(data[10]) << 8) | uint16(data[11])

// 解析查询部分
cur := 12
for i := 0; i < int(msg.QDCount); i++ {
	name, n := parseDNSName(data, cur)
	cur += n
	qtype := (uint16(data[cur]) << 8) | uint16(data[cur+1])
	qclass := (uint16(data[cur+2]) << 8) | uint16(data[cur+3])
	cur += 4
	msg.Quest = append(msg.Quest, dnsQuestion{Name: name, Type: qtype, Class: qclass})
}

return nil

}

// marshal 将DNS消息转换为二进制数据 func (msg *dnsMsg) marshal() []byte { data := make([]byte, 12) data[0] = byte(msg.ID >> 8) data[1] = byte(msg.ID) data[2] = byte(msg.Flags >> 8) data[3] = byte(msg.Flags) data[4] = byte(msg.QDCount >> 8) data[5] = byte(msg.QDCount) data[6] = byte(msg.ANCount >> 8) data[7] = byte(msg.ANCount) data[8] = byte(msg.NSCount >> 8) data[9] = byte(msg.NSCount) data[10] = byte(msg.ARCount >> 8) data[11] = byte(msg.ARCount)

for _, q := range msg.Quest {
	data = append(data, encodeDNSName(q.Name)...)
	data = append(data, byte(q.Type>>8), byte(q.Type))
	data = append(data, byte(q.Class>>8), byte(q.Class))
}

for _, ans := range msg.Answer {
	data = append(data, encodeDNSName(ans.Name)...)
	data = append(data, byte(ans.Type>>8), byte(ans.Type))
	data = append(data, byte(ans.Class>>8), byte(ans.Class))
	data = append(data, byte(ans.TTL>>24), byte(ans.TTL>>16), byte(ans.TTL>>8), byte(ans.TTL))
	data = append(data, byte(ans.RDLength>>8), byte(ans.RDLength))
	data = append(data, encodeDNSData(ans.Type, ans.Data)...)
}

return data

}

// parseDNSName 从二进制数据中解析DNS域名 func parseDNSName(data []byte, pos int) (string, int) { var name string cur := pos loop: for { len := int(data[cur]) switch len & 0xC0 { case 0x00: name += string(data[cur+1 : cur+1+len]) + "." cur += len + 1 case 0xC0: off := (int(data[cur]&0x3F) << 8) | int(data[cur+1]) n, _ := parseDNSName(data, off) name += n cur += 2 break loop default: cur += len + 1 break loop } } return name, cur - pos }

// encodeDNSName 将DNS域名转换为二进制数据 func encodeDNSName(name string) []byte { var data []byte labels := splitDNSName(name) for _, label := range labels { data = append(data, byte(len(label))) data = append(data, []byte(label)...) } data = append(data, 0) return data }

// splitDNSName 分割DNS域名 func splitDNSName(name string) []string { var labels []string start := 0 for i := 0; i < len(name); i++ { if name[i] == '.' { labels = append(labels, name[start:i]) start = i + 1 } } labels = append(labels, name[start:]) return labels }

// encodeDNSData 将DNS数据转换为二进制数据 func encodeDNSData(qtype uint16, data string) []byte { switch qtype { case 1: // A记录 ip := net.ParseIP(data) if ip == nil { return []byte{} } return []byte(ip.To4()) case 28: // AAAA记录 ip := net.ParseIP(data) if ip == nil { return []byte{} } return []byte(ip.To16()) default: return []byte{} } }

// forwardDNSRequest 转发DNS请求 func forwardDNSRequest(req *dnsMsg) (*dnsMsg, error) { resp := &dnsMsg{ ID: req.ID, Flags: req.Flags, QDCount: req.QDCount, ANCount: 0, NSCount: 0, ARCount: 0, }

for _, q := range req.Quest {
	switch q.Name {
	case "www.baidu.com.":
		resp.Answer = append(resp.Answer, dnsRR{
			Name:     q.Name,
			Type:     q.Type,
			Class:    q.Class,
			TTL:      600,
			RDLength: 4,
			Data:     "119.29.29.29",
		})
	case "www.google.com.":
		resp.Answer = append(resp.Answer, dnsRR{
			Name:     q.Name,
			Type:     q.Type,
			Class:    q.Class,
			TTL:      600,
			RDLength: 4,
			Data:     "118.1.1.1",
		})
	}
}

resp.ANCount = uint16(len(resp.Answer))
return resp, nil
golang 写一个dns中转代码 将wwwbaiducom域名请求到119292929 和 wwwgooglecom 域名请求到118111 要求代码能运行

原文地址: https://www.cveoy.top/t/topic/fnwK 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录