Hey guys,
I want to do dns proxy package to use in my another app. I will do it by changing dns server address. I will change it to 127.0.0.1 and i will listen localhost when some apps request i will send request by using real wifi then i will transmit the dns respond to app on localhost.
I can send request on wifi and i can respond with dns server that runs on localhost but there are problems.
After i get dns respond packet i want to send it to dns server function with channels(at least i thought it could be like that) then dns server was going to respond app.
These the problems i thought:
- If a request comes in, another request comes before the app responds, the chan changes and I can’t respond correctly
- If a request comes, then I forward that request to the server but if there is no response, I cannot listen to other requests.
and there is my code:
func main() {
server := &dns.Server{Addr: ":53", Net: "udp"}
go server.ListenAndServe()
dns.HandleFunc(".", handleRequest)
ListenToWifi()
select {}
}
I use miekg/dns package in there.
When request comes in handleRequest func will work
I listen wifi with ListenToWifi() func
func handleRequest(w dns.ResponseWriter, req *dns.Msg) {
resp := new(dns.Msg)
resp.SetReply(req)
SendPacketFromLocalHost(req.Id, req.Question[0].Name)
w.WriteMsg(resp)
}
func SendPacketFromLocalHost(id uint16, domain string) {
// Open device
handle, err := pcap.OpenLive(`\Device\NPF_Loopback`, 1024, false, 0)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
SendPacket(handle, id, domain)
}
func ListenToWifi() {
// Open device
handle, err := pcap.OpenLive(`\Device\NPF_{<Device-Hardw-Id>}`, 2048, false, 100*time.Millisecond)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
// UDP Layer
udpLayer := packet.Layer(layers.LayerTypeUDP)
if udpLayer == nil {
continue
}
_, ok := udpLayer.(*layers.UDP)
if !ok {
continue
}
// DNS Layer
dnsLayer := packet.Layer(layers.LayerTypeDNS)
if dnsLayer == nil {
continue
}
dns, ok := dnsLayer.(*layers.DNS)
if !ok {
continue
}
domainName := string([]byte(dns.Questions[0].Name))
log.Printf("%s 0x%x \n", domainName, dns.ID)
}
}
func SendPacket(handle *pcap.Handle, dnsID uint16, domainNames ...string) {
// Used for loopback interface
lo := layers.Loopback{
Family: layers.ProtocolFamilyIPv4,
}
// Create ip layer
ip := layers.IPv4{
Version: 4,
TTL: 128,
SrcIP: net.IP{192, 168, 20, 55}, // router ip
DstIP: net.IP{192, 168, 20, 1}, // my ip
Protocol: layers.IPProtocolUDP,
}
// Create udp layer
udp := layers.UDP{
SrcPort: 65444,
DstPort: 53,
}
udp.SetNetworkLayerForChecksum(&ip)
questions := []layers.DNSQuestion{}
for _, d := range domainNames {
qst := layers.DNSQuestion{
Name: []byte(d),
Type: layers.DNSTypeA,
Class: layers.DNSClassIN,
}
questions = append(questions, qst)
}
dns := layers.DNS{
BaseLayer: layers.BaseLayer{},
ID: dnsID,
QR: false,
OpCode: 0,
AA: false,
TC: false,
RD: true,
RA: true,
Z: 0,
ResponseCode: 0,
QDCount: 1,
ANCount: 0,
NSCount: 0,
ARCount: 0,
Questions: questions,
}
buffer := gopacket.NewSerializeBuffer()
options := gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
if err = gopacket.SerializeLayers(buffer, options,
&lo,
&ip,
&udp,
&dns,
); err != nil {
fmt.Printf("[-] Serialize error: %s\n", err.Error())
return
}
outgoingPacket := buffer.Bytes()
if err = handle.WritePacketData(outgoingPacket); err != nil {
fmt.Printf("[-] Error while sending: %s\n", err.Error())
return
}
}
I thought that i was going to use chans and when a request comes in i was going to send domain name with channel in handleRequest() after i get response i was going to send response to app.
Do you know guys how can i achieve it?
thx for helping