Recent

Author Topic: How to use idDnsServer  (Read 1204 times)

aydın

  • Jr. Member
  • **
  • Posts: 77
How to use idDnsServer
« on: September 08, 2022, 09:22:47 pm »
I don't know how to use idDnsServer, one sample code is enough.

Thanks you in advance for your help.
Lazarus 3.0 on Ubuntu 23.04 and Windows 11

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2088
  • Fifty shades of code.
    • Delphi & FreePascal
Re: How to use idDnsServer
« Reply #1 on: September 08, 2022, 10:06:02 pm »
I just tried it once many many years ago and i gave up trying to play with it.
I decided to write my own class for that purpose where "TIdUDPServer" was the "Father"-Class from what my class derived.
Maybe i do find its source somewhere...
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

aydın

  • Jr. Member
  • **
  • Posts: 77
Re: How to use idDnsServer
« Reply #2 on: September 09, 2022, 10:32:04 am »
I created an idUdpServer, assigned 0.0.0.0 as ip, 53 as port.

When I searched www.jixoi.com, I got the answer "b~        wwwjixoicom   ".

How should I read this data and respond back?
Lazarus 3.0 on Ubuntu 23.04 and Windows 11

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2088
  • Fifty shades of code.
    • Delphi & FreePascal
Re: How to use idDnsServer
« Reply #3 on: September 09, 2022, 11:50:41 am »
My source is broken, i do not have my full source anymore but some things of how i did survived:

class Header:
Code: Pascal  [Select][+][-]
  1. type
  2.   TSimpleDNSServer = class(TIdUDPServer)
  3.   protected
  4.     procedure DoUDPRead(AData: TIdBytes; ABinding: TIdSocketHandle); override; // called on receive data
  5.   private
  6.     function ReadPackage(Data: TBytes): TDNSPackage; // read packet
  7.     procedure HandlePackage(var DNSPackage: TDNSPackage; Binding: TIdSocketHandle); // handle packet
  8.     procedure SendDNSPackage(DNSPackage: TDNSPackage; Binding: TIdSocketHandle); // answer
  9.   end;
packet header
Code: Pascal  [Select][+][-]
  1. type
  2.   TDNSHeader = record
  3.     ID: Word; // 16bitu Identifier
  4.     QR: Boolean; // 1bit False=Query True=Response
  5.     OPCODE: Array[0..3] of Boolean; // 4bit 0=Query 1=IQuery 2=Status 3-15 Reserved
  6.     AA: Boolean; // 1bit True in Response - Authoritative Answer
  7.     TC: Boolean; // 1bit TrunCation
  8.     RD: Boolean; // 1bit Recursion Desired
  9.     RA: Boolean; // 1bit Recursion Available
  10.     Z: Array[0..2] of Boolean; // 3bit Reserved --> 0
  11.     RCODE: Array[0..3] of Boolean; // 4bit - Response Code
  12.     QDCOUNT: Word; // 16bitu Number of Entries in Question Section
  13.     ANCOUNT: Word; // 16bitu Number of RRs in Answer Section
  14.     NSCOUNT: Word; // 16bitu Number of Nameserver RRs in the Authority Records Section
  15.     ARCOUNT: Word; // 16bitu Number of RRs in Additional Records Section
  16.   end;
request header
Code: Pascal  [Select][+][-]
  1. type
  2.   TDNSQuestion = record
  3.    QNAME: String; // Query-Name
  4.    NamePointer: Integer; // Compression (etwas komplizierter, erkläre ich später)
  5.    QTYPE: Word; // 16bitu Type of Query
  6.    QCLASS: Word; // 16bitu Class of Query
  7.   end;
content header
Code: Pascal  [Select][+][-]
  1. type
  2.   TResorceRecord = record
  3.     NAME: TBytes; // a domain name to which this resource record pertains.
  4.     RTYPE: Word; // 16bitu Meaning of Data in RDATA
  5.     RCLASS: Word; // 16bitu Class of Data in RDATA
  6.     TTL: LongWord; // 32bitu Cache-Time
  7.     RDLENGTH: Word; // 16bitu Number of Octets in RDATA
  8.     RDATA: TBytes; // data storage
  9.   end;
putting things together
Code: Pascal  [Select][+][-]
  1. type
  2.   TDNSPackage = record
  3.     Header : TDNSHeader;
  4.     Question : Array of TDNSQuestion;
  5.     Answer : Array of TResorceRecord;
  6.   end;

class methods
Code: Pascal  [Select][+][-]
  1. procedure TSimpleDNSServer.DoUDPRead(AData: TIdBytes; ABinding: TIdSocketHandle);
  2. var
  3.   DNSPackage: TDNSPackage;
  4. begin
  5.   DNSPackage := ReadPackage(AData);
  6.   HandlePackage(DNSPackage, ABinding);
  7.   SendDNSPackage(DNSPackage, Binding);
  8.   FreePackage(DNSPackage);
  9. end;

class methods
Code: Pascal  [Select][+][-]
  1. function TSimpleDNSServer.ReadPackage(Data: TBytes): TDNSPackage;
  2. var
  3.   Buffer16bit: TBytes;
  4.   Position: Integer;
  5.   Flags, Flags2: Array[0..7] of Boolean; // byte to bit
  6.   i: Integer;
  7. begin
  8.   SetLength(Buffer16bit, 2);
  9.   Result.Header.ID := BytesToWord(ReadFromBytes(Data, 0, 2));
  10.   Flags := ByteToBits(Data[2]);
  11.   Flags2 := ByteToBits(Data[3]);
  12.   with Result.Header do
  13.   begin
  14.     QR := Flags[0];
  15.     OPCODE[0] := Flags[1];
  16.     OPCODE[1] := Flags[2];
  17.     OPCODE[2] := Flags[3];
  18.     OPCODE[3] := Flags[4];
  19.     AA := Flags[5];
  20.     TC := Flags[6];
  21.     RD := Flags[7];
  22.     RA := Flags2[0];
  23.     Z[0] := Flags2[1];
  24.     Z[1] := Flags2[2];
  25.     Z[2] := Flags2[3];
  26.     RCODE[0] := Flags2[4];
  27.     RCODE[1] := Flags2[5];
  28.     RCODE[2] := Flags2[6];
  29.     RCODE[3] := Flags2[7];
  30.   end;
  31.   Result.Header.QDCOUNT := BytesToWord(ReadFromBytes(Data, 4, 2));
  32.   Result.Header.ANCOUNT := BytesToWord(ReadFromBytes(Data, 6, 2));
  33.   Result.Header.NSCOUNT := BytesToWord(ReadFromBytes(Data, 8, 2));
  34.   Result.Header.ARCOUNT := BytesToWord(ReadFromBytes(Data, 10, 2));
  35.   SetLength(Result.Question, Result.Header.QDCOUNT);
  36.   Position := 12;
  37.   for i := 0 to Result.Header.QDCOUNT-1 do
  38.   begin
  39.     Result.Question[i].QNAME := GetStringInBytes(Data, Position);
  40.     Result.Question[i].NamePointer := Position;
  41.     Position := Position + Length(Result.Question[i].QNAME);
  42.     Result.Question[i].QTYPE := BytesToWord(ReadFromBytes(Data, Position, 2));
  43.     Inc(Position, 2);
  44.     Result.Question[i].QCLASS := BytesToWord(ReadFromBytes(Data, Position, 2));
  45.     Inc(Position, 2);
  46.   end;
  47.   SetLength(Buffer16bit, 0);
  48. end;

class methods
Code: Pascal  [Select][+][-]
  1. procedure TSimpleDNSServer.HandlePackage(var DNSPackage: TDNSPackage; Binding: TIdSocketHandle);
  2. var
  3.   i: Integer;
  4.   CompressionBytes: TBytes;
  5.   Compression1: Array[0..7] of Boolean;
  6.   IPAddress: Array[0..3] of Byte;
  7. begin
  8.   if DNSPackage.Header.QR then
  9.     Exit;
  10.   with DNSPackage do
  11.   begin
  12.     with Header do
  13.     begin
  14.       QR := True;
  15.       AA := False;
  16.       RA := True;
  17.       RCODE := 0;
  18.       ANCOUNT := DNSPackage.Header.QDCOUNT;
  19.     end;
  20.   end;
  21.   SetLength(DNSPackage.Answer, DNSPackage.Header.ANCOUNT);
  22.   for i := 0 to DNSPackage.Header.QDCOUNT-1 do
  23.   begin
  24.     if (DNSPackage.Question[i].QTYPE = 1) and (DNSPackage.Question[i].QCLASS = 1) then
  25.     begin
  26.       with DNSPackage.Answer[i] do
  27.       begin
  28.         IPAddress := DNSPackage.Question[i].QNAME;
  29.         CompressionBytes := WordToBytes(DNSPackage.Question[i].NamePointer);
  30.         Compression1 := ByteToBits(CompressionBytes[0]);
  31.         Compression1[0] := True;
  32.         Compression1[1] := True;
  33.         CompressionBytes[0] := BitsToByte(Compression1);
  34.         SetLength(NAME, 2);
  35.         NAME[0] := CompressionBytes[0];
  36.         NAME[1] := CompressionBytes[1];
  37.         RTYPE := 1;
  38.         RCLASS := 1;
  39.         TTL := 300;
  40.         RDLENGTH := 4;
  41.         SetLength(RDATA, 4);
  42.         RDATA[0] := IPAddress[0];
  43.         RDATA[1] := IPAddress[1];
  44.         RDATA[2] := IPAddress[2];
  45.         RDATA[3] := IPAddress[3];
  46.       end;
  47.     end;
  48.   end;
  49. end;

class methods
Code: Pascal  [Select][+][-]
  1. procedure TSimpleDNSServer.SendDNSPackage(DNSPackage: TDNSPackage; Binding: TIdSocketHandle);
  2. var
  3.   Bytes: TBytes;
  4.   Flags, Flags2: Array[0..7] of Boolean;
  5.   i: Integer;
  6.   Position: Integer;
  7. begin
  8.   SetLength(Bytes, SizeOfPackage(DNSPackage));
  9.   WriteToBytes(Bytes, WordToBytes(DNSPackage.Header.ID), 0);
  10.   with DNSPackage.Header do
  11.   begin
  12.     Flags[0] := QR;
  13.     Flags[1] := OPCODE[0];
  14.     Flags[2] := OPCODE[1];
  15.     Flags[3] := OPCODE[2];
  16.     Flags[4] := OPCODE[3];
  17.     Flags[5] := AA;
  18.     Flags[6] := TC;
  19.     Flags[7] := RD;
  20.     Flags2[0] := RA;
  21.     Flags2[1] := Z[0];
  22.     Flags2[2] := Z[1];
  23.     Flags2[3] := Z[2];
  24.     Flags2[4] := RCODE[0];
  25.     Flags2[5] := RCODE[1];
  26.     Flags2[6] := RCODE[2];
  27.     Flags2[7] := RCODE[3];
  28.   end;
  29.   Bytes[2] := BitsToByte(Flags);
  30.   Bytes[3] := BitsToByte(Flags2);
  31.   WriteToBytes(Bytes, WordToBytes(DNSPackage.Header.QDCOUNT), 4);
  32.   WriteToBytes(Bytes, WordToBytes(DNSPackage.Header.ANCOUNT), 6);
  33.   WriteToBytes(Bytes, WordToBytes(DNSPackage.Header.NSCOUNT), 8);
  34.   WriteToBytes(Bytes, WordToBytes(DNSPackage.Header.ARCOUNT), 10);
  35.   Position := 12;
  36.   for i := 0 to DNSPackage.Header.QDCOUNT-1 do
  37.   begin
  38.     WriteToBytes(Bytes, ToBytes(DNSPackage.Question[i].QNAME), Position);
  39.     Inc(Position, Length(DNSPackage.Question[i].QNAME));
  40.     WriteToBytes(Bytes, WordToBytes(DNSPackage.Question[i].QTYPE), Position);
  41.     Inc(Position, 2);
  42.     WriteToBytes(Bytes, WordToBytes(DNSPackage.Question[i].QCLASS), Position);
  43.     Inc(Position, 2);
  44.   end;
  45.   for i := 0 to DNSPackage.Header.ANCOUNT-1 do
  46.   begin
  47.     Bytes[Position] := DNSPackage.Answer[i].NAME[0];
  48.     inc(Position);
  49.     Bytes[Position] := DNSPackage.Answer[i].NAME[1];
  50.     inc(Position);
  51.     WriteToBytes(Bytes, WordToBytes(DNSPackage.Answer[i].RTYPE), Position);
  52.     Inc(Position, 2);
  53.     WriteToBytes(Bytes, WordToBytes(DNSPackage.Answer[i].RCLASS), Position);
  54.     Inc(Position, 2);
  55.     WriteToBytes(Bytes, LongWordToBytes(DNSPackage.Answer[i].TTL), Position);
  56.     Inc(Position, 4);
  57.     WriteToBytes(Bytes, WordToBytes(DNSPackage.Answer[i].RDLENGTH), Position);
  58.     Inc(Position, 2);
  59.     WriteToBytes(Bytes, DNSPackage.Answer[i].RDATA, Position);
  60.     Inc(Position, DNSPackage.Answer[i].RDLENGTH);
  61.   end;
  62.   Binding.SendTo(Binding.PeerIP, Binding.PeerPort, Bytes);
  63. end;

I hope it helps, more i can not find anymore.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

aydın

  • Jr. Member
  • **
  • Posts: 77
Re: How to use idDnsServer
« Reply #4 on: September 09, 2022, 07:05:31 pm »
Thanks KodeZwerg for the reply.
Lazarus 3.0 on Ubuntu 23.04 and Windows 11

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1314
    • Lebeau Software
Re: How to use idDnsServer
« Reply #5 on: September 09, 2022, 07:05:39 pm »
I don't know how to use idDnsServer, one sample code is enough.

Unfortunately, I'm not aware of any examples for TIdDNSServer.

What exactly are you trying to accomplish?
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

aydın

  • Jr. Member
  • **
  • Posts: 77
Re: How to use idDnsServer
« Reply #6 on: September 09, 2022, 08:06:33 pm »
I want to set up my own DNS server in my local network.
Lazarus 3.0 on Ubuntu 23.04 and Windows 11

loaded

  • Hero Member
  • *****
  • Posts: 825
Re: How to use idDnsServer
« Reply #7 on: September 12, 2022, 07:03:34 am »
Instead of creating your own dns;
There are linux-based dns servers customized just for this job.
Or there may be such a setting on the modem you are using.
I think using them can solve your problem faster.
Check out  loaded on Strava
https://www.strava.com/athletes/109391137

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: How to use idDnsServer
« Reply #8 on: September 14, 2022, 10:13:08 pm »
I guess you probably want to create your own Recursive DNS server, and not an authoratative one. Generally all you need to do for that is parse incoming requests, go through each request individually and cascade down the line of authoratative DNS servers, once you get your record, you can more or less simply paste the result into your response.

DNS protocol specification: https://datatracker.ietf.org/doc/html/rfc1035
For the record and request formats you could checkout my DNS client implementation from AsyncNet: https://github.com/Warfley/AsyncNet/blob/master/src/dns/asyncnet.dns.resrecords.pas and https://github.com/Warfley/AsyncNet/blob/master/src/dns/asyncnet.dns.pas

It's not really hard but a bit tedious

 

TinyPortal © 2005-2018