Volt- Опубликовано 3 июня, 2016 Поделиться Опубликовано 3 июня, 2016 (изменено) Добрый день. Кинул на форму idUDPServer1 и Memo1 В событии idUDPServer1.OnUDPRead написал: procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin Memo1.Lines.Add(BytesToString(AData,13)); end; в событии Form1.OnCreate написал: procedure TForm1.FormCreate(Sender: TObject); begin idUDPServer1.DefaultPort:=53; idUDPServer1.Active:=True; end; Запускаю проект. Захожу в командную строку Windows и набираю команду: nslookup google.ru 127.0.0.1 В Memo1 появляется DNS запрос, но что то не так с кодировкой. Первая строчка должна выглядеть так "1.0.0.127.in-addr.arpa" а вторая и последующие так "google.ru" Как поправить? Изменено 3 июня, 2016 пользователем Volt- Цитата Ссылка на комментарий
0 Pax Beach Опубликовано 3 июня, 2016 Поделиться Опубликовано 3 июня, 2016 (изменено) 1 час назад, Volt- сказал: В Memo1 появляется DNS запрос, но что то не так с кодировкой. Первая строчка должна выглядеть так "1.0.0.127.in-addr.arpa" а вторая и последующие так "google.ru" Как поправить? Всегда входящие данные нужно обрабатывать на предмет кодировки, длины и некорректных символов. Дальше, наверняка, Вы будете логи писать в базу или куда-то еще, а уязвимости нам в базе не нужны =) Не понятно, что у Вас за проект, VCL/FMX? Скорее всего, данные приходят в UTF8, а в TMemo пишутся строки ANSI (может наоборот). В любом случае необходимо делать приведение входящих данных к родной кодировке String. Изменено 3 июня, 2016 пользователем Pax Beach Цитата Ссылка на комментарий
2 Евгений Корепов Опубликовано 3 июня, 2016 Поделиться Опубликовано 3 июня, 2016 (изменено) Все правильно получаете, кодировка тут не при чем. Согласно спецификации "DNS Packet Structure", вы получаете не строку, а пакет который нужно разобрать. К примеру если запрос будет "nslookup www.google.ru 127.0.0.1", то там где вы получаете имя хоста будет строка "''#3'www'#6'google'#2'ru'#0#0#1#0#1". Парсинг простейший: #3 - означает что далее идут 3 символа хоста 'www' - вот ожидаемые 3 символа #6 - далее идут еще 6 символов хоста 'google' - ага, вот они #2 - ну и еще 2 символа 'ru' - ура, они здесь #0 - конец имени хоста, складываем в кучу, перемежая точками и получаем www.google.ru #0 - дальше у нас служебная информация... #1 #0 #1 Вот как то так. P.S. А зачем вам на таком низком уровне работать? Может использовать IdDNSServer : TIdDNSServer ? P.P.S. Правильно Memo1.Lines.Add(BytesToString(AData,12)); //(12, а не 13) Изменено 3 июня, 2016 пользователем Евгений Корепов Pax Beach, kami, enatechno и 5 других 8 Цитата Ссылка на комментарий
0 Volt- Опубликовано 6 июня, 2016 Автор Поделиться Опубликовано 6 июня, 2016 (изменено) Евгений Корепов Спасибо за наглядное разъяснение. С парсингом разобрался. Сейчас запрос приходит как нужно. Изменено 6 июня, 2016 пользователем Volt- Цитата Ссылка на комментарий
0 Volt- Опубликовано 6 июня, 2016 Автор Поделиться Опубликовано 6 июня, 2016 (изменено) Теперь проблема в следующем. Получив запрос DNS я его отправляю через idDNSResolve и ответ отправить обратно в командную строку. procedure TForm1.UDPBeforeQuery(ABinding: TIdSocketHandle; ADNSHeader: TDNSHeader; var ADNSQuery: TIdBytes); begin form1.IdDNSResolver1.Resolve('google.ru'); form1.IdDNSResolver1.DNSHeader.AA:=ADNSHeader.AA; form1.IdDNSResolver1.DNSHeader.ANCount:=ADNSHeader.ANCount; form1.IdDNSResolver1.DNSHeader.ARCount:=ADNSHeader.ARCount; form1.IdDNSResolver1.DNSHeader.BitCode:=ADNSHeader.BitCode; form1.IdDNSResolver1.DNSHeader.ID:=ADNSHeader.ID; form1.IdDNSResolver1.DNSHeader.NSCount:=ADNSHeader.NSCount; form1.IdDNSResolver1.DNSHeader.Qr:=1; form1.IdDNSResolver1.DNSHeader.OpCode:=ADNSHeader.OpCode; form1.IdDNSResolver1.DNSHeader.QDCount:=ADNSHeader.QDCount; form1.IdDNSResolver1.DNSHeader.RA:=ADNSHeader.RA; form1.IdDNSResolver1.DNSHeader.RCode:=ADNSHeader.RCode; form1.IdDNSResolver1.DNSHeader.RD:=ADNSHeader.RD; form1.IdDNSResolver1.DNSHeader.TC:=ADNSHeader.TC; ABinding.SendTo(ABinding.PeerIP,ABinding.PeerPort,form1.IdDNSResolver1.DNSHeader.GenerateBinaryHeader); end; Но в командной строке ответ не отображается. Как правильно его отправить? Изменено 6 июня, 2016 пользователем Volt- Цитата Ссылка на комментарий
0 Евгений Корепов Опубликовано 7 июня, 2016 Поделиться Опубликовано 7 июня, 2016 Отправлять ответ вы должны там же где получаете запрос procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin .. .. ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Ваши данные...); end; Цитата Ссылка на комментарий
0 Volt- Опубликовано 7 июня, 2016 Автор Поделиться Опубликовано 7 июня, 2016 (изменено) А как сформировать эти данные для отправки в IdDNSResolver1? Уже всю голову сломал. =( procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin form1.IdDNSResolver1.Resolve('google.ru'); ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort,form1.IdDNSResolver1.ГдеХранитсяОтветВФорматеTBytes); end; Я не могу понять как мне сделать пакет для отправки ответа. Как TBytes сформировать. Или я чего то не так понимаю? Изменено 7 июня, 2016 пользователем Volt- Цитата Ссылка на комментарий
0 Евгений Корепов Опубликовано 7 июня, 2016 Поделиться Опубликовано 7 июня, 2016 Не понял ваш вопрос. Приложите ваш проект (или полный листинг), трудно понимать вырванные из контекста вопросы и куски кода. Цитата Ссылка на комментарий
0 Volt- Опубликовано 7 июня, 2016 Автор Поделиться Опубликовано 7 июня, 2016 (изменено) Пример приложил. Запускаете его, заходите в командную строку и набираете nslookup google.ru 127.0.0.1 и увидите что в неё (командную строку) не придет ответ от нашего сервера DNS. Вопрос в том, как правильно сформировать ответ что бы он дошел до командной строки. DNS.rar Изменено 7 июня, 2016 пользователем Volt- Цитата Ссылка на комментарий
0 Rusland Опубликовано 7 июня, 2016 Поделиться Опубликовано 7 июня, 2016 (изменено) Volt-, на строке MainForm.IdDNSResolver.Resolve(S); ругается: Цитата Project DNS.exe raised exception class EIdDnsResolverError with message 'DNS Server Reports Query Name Error'. До ABinding.SendTo не доходит управление Изменено 7 июня, 2016 пользователем Rusland Цитата Ссылка на комментарий
0 Volt- Опубликовано 7 июня, 2016 Автор Поделиться Опубликовано 7 июня, 2016 Странно, у меня на Delphi XE7 на эту строчку не ругается. Попробуйте для теста в ручную забить.MainForm.IdDNSResolver.Resolve('google.ru') Цитата Ссылка на комментарий
0 Rusland Опубликовано 7 июня, 2016 Поделиться Опубликовано 7 июня, 2016 (изменено) Попробовал, теперь это место проходит... Может ответ кодировать надо? Изменено 7 июня, 2016 пользователем Rusland Цитата Ссылка на комментарий
0 Volt- Опубликовано 7 июня, 2016 Автор Поделиться Опубликовано 7 июня, 2016 Rusland При всем уважении к сообществу, я не знаю как нужно формировать ответ. Прошу помощи у гуру. Цитата Ссылка на комментарий
0 Евгений Корепов Опубликовано 7 июня, 2016 Поделиться Опубликовано 7 июня, 2016 2 часа назад, Volt- сказал: Пример приложил. Запускаете его, заходите в командную строку и набираете nslookup google.ru 127.0.0.1 и увидите что в неё (командную строку) не придет ответ от нашего сервера DNS. Вопрос в том, как правильно сформировать ответ что бы он дошел до командной строки. DNS.rar Для начал у вас не правильно работает function ReplaceSpecSymbol, она оставляет спецсимволы в конце строки. Вот накидал правильно работающую: function ReplaceSpecSymbol(S: String): String; var Count : Integer; begin Count:=0; Result:=''; while True do begin Count:=Ord(S.Chars[0]); Result:=Result+S.Substring(1,Count)+'.'; S:=S.Remove(0,Count+1); if Ord(S.Chars[0])=0 Then break; end; Result:=Result.TrimRight(['.']); end; После этого в вашем проекте нормально все ресолвится, но что отсылать в ответ на lookup я не имею представления. Не знаю как заставить IdDNSResolver отдать данные в сыром формате, надо искать и читать документацию. Вот код процедуры, но надо разобраться что слать: procedure TMainForm.IdUDPServerUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); var S, Domain: String; I : Integer; ABuffer : TIdBytes; begin S:=ReplaceSpecSymbol(BytesToString(AData,12)); Memo_Log.Lines.Add(S); if Pos('in-addr.arpa',S)=0 then begin IdDNSResolver.Resolve(S); for I := 0 to IdDNSResolver.QueryResult.Count-1 do if IdDNSResolver.QueryResult[I].RecType = qtA then begin S:=TARecord(IdDNSResolver.QueryResult[I]).IPAddress; Memo_Log.Lines.Add('IdDNSResolver: '+S); end; // Вот дальше не знаю что именно пересылать // ABuffer:=DNSHeader.GenerateBinaryHeader; // ABuffer:=IdDNSResolver.PlainTextResult; // ABuffer:=ABuffer+IdDNSResolver.InternalQuery; // ABuffer:=IdDNSResolver.InternalQuery; ABinding.Send(ABuffer); end; Вы можете поразбираться с помощью простейшего DNS прокси, по крайней мере будете видеть что идет в запросе и что в ответе. Код ниже, только пропишите глобальную переменную ALocalPort : Integer, для запоминания забинденного порта на 127.0.0.1 procedure TMainForm.IdUDPServerUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); Const ExternalDNSHost = '8.8.8.8'; LocalHost = '127.0.0.1'; begin if ABinding.PeerIP.Equals(LocalHost) then // если запрос с локального, пересылаем на внешний dns begin ALocalPort:=ABinding.PeerPort; IdUDPServer.SendBuffer(ExternalDNSHost,53,AData); end; if ABinding.PeerIP.Equals(ExternalDNSHost) then // если с внешнего, пересылаем на локальный IdUDPServer.SendBuffer(LocalHost,ALocalPort,AData); exit; end; в коммандной строке используйте "nslookup -retry=1 -timeout=30 google.ru 127.0.0.1 " (один повтор запроса, чтоб не засирать отладку и таймаут сколько нужно секунд, что не отвалился запрос пока будете разбираться) Rusland и Volt- 2 Цитата Ссылка на комментарий
0 Volt- Опубликовано 8 июня, 2016 Автор Поделиться Опубликовано 8 июня, 2016 Попробовал сделать через idDNSServer, но ответ так и не приходит в командную строку. Выкладываю исходник. DNS2.rarЗапускаете его, заходите в командную строку и набираете nslookup google.ru 127.0.0.1 и увидите что в неё (командную строку) не придет ответ от нашего сервера DNS.Вопрос в том, как правильно сформировать ответ что бы он дошел до командной строки. Если у кого получиться добиться получения ответа в командно строке, напиши пожалуйста. Очень хочется разобраться в вопросе. Цитата Ссылка на комментарий
0 Евгений Корепов Опубликовано 8 июня, 2016 Поделиться Опубликовано 8 июня, 2016 Вот посмотрите, просто и красиво TSimpleDNSServer http://www.delphipraxis.net/87433-dns-server-mit-indys-tiddnsserver-%3D-verwirrung.html Rusland 1 Цитата Ссылка на комментарий
0 Volt- Опубликовано 8 июня, 2016 Автор Поделиться Опубликовано 8 июня, 2016 9 минут назад, Евгений Корепов сказал: Вот посмотрите, просто и красиво TSimpleDNSServer http://www.delphipraxis.net/87433-dns-server-mit-indys-tiddnsserver-%3D-verwirrung.html Спасибо, я раньше находил эту статью, но по ней ещё больше вопросов. Пытался воспроизвести у себя, но ругается на WriteToBytes, WordToBytes, LongWordToBytes, ToBytes, BitsToByte, BytesToWord, ReadFromBytes, ByteToBits. Цитата Ссылка на комментарий
Вопрос
Volt-
Добрый день.
Кинул на форму idUDPServer1 и Memo1
В событии idUDPServer1.OnUDPRead написал:
procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin Memo1.Lines.Add(BytesToString(AData,13)); end;
в событии Form1.OnCreate написал:
procedure TForm1.FormCreate(Sender: TObject); begin idUDPServer1.DefaultPort:=53; idUDPServer1.Active:=True; end;
Запускаю проект.
Захожу в командную строку Windows и набираю команду:
nslookup google.ru 127.0.0.1
В Memo1 появляется DNS запрос, но что то не так с кодировкой.
Первая строчка должна выглядеть так "1.0.0.127.in-addr.arpa" а вторая и последующие так "google.ru"
Как поправить?
Изменено пользователем Volt-Ссылка на комментарий
16 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.