Good day.
I try to implement a simple DNS server through idDNSServer and idDNSResolver .
//Запускаем сервер procedure TMainForm.Button_StartClick(Sender: TObject); begin MainForm.IdDNSResolver.Host:='8.8.8.8'; MainForm.IdDNSServer.UDPTunnel.OnBeforeQuery:=IdDNSServerUDPTunnelBeforeQuery; MainForm.IdDNSServer.UDPTunnel.DefaultPort:=53; MainForm.IdDNSServer.Active:=True; end; In the Windows command line, type nslookup google.ru 127.0.0.1
We catch the query with our DNS server:
//Заменить спец. символы на точки. function ReplaceSpecSymbol(S: String): String; var i: Integer; begin for i:=1 to Length(S) do if Char(S[i]) in [#1..#31] then S[i]:=#46; Delete(S,1,1); //Убираем первую точку. S:=Copy(S,1,Pos(#0,S)-1); //Убираем все что после домена. Result:=S; end; //Обработчик события OnBeforeQuery. Срабатывает каждый раз как ловит пакет. procedure TMainForm.IdDNSServerUDPTunnelBeforeQuery(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader; var ADNSQuery: TIdBytes); var S: String; i: Integer; ABufferHeader, ABufferQuery: TIdBytes; h:TResultRecord; begin S:=ReplaceSpecSymbol(BytesToString(ADNSQuery,12)); MainForm.Memo_Log.Lines.Add(S); if Pos('in-addr.arpa',S)=0 then begin MainForm.IdDNSResolver.QueryType:=[qtA]; MainForm.IdDNSResolver.Resolve(S); //Отправляем наш запрос, через idDNSResolver for i:=0 to MainForm.idDNSResolver.QueryResult.Count-1 do begin if IdDNSResolver.QueryResult[i].RecType=qtA then begin S:=TARecord(IdDNSResolver.QueryResult[i]).IPAddress; Memo_Log.Lines.Add('IdDNSResolver qtA: '+S); end; {//Это просто пробовал получить овтет в формате TXT. Получает. if IdDNSResolver.QueryResult[i].RecType=qtTXT then begin S:=TTextRecord(IdDNSResolver.QueryResult[i]).Text.Strings[0]; Memo_Log.Lines.Add('IdDNSResolver qtTXT: '+S); end;} end; //Заменяем заголовки для того что бы совпал ID пакета. MainForm.IdDNSResolver.DNSHeader.ID:=ADNSHeader.ID; //Тут подставляем наш ID. MainForm.IdDNSResolver.DNSHeader.Qr:=1; //Тут ставим 1, помечая тем самым что это ответный пакет. MainForm.IdDNSResolver.DNSHeader.AA:=ADNSHeader.AA; MainForm.IdDNSResolver.DNSHeader.ANCount:=ADNSHeader.ANCount; MainForm.IdDNSResolver.DNSHeader.ARCount:=ADNSHeader.ARCount; MainForm.IdDNSResolver.DNSHeader.BitCode:=ADNSHeader.BitCode; MainForm.IdDNSResolver.DNSHeader.NSCount:=ADNSHeader.NSCount; MainForm.IdDNSResolver.DNSHeader.OpCode:=ADNSHeader.OpCode; MainForm.IdDNSResolver.DNSHeader.QDCount:=ADNSHeader.QDCount; MainForm.IdDNSResolver.DNSHeader.RA:=ADNSHeader.RA; MainForm.IdDNSResolver.DNSHeader.RCode:=ADNSHeader.RCode; MainForm.IdDNSResolver.DNSHeader.RD:=ADNSHeader.RD; MainForm.IdDNSResolver.DNSHeader.TC:=ADNSHeader.TC; ABufferHeader:=MainForm.IdDNSResolver.DNSHeader.GenerateBinaryHeader; //Переводим заголовок в TidBytes. ABufferQuery:=MainForm.IdDNSResolver.InternalQuery; //<<--Ответ это или нет, непонятно! //Вот тут отправляем заголовок и ответ, но в командную строку ни чего не приходит. ABinding.SendTo(ABinding.PeerIP,ABinding.PeerPort,ABufferHeader+ABufferQuery); end; But the command line does not receive a response from our DNS server. How to implement it correctly?