LINUX.ORG.RU

Опубликован эксплойт для «отравления» DNS-кэша

 , , ,


0

0

Опубликован код, эксплуатирующий недавно выявленную уязвимость в DNS-серверах — возможность "отравления" DNS-кэша, открытую Дэном Каминским.

Эксплойт, позволяющий злоумышленнику вставить произвольные записи в кэш DNS-сервера, был добавлен в программу Metasploit, свободно распространяемую программу тестирования и атаки компьютерных сетей. Авторство кода принадлежит автору Metaspliot HD Moore совместно с исследователем, известным как |)ruid.

Код, который можно посмотреть тут, использует известные недостатки протокола DNS и его известных реализаций.

По заявлению Каминского, атаку можно организовать за секунды. ZDNet просит пользователей и админов: обновите ваши сервера. Пожалуйста!

>>> Подробности

★★

Проверено: maxcom ()
Последнее исправление: cetjs2 (всего исправлений: 1)

Ответ на: комментарий от baka-kun

>Какая самоуверенная молодежь пошла... Повторяю, Дэн уже не раз говорил об этом. И djbdns на такую туфту не ловится.

Ладно, щелкнем по носу еще раз.

Описание протокола DNS на пальцах: есть идентификатор запроса (всего 16 бит), есть поле запроса (домен), поле ответа, поле авторитарного ответа и поле дополнительного ответа (для запроса последние три - пустые).

В ответе на запрос присутствует нужный идентификатор, поле запроса пустое, поле ответа содержит (r)esource (r)ecords (RRs) для ответа на запрос. Поле авторитарного ответа должно содержать данные от авторитарного для этого домена сервера. Поле дополнительных данных может содержать все, что угодно.

Как олбнаружил Дэн, resource records из additional rr section парсятся точно так же, как будто они получены в качестве answer rr section, т.е. можно перезаписать данные для yahoo.com.

Ваш пример выше показывает глупости, существующие 10 лет назад с перезаписью NS/A записи для того или иного resolver'а. на эту атаку (особенность протокола!) ловятся все, нужно только отсутствие записи для yahoo.com в кэше ресолвера и совпадение идентифокатора запроса.

Это старая и в современных реалиях не очень осуществимая атака, DJB DNS на нее так же прекрасно ловится, ах, да, у него жу случайный порт запроса, т.е. нужно послать не один ответ а 64 тысячи, что очень просто.

Об атаке через additional rr, которая очень упрощает махинации со случайными портами (читай: удаляет эту часть), Дэн будет говорить впервые (публично).

>Сейчас ни один нормальный кеширующий сервер не примет информацию от левого домена, где бы в ответе она не находилась.

Ога, то-то все так засуетились 8 июля :) Домашнее задание: найти в гугле matasano article about dsn poisoning.

anonymous
()
Ответ на: комментарий от anonymous

>Домашнее задание: найти в гугле matasano article about dsn poisoning.

Дам шпаргалку: google://Reliable DNS Forgery in 2008

возможно в кэше еще осталось.

anonymous
()

DNSSec расширение для клиент<->сервек неспроста так долго валяецца "на полке".

BasileyOne
()
Ответ на: комментарий от anonymous

> Ладно, щелкнем по носу еще раз.

Ого! Оно ещё дрыгается, но поиском не занималось...

> Как олбнаружил Дэн, resource records из additional rr section парсятся точно так же, как будто они получены в качестве answer rr section, т.е. можно перезаписать данные для yahoo.com.

Как об этом говорил /другой/ Дэн десяток лет назад: а не пошли бы не in-bailiwick additional RR к дьяволу! Такие glue не нужны для нормальной работы ресолвера, их никто не спрашивал, поэтому мы можем смело игнорировать эту «дружелюбно предоставленную» дополнительную информацию.

> на эту атаку (особенность протокола!) ловятся все, нужно только отсутствие записи для yahoo.com в кэше ресолвера и совпадение идентифокатора запроса.

На приведенный мной poisoning не ловится /ни один/ вменяемы кеш, кроме старых производных bind при определенных условиях.

> DJB DNS на нее так же прекрасно ловится, ах, да, у него жу случайный порт запроса, т.е. нужно послать не один ответ а 64 тысячи

Я в этом обсуждении приводил /две/ атаки. Для первой надо угадать порт И id, то есть брутфорсом перебрать почти 2^32 (чуть больше четырех миллиардов) комбинация на каждый запрос.

Второй он не подвержен принципиально, поскольку информацию о поддоменах yahoo.com он примет /только/ от NS-ов yahoo.com, а информацию о .com /только/ от корневых. И неважно, где будет находиться отрава: в основной части ответа, или в дополнительной. Весь out-of-bailiwick glue он просто проигнорирует.

> Об атаке через additional rr ... Дэн будет говорить впервые (публично).

Обо всех случаях cache poisoning Дэн /Бернштайн/ говорил неоднократно больше десяти лет.

Так вот, атака твоего Каминского комплексная: осуществляется первая из упомянутых мной, а в ответ подсовывается вторая, которая должна пройти проверку юрисдикции. Главное, вовсе не упрощается «махинация с портами»: ты можешь заставить меня отресолвить какой-нибудь kjbgd.yahoo.com, но с какого порта и с каким id я это делаю останется неизвестным.

Он уповает только на то, что сможет заставить меня ресолвить мусор часто и много, увеличив свои шансы на перебор 65536 вариантов для непатченных bind-like или 4227858432 вариантов для остальных ресолверов.

Это на данный момент всё.

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

Да, единственная польза от этого шума — наконец-то пропатчили bind.

Правда теперь он стал не просто очень тормозным сервером, а самым-самым тормозным в мире. ;)

baka-kun ★★★★★
()

да жлобство это все. ессно будет тормозить. потому и RFC 2635 не внедряли, к примеру. теперь - ПРИЙДЕТСЯ. после первого-же иска, клиента, ISP-у(не у нас, увы).

p.s. жаба дущит купить больше железа под NS ? нету времени на [настройку-обновление]NS ? валите из бизнесса(ISP). "ибо нех" (c) [там таким].

BasileyOne
()
Ответ на: комментарий от baka-kun

> Да, единственная польза от этого шума — наконец-то пропатчили bind. Правда теперь он стал не просто очень тормозным сервером, а самым-самым тормозным в мире. ;)

Кстати, хотя читать код djbdns не очень-то приятно, но быстрее и эффективнее вряд ли кому удастся сделать. Я когда-то думал сделать кеширующую сеть днс-ов по типу memcached. Времени свободного не хватило.

Casus ★★★★★
()
Ответ на: комментарий от baka-kun

>Второй он не подвержен принципиально, поскольку информацию о поддоменах yahoo.com он примет /только/ от NS-ов yahoo.com, а информацию о .com /только/ от корневых. И неважно, где будет находиться отрава: в основной части ответа, или в дополнительной. Весь out-of-bailiwick glue он просто проигнорирует.

Тем самым нарушая стандарт. Это похоже на его же грабли в случае второго MX: мне это не нужно, поэтому этого нет, поэтому мой сервер очень безопасный.

>Так вот, атака твоего Каминского комплексная: осуществляется первая из упомянутых мной, а в ответ подсовывается вторая, которая должна пройти проверку юрисдикции. Главное, вовсе не упрощается «махинация с портами»: ты можешь заставить меня отресолвить какой-нибудь kjbgd.yahoo.com, но с какого порта и с каким id я это делаю останется неизвестным.

>Он уповает только на то, что сможет заставить меня ресолвить мусор часто и много, увеличив свои шансы на перебор 65536 вариантов для непатченных bind-like или 4227858432 вариантов для остальных ресолверов.

Бугога, да вы одмин от бога!

Хакер просто поднимает собственный подпатченный DNS сервер для какого-то своего домена, присылает жертве e-mail с сылкой на картинку из этого домена, или просто заходит на сайт из этого домена, если атакующий внутри сети, и все. Система попытается разрезолвить www.hackers_site.com, параллельно получив additional rr для www.microsoft.com

Т.е. не обязательно пытаться разрезолвить asdadad.microsoft.com, чтобы изменить www.microsoft.com, если djbdns это не позволяет, то он нарушает протокол (сюрприз, уже в который раз). Хотя стоит отметить, что это очень кривая особенность протокола, и ее нужно было бы запретить в стандарте.

Я подозреваю, что все заплатки, во-первых, делают порт источника случайным, а во-вторых, отрезают additional rr, и теперь системе приходится посылать несколько сообщений.

Чтобы обойти махинации с портами достаточно просто послать много запросов на разные домены, т.е. атакующему из внутренней сети нужно либо сделать много запросов на поддомены атакуемого домена, либо прислать кому-то письмо с кучей ссылок на картинки, outlook прекрасно все зажует.

anonymous
()
Ответ на: комментарий от anonymous

> Тем самым нарушая стандарт.

rfc1034? В этой части ему не соответствует /ни один/ кеш. Если устаревший стандарт требует, «положите ключ под коврик, и оставьте записку, где лежат деньги», никто следовать не будет.

> Система попытается разрезолвить www.hackers_site.com, параллельно получив additional rr для www.microsoft.com

В ответе данные out-of-bailiwick — за пределами юрисдикции хакерского DNS. В таком виде атака известна с 1990. Уже давно /никто/ на это не ловится, bind начал лечиться где-то в 1997 году, правда остался старый алгоритм определения «правдоподобности» ответа,приносящий больше проблем, чем пользы.

> достаточно просто послать много запросов на разные домены... либо прислать кому-то письмо с кучей ссылок

Если у тебя нормально с математикой, оцени количество запросов, необходимое для угадывания одного правильного ответа из четырех миллиардов возможных. Потом оцени размер письма ;)

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

Нашел в интересное решение (ладно, прочитал в блоге). Решение проблемы ведь тривиальное: заставить резолвить только по TCP. Все серверы и так должны это поддерживать по стандарту, просто отключить в конфиге кэширующего сервера возможность рекурсивно ресолвить по UDP, и _все_ проблемы разом решены. Остается только дополнительные записи, не относящиеся к запрашиваемому домену, но это хоть и есть в стандарте, отключается в конфиге.

anonymous
()
Ответ на: комментарий от baka-kun

>Если у тебя нормально с математикой, оцени количество запросов, необходимое для угадывания одного правильного ответа из четырех миллиардов возможных. Потом оцени размер письма ;)

На каждый запрос нужно отправить примерно 4 миллиарда ответов. Берем письмо, в котором 64 тысячи ссылок на картинки, outlook попытается разресолвить все (даже пока не скачивая картинки), итого нужно будет всего 65 тысяч пакетов в единственный порт, т.к. запросы забьют все возможные порты источника, атакующему нужно будет посылать пакеты только в один порт. Цифры можно подвигать на порядок в любом направлении.

Это немного. Если атакующий находися внутри сети (или какой-нибудь троян у него есть), задача упрощается - троян может тупо запрашивать в вечном цикле поддомены аткуемого домена.

anonymous
()
Ответ на: комментарий от anonymous

> отключить в конфиге кэширующего сервера возможность рекурсивно ресолвить по UDP

Если официальный (авторитетный) сервер не содержит данных, превышающих размер UDP датаграммы, он имеет полное право вообще не отвечать на TCP. Такое поведение стандартизовано.

> и _все_ проблемы разом решены.

Да, спуфить по TCP немного сложнее, но и скорость обслуживания упадет в разы, если не на порядки.

Для решения достаточно просто спрашивать одни данные несколько раз. Два раза — вероятность спуфа 1/2^64, четыре - 1/2^128. Это будет быстрее TCP и надежней.

baka-kun ★★★★★
()
Ответ на: комментарий от anonymous

> письмо, в котором 64 тысячи ссылок на картинки, outlook попытается разресолвить все

Аутлук может и попытается, да кто же ему даст? Кеш провайдера примет от тебя только сотню запросов одновременно, а наружу они будут оправлены вперемешку с остальными задачами ресолвера.

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>Да, спуфить по TCP немного сложнее, но и скорость обслуживания упадет в разы, если не на порядки.

Тогда как же работают веб-серверы с десятками тысяч запросов в секунду и миллионами одновременных соединений?

>Для решения достаточно просто спрашивать одни данные несколько раз. Два раза — вероятность спуфа 1/2^64, четыре - 1/2^128. Это будет быстрее TCP и надежней.

Это заметно медленнее TCP... В TCP можно добиться, что будет послан только _два_ дополнительных пакета клиентом (syn + fin), и два - сервером (syn+ack и ack для последнего fin). Клиент может объединить данные с первым ack'ом. Сервер - со вторым.

anonymous
()
Ответ на: комментарий от baka-kun

>Аутлук может и попытается, да кто же ему даст? Кеш провайдера примет от тебя только сотню запросов одновременно, а наружу они будут оправлены вперемешку с остальными задачами ресолвера.

Все даже проще: не нужно перебирать 64 тысячи портов - парадокс близнецов для задачи выбора как порта, так и идентификатора упрощает задачу более чем существенно. Многие (если не большинство) провайдеры ограничиваются верхними портами (выше 40000). Так что задача не только в теории, но и на практике, выглядит не так уж сложно.

anonymous
()
Ответ на: комментарий от anonymous

> Тогда как же работают веб-серверы с десятками тысяч запросов

Элементарно. А вот кеширующий DNS (который мы вроде как атакуем) просто физически не в состоянии послать одновременно больше запросов, чем количество доступных ему портов.

При этом учти, что атакующий клиент не единственный, и рядом ещё несколько интенсивных потребителей вроде почтарей и веб-серверов, не говоря уже о тысячах простых клиентов сети провайдера.

А в нормальной сети ещё и IPS работает, который просто не даст свободно флудить кеш левыми запросами.

> Это заметно медленнее TCP...

Нет. Минимальная TCP-сессия (без данных): syn>, syn-ack<, ack>, fin>, fin-ack<, ack>. Правда в большинстве случаев финал будет четырехходовым: fin>, ack<, fin<, ack>.

Добавь два пакета на запрос и подтверждение, два на ответ и подтверждение.

Не меньше десять пакетов, то есть по UDP можно провести минимум пять сессий вопрос/ответ. «Минимум» потому, что сервер может отправить все пять запросов одновременно, дождавшись пяти ответов (или двух/трех/четырех одинаковых), а в TCP всё надо делать синхронно.

> Клиент может объединить данные с первым ack'ом. Сервер - со вторым.

То есть сломать системный IP-стек, и использовать свою реализацию в юзерспейс на raw socket? И это(!) будет быстрее?

PS. Причем я ещё молчу про потерявшиеся ack, ретрансмиты по три раза syn и fin...

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>А вот кеширующий DNS (который мы вроде как атакуем) просто физически не в состоянии послать одновременно больше запросов, чем количество доступных ему портов.

Ему просто нужно делать это по tcp. TCP _не_ медленнее UDP уже лет 10 как.

>То есть сломать системный IP-стек, и использовать свою реализацию в юзерспейс на raw socket? И это(!) будет быстрее?

Хех, я уж думал, baka-kun исправился... Почитайте на досуге про различные tcp опции для сокетов. После этого предыдущий абзац (и то, что вы написали выше в своем сообщении) пропадет само по себе.

anonymous
()
Ответ на: комментарий от baka-kun

>PS. Причем я ещё молчу про потерявшиеся ack, ретрансмиты по три раза syn и fin...

Цирк продолжается :) А по таймауту обнаружить потерю UDP пакета и перепослать запрос получается быстрее - да вы не только одмин, вы еще и сетевой программист от бога!

anonymous
()
Ответ на: комментарий от anonymous

> TCP _не_ медленнее UDP уже лет 10 как.

В транзакциях в секунду на данных, умещающихся в один UDP пакет? А на сатурированном канале?

> Почитайте на досуге про различные tcp опции для сокетов.

Прозреваю великого программиста! ;)

О Великий, соблаговоли сообщить презренному опции сии, да в каковых стеках протоколов интернетных он узреть может всю могучесть ихнюю, дабы отринуть адовския сокеты BSD-ёвые, да приобщиться к свету истины благолепной! Научи сираго, яви кода твоего несравненнаго, select, listen, accept да connect твой присный!

baka-kun ★★★★★
()
Ответ на: комментарий от anonymous

> А по таймауту обнаружить потерю UDP пакета и перепослать запрос получается быстрее

Что по таймауту не получить ответ на UDP, что на syn — эквипенисуально.

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>В транзакциях в секунду на данных, умещающихся в один UDP пакет? А на сатурированном канале?

Это что за страшное слово? Вообще да, TCP в маленьких пакетах забивает канал ровно настолько, насколько это делает UDP как в bulk transfer, так и в round-robin.

>О Великий, соблаговоли сообщить презренному опции сии, да в каковых стеках протоколов интернетных он узреть может всю могучесть ихнюю, дабы отринуть адовския сокеты BSD-ёвые, да приобщиться к свету истины благолепной! Научи сираго, яви кода твоего несравненнаго, select, listen, accept да connect твой присный!

Слушай меня, о юный падаван. В ядре Линуксовом, начиная со времен незапамятных, есть ack'и отложенные, и если милостею божыю их поставить для сокета соединяющегося, то пустоголовый ack, что должен был быть послан, может быть к данным присовокуплен.

А для пущего просветления, о юный падаван, читай на ночь молитву божыю, что отлита золотыми буковами Кириллом и Мефодием дарованными, в файле net/ipv4/tcp_input.c и функции tcp_rcv_synsent_state_process().

anonymous
()
Ответ на: комментарий от baka-kun

Это был вопрос.

Краткая хронология:

baka-kun: PS. Причем я ещё молчу про потерявшиеся ack, ретрансмиты по три раза syn и fin...

Анонимус: А по таймауту обнаружить потерю UDP пакета и перепослать запрос получается быстрее (здесь вопрос ироничный)

baka-kun: Что по таймауту не получить ответ на UDP, что на syn — эквипенисуально.

Вообще да, разницы нет, но из-за того, что TCP все сделает сам, при прочих равных получается быстрее в round-robin. Про bulk transfer и отсутствие окна в udp вообще молчу.

anonymous
()
Ответ на: комментарий от anonymous

> Это что за страшное слово?

Загляни в словарь.

> TCP в маленьких пакетах забивает канал ровно настолько, насколько это делает UDP

TCP в маленьких /транзакциях/ — connect->send->recv->close — забивает канал в обе стороны в несколько раз больше, чем UDP.

> В ядре Линуксовом, начиная со времен незапамятных, есть ack'и отложенные … пустоголовый ack … может быть к данным присовокуплен.

Точнее в пакете с ack могут содержаться данные. Ты не открыл Америку. Правда они могут быть не в любом таком пакете. Например всё, полученное после или вместе с fin от той стороны, будут игнорироваться. Именно поэтому твоё предложение передавать данные в ack после fin идет лесом, ибо мимо rfc.

Я тебе даже больше скажу: протокол позволяет передавать данный в течении хендшейка, то есть в syn, syn+ack и последующем ack. Правда есть пара НО: а) приложению они могут быть переданы только после перехода сокета в established, б) Линукс так не умеет, и данные до в пакете с syn дропает (BSD умеет их принять).

А ведь совместимость с Линуксом соблюдать придется, и с виндой, и с солярой, и со всякими прочими поделками.

Поэтому даже кратчайший более-менее совместимый вариант

syn >
syn+ack <
ack+data >
ack+data <
ack >
rst <

придется отвергнуть по соображениям совместимости.

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>Например всё, полученное после или вместе с fin от той стороны, будут игнорироваться. Именно поэтому твоё предложение передавать данные в ack после fin идет лесом, ибо мимо rfc.

Еще раз перечитай, где передавать данные.

>Я тебе даже больше скажу: протокол позволяет передавать данный в течении хендшейка, то есть в syn, syn+ack и последующем ack. Правда есть пара НО: а) приложению они могут быть переданы только после перехода сокета в established, б) Линукс так не умеет, и данные до в пакете с syn дропает (BSD умеет их принять).

Молодец, указанную функцию хорошо изучил.

>TCP в маленьких /транзакциях/ — connect->send->recv->close — забивает канал в обе стороны в несколько раз больше, чем UDP.

Sigh. Нет, не забивает. Дополнительные два пакета здесь погоды не делают. Основная причина, почему TCP мало используется - это особенность DNS протокола, когда при вычитывании пакета не известна его длина. Поэтому при работе с TCP сначала вычитывается длина одного сегмента (например части имени), затем сегмент, затем длина второго и т.д. Даже на вполне обычный запрос "IN A" таких вычитываний из сокета может потребоваться _десятки_. А время системного вызова очень дорого, так что все преимущества TCP пропадают. В UDP нет потока октетов, поэтому пакет вычитыватся за один системный вызов, а затем парсится в userspace. Это я и хотел от вас услышать, но увы...

anonymous
()
Ответ на: комментарий от anonymous

> Еще раз перечитай, где передавать данные.

Судя по твоему описанию — после fin. Не спорю, я мог не так понять, ясность мысли
на текст не была перенесена, к сожалению.

Давай пробежимся по одной TCP DNS-транзакции клиент<->сервер, как она обычно происходит.
Попрошу в ответ исправить мою последовательность, и привести свою. Слева клиент,
справа сервер:

syn >
syn+ack <
ack >            // теоретически клиент уже мог отправить запрос здесь
                 // но для совместимости все стеки шлют сначала пустой ack
ack+data[+psh] > // запрос, скорее всего с push
ack <            // без данных, поскольку в буффере на отправку в этот момент пусто,
                 // но если стек умеет подождать (таких мало), и сервер нашел ответ быстро,
                 // теоретически он мог уйти здесь. Маловероятно и непереносимо.
ack+data[+psh] < // ответ сервера, если он не дал его раньше, экономя один пакета
ack+fin >
ack <
ack+fin <
ack >

На этом транзакция завершилась, стороны перешли в TIME-WAIT на пару минут.

> Молодец, указанную функцию хорошо изучил.

Вообще-то ты разговариваешь с человеком, который написал свою реализацию IP стека
десяток лет назад. И она до сих пор применяется в некоторых маломощных железках
с заказными SOC.

> Нет, не забивает. Дополнительные два пакета здесь погоды не делают.

Обычно дополнительных восемь, по четыре в каждую сторону. Плюс заголовок TCP
пакета минимум на 16 байт длиннее. А канал не резиновый. На маленьких транзакциях,
сравнимых в массе с длиной заголовка TCP в случае DNS, разница огромна.

> вычитываний из сокета может потребоваться _десятки_.

До этого мы с тобой ещё не дошли. Но в качестве домашнего задания можешь
поупражняться с read(sock, buffer, 65536).

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

syn >
syn+ack <

ack > Здесь уже DNS запрос
< ack и данные ответа на DNS запрос

fin >
ack+fin <

или проще по RST.

Все в пределах протокола и гарантированно поддерживается *bsd и linux. Насколько я знаю в solaris тоже. Про windows ничего не могу сказать, но это в пределах протокола, так что должна поддерживать тоже.

Как мы видим - всего два лишних пакета от каждого из агентов. Зато (отвлечемся от проблемы с сисколами в случае TCP) куча преимуществ TCP: нет проблем с безопасностью, нет проблем при фрагментации (сюрприз, именно TCP используется для трансфера зон, где очень большие запросы), бОльшая скорость в случае нескольких запросов в одном соединении.

>До этого мы с тобой ещё не дошли. Но в качестве домашнего задания
>можешь поупражняться с read(sock, buffer, 65536).

Бугога, а ты попробуй это на практике с tcp сокетом, когда в нем только 20 байт данных.

Можно использовать неблокирующий вариант, и дочитать после распарсивания, но возникают проблемы с многопоточной обработкой - сокет должен быть залочен, пока не обработаются все вычитанные одним потоком запросы, т.к. потенциально в сокете еще остались данные для предыдущего запроса. Хотя может быть многопоточная обработка одного соединения и через чур, тогда TCP - наилучшее решение проблемы, нужно экспериментировать.

anonymous
()
Ответ на: комментарий от anonymous

syn >
syn+ack <

ack > Здесь уже DNS запрос
< fin+ack+ данные ответа на DNS запрос

ack >

Можно даже так, но работает только для еденичного запроса от клиента.

anonymous
()
Ответ на: комментарий от anonymous

Ха, вот это я напартачил... В DNS TCP используется префикс из 2х октетов, в которых указана длина сообщения, так что на этом все преимущества UDP пропадают.

Кстати, что же вы не поправляете про блокирующие recv/read? Уже пора :)

anonymous
()
Ответ на: комментарий от anonymous

То есть, как я и предполагал ранее, ты предлагаешь заниматься реализацией протокола в юзерспейс на raw socket? Или срочно переписывать все ip-стеки по твоим пожеланиям?

> ack > Здесь уже DNS запрос

К сожалению, этот ack будет отправлен как часть вызова connect(), а пока он не завершиться, писать данные в сокет ты не можешь. Я знаю стеки, которые так умеют, но в интернете их далеко не большинство. Также я знаю стеки, которые до перехода в established, для чего нужен именно этот ack, вообще не примут данных, и таких больше первых.

> fin

Сожалею, но один только fin послан быть не может, стандарт требует ack+fin с каждой стороны. Причем оба должны быть подтвержден ack, иначе соединение не закроется, и стек будет перепосылать ack+fin, пока ему не надоест.

> проще по RST

Не проще. В ответ на rst стек убивает сокет вместе со всеми его буферными данными и посылает в приложение сигнал, поэтому нет никакой гарантии, что ты успеешь вычитать данные до разрыва. Более того, я знаю реализации, где ты при всем желании не успеешь, там даже явно требуется инвалидировать все полученные в такой сессии данные.

> fin+ack+ данные

Существует множество стеков, которые не примут данные в одном пакете с fin. Точнее практически нет таких, которые примут.

> именно TCP используется для трансфера зон, где очень большие запросы

TCP используется для любого запроса (и полного ответа), который превышает 512 байт (не будем о EDNS и DNSSEC, это другой разговор).

> нескольких запросов в одном соединении

Чего в случае DNS не бывает.

> а ты попробуй это на практике с tcp сокетом, когда в нем только 20 байт данных

Двойка вам, молодой человек, домашнее задание провалено. Вызов read() положит в начало буфера все данные, и вернет 20 — длину ответа. А в рассматриваемых нами примерах передается только один пакет, поэтому read() разместит его данные в буфере целиком, и опять таки вернет длину.

> но возникают проблемы с многопоточной обработкой - сокет должен быть залочен, пока не обработаются все вычитанные одним потоком запросы, т.к. потенциально в сокете еще остались данные для предыдущего запроса

Кому должен? Как всё запущено… Складывается впечатление, что молодой человек ничего не знает о работе TCP. Даже того, что потоки данных идентифицируются четырьмя величинами: двумя IP адресами и двумя портами. Можно принять множество коннектов на один порт, при этом каждый будет иметь уникальный дескриптор и упорядоченные данные, которые просто никак не могут перепутаться.

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>То есть, как я и предполагал ранее, ты предлагаешь заниматься реализацией протокола в юзерспейс на raw socket? Или срочно переписывать все ip-стеки по твоим пожеланиям?

OMG! Протри же наконец глаза - это все реализовано в ядерном стеке много лет назад. Пример с отложенным ack ничему не научил?

>К сожалению, этот ack будет отправлен как часть вызова connect(), а пока он не завершиться, писать данные в сокет ты не можешь. Я знаю стеки, которые так умеют, но в интернете их далеко не большинство. Также я знаю стеки, которые до перехода в established, для чего нужен именно этот ack, вообще не примут данных, и таких больше первых.

Неверно! Смотри в сторону неблокирующих сокетов. Это прямо сейчас можно делать в Linux. Возвращение из connect означает получение syn+ack с другой стороны, если включены отложенные ack'и.

>> нескольких запросов в одном соединении

>Чего в случае DNS не бывает.

Ога, и зоны у нас тоже не передаются мужду хостами. Или простойший кэширующий сервер, который принимает от клиентов заросы, смотрит в своем кэше, и если там ответа нет, по единственному соединению запрашивает данные у вышестощего в иерархии (например у провайдера).

>Кому должен? Как всё запущено… Складывается впечатление, что молодой человек ничего не знает о работе TCP. Даже того, что потоки данных идентифицируются четырьмя величинами: двумя IP адресами и двумя портами. Можно принять множество коннектов на один порт, при этом каждый будет иметь уникальный дескриптор и упорядоченные данные, которые просто никак не могут перепутаться.

Вы уже показали свое знание TCP выше :) А до этого - знание DNS. Теперь показывате знание потоков и разделяемых между ними файловых дескрипторов :)

Для вас сюрприз, что одно и то же соединение могут обслуживать несколько потоков? Один и тот же сокет (connected или accepted, не важно), из которого несколько потоков вычитывают по очереди по запросу и начинают их обрабатывать: каждый свой, а потом пишут ответ в тот же сокет (тоже по очереди, котороая контроллируется например семафором или posix mutex)...

А сколько у вас гонору :) Поэтому в начале и было написано "щелкнуть по носу".

anonymous
()
Ответ на: комментарий от baka-kun

>> проще по RST

>Не проще. В ответ на rst стек убивает сокет вместе со всеми его буферными данными и посылает в приложение сигнал, поэтому нет никакой гарантии, что ты успеешь вычитать данные до разрыва. Более того, я знаю реализации, где ты при всем желании не успеешь, там даже явно требуется инвалидировать все полученные в такой сессии данные.

В ответ на RST вообще ничего не происходит с данными - сокет просто помечается как CLOSE. И из него все еще можно вычитать полученные до rst данные. И сигнал будет получен только когда процесс попытается прочитать/записть данные из этого сокета, и любой dns сервер запрещает этот сигнал, чтобы его не убил случайно отвалившийся клиент. Невычитанные данные будут уничтожены только после того, как процесс закроет файловый дескриптор, ссылающийся на сокет. Что вам еще рассказать про сетевой стек? :)

anonymous
()
Ответ на: комментарий от baka-kun

>Сожалею, но один только fin послан быть не может, стандарт требует ack+fin с каждой стороны. Причем оба должны быть подтвержден ack, иначе соединение не закроется, и стек будет перепосылать ack+fin, пока ему не надоест.

Вообще-то ты сам просил только разницу между твоей диаграммй и тем, что я предложил. Если бы я убрал syn/syn+ack, тоже стал бы кричать, что нарушет tcp протокол? :)

anonymous
()
Ответ на: комментарий от anonymous

> … все реализовано в ядерном стеке … прямо сейчас можно делать в Linux

Может для тебя будет сюрпризом, но интернет не начинается и не заканчивается Линуксом. Весь твой лепет смешно читать, он равносилен капризу, «хочу, чтобы все сделали как я сказал; хочу, хочу, хочу!»

> Возвращение из connect означает получение syn+ack с другой стороны, если включены отложенные ack'и

Другая сторона всё ещё в syn-received. Как я уже сказал, есть стеки, отбрасывающие любые данные до перехода в established.

Очередное домашнее задание: вместо бесплотных фантазий напиши пару тестовых приложений (bind, listen, accept, read, write, close и connect, write, read, close), затем понаблюдай tcpdump. О результатах доложи.

> Ога, и зоны у нас тоже не передаются мужду хостами

У меня через AXFR не передаются, ибо их не отдают направо-налево всем желающим. А у кого передаются, там тоже одна транзакция запрос-длинный_ответ.

> простойший кэширующий сервер, который принимает от клиентов заросы, смотрит в своем кэше, и если там ответа нет, по единственному соединению запрашивает данные у вышестощего в иерархии

Нет такого в природе. Во-первых, каждый запрос происходит в своём соединении. Во-вторых, клиентский ресолвер выставляет RD, запрашивая рекурсию, а кеши отправляют запросы со снятым RD, поэтому друг у друга ничего не запрашивают, за редким исключением специально построенных иерархий с централизованным управлением. Ну ещё кривой bind может допускать такой некорректный cache snooping. В-третьих, последовательные запросы через одно соединение будут на порядок медленнее параллельных через разные.

> Для вас сюрприз, что одно и то же соединение могут обслуживать несколько потоков?

Только с геморроем в виде ad-hoc сериализации своим протоколом, превращая параллельный интерфейс в последовательный. Причем это обязательно будет соединение точка-точка между двумя конкретными приложениями. Нафиг, нафиг.

> В ответ на RST вообще ничего не происходит с данными - сокет просто помечается как CLOSE

Не путай принудительно разорванное соединение с полузакрытым, когда одна сторона в fin-wait уже не может передавать, но продолжает принимать. Здесь не тот случай.

> И из него все еще можно вычитать полученные до rst данные

Ничего подобного. После получения rst активный сокет сразу переходит в closed, TCB освобождается, все текущие действия принудительно обрываются с ошибкой ECONNRESET, никакие данные уже недоступны.

> ты сам просил только разницу между твоей диаграммй и тем, что я предложил

К сожалению, кроме грубейших ошибок ты ничего не предложил.

> Если бы я убрал syn/syn+ack, тоже стал бы кричать, что нарушет tcp протокол?

Я бы просто сказал, что TCP/IP стеки так себя не ведут, поэтому иди лесом. И подальше.

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>Может для тебя будет сюрпризом, но интернет не начинается и не заканчивается Линуксом. Весь твой лепет смешно читать, он равносилен капризу, «хочу, чтобы все сделали как я сказал; хочу, хочу, хочу!»

>Другая сторона всё ещё в syn-received. Как я уже сказал, есть стеки, отбрасывающие любые данные до перехода в established.

>Очередное домашнее задание: вместо бесплотных фантазий напиши пару тестовых приложений (bind, listen, accept, read, write, close и connect, write, read, close), затем понаблюдай tcpdump. О результатах доложи.

Опять столько пафоса. Добавление данных в ack после syn - это _стандартное_ поведение. Оно описано в rfc. Оно применяется в low latency системах. Вы об этом не знаете и утверждаете, что это невозможно.

>> В ответ на RST вообще ничего не происходит с данными - сокет просто помечается как CLOSE

>Не путай принудительно разорванное соединение с полузакрытым, когда одна сторона в fin-wait уже не может передавать, но продолжает принимать. Здесь не тот случай.

Да вы же вообще не понимаете, что пишете. Просто придираетесь к каждому предложению, пытаясь показать свои знания. Прочтите выше, когда этот rst предлагается использовать: как один из вариантов разрыва соединения, если не устраивает ситуация с двумя пакетами (fin и ack).

>Нет такого в природе. Во-первых, каждый запрос происходит в своём соединении. Во-вторых, клиентский ресолвер выставляет RD, запрашивая рекурсию, а кеши отправляют запросы со снятым RD, поэтому друг у друга ничего не запрашивают, за редким исключением специально построенных иерархий с централизованным управлением. Ну ещё кривой bind может допускать такой некорректный cache snooping. В-третьих, последовательные запросы через одно соединение будут на порядок медленнее параллельных через разные.

Какая узость... Если глаза и уши закрыть, то в мире вообще ничего нет! Высуньте наконец голову из песка. Кэши никогда рекурсивные флаги не трогают, этого нельзя делать по стандарту, иногда добавляют RA, если использовалась рекурсия.

anonymous
()
Ответ на: комментарий от baka-kun

>> Для вас сюрприз, что одно и то же соединение могут обслуживать несколько потоков?

>Только с геморроем в виде ad-hoc сериализации своим протоколом, превращая параллельный интерфейс в последовательный. Причем это обязательно будет соединение точка-точка между двумя конкретными приложениями. Нафиг, нафиг.

Ну и каша... Интересно, а из udp сокета в несколько потоков можно читать по-вашему? Т.е. такой сервер или не нужен (ну да, голова же в песке), или все же все будет работать? Будет. И это используется. И тоже самое используется в tcp. Вы же об этом просто не знаете, т.к. никогда не приходилось делать самому, а уже считаете, что узнали мир...

>> И из него все еще можно вычитать полученные до rst данные

>Ничего подобного. После получения rst активный сокет сразу переходит в closed, TCB освобождается, все текущие действия принудительно обрываются с ошибкой ECONNRESET, никакие данные уже недоступны.

Снова низачет :) Слова написаны правильно только в первой части предложения про CLOSE. Никогда не получали из poll() POLLIN|POLLHUP? Видимо, никогда... Или если RST приходит во время вычитывания данных: данные продолжат вычитываться до конца сискола (если сигнал зарещен, как у всех нормальных людей). И Connection reset тоже возвращается, но описанная выше ситуация работает. Впрочем, в вашем мире, видимо, нет :)

anonymous
()
Ответ на: комментарий от baka-kun

>> ты сам просил только разницу между твоей диаграммй и тем, что я предложил

>К сожалению, кроме грубейших ошибок ты ничего не предложил.

Да ты не обижайся :)

>> Если бы я убрал syn/syn+ack, тоже стал бы кричать, что нарушет tcp протокол?

>Я бы просто сказал, что TCP/IP стеки так себя не ведут, поэтому иди лесом. И подальше.

Вот это железобетонный аргумент: "TCP/IP стеки так себя не ведут" ! Конечно не ведут, когда нужно показать только часть протокола. Отлично подходит, когда нужно придраться хоть к чему-нибудь :)

anonymous
()
Ответ на: комментарий от anonymous

> Добавление данных в ack после syn - это _стандартное_ поведение. Оно описано в rfc.

Прием данные в пакетах syn и syn+ack — стандартное поведение, описано в rfc. Работает в BSD, вот только Линукс так не умеет, и дропает данные. Ты опять будешь настаивать на частном случае, а не на общем знаменателе для /всеобщего/ сервиса? Почему тогда не предлагаешь посылать запрос вместе с syn, ответ с syn+ack, а завершать rst?

Тестик уже написал? На разных системах погонял? Насладился tcpdump-ом?

> Прочтите выше, когда этот rst предлагается использовать

Зачем? Лучше расскажи, как изнутри приложения универсальным способом заставить ip-стек послать rst.

> Кэши никогда рекурсивные флаги не трогают, этого нельзя делать по стандарту

Кеши /в ответе клиенту/ сохраняют флаг RD, а свои пакеты посылают без запроса рекурсии. По стандарту. Это элементарные соображения безопасности: нельзя отправлять недоверяемому серверу рекурсивные запросы. Да и бесполезно, всё равно не входящие в зону ответственности данные будут отброшены рекурсивным ресолвером.

> иногда добавляют RA, если использовалась рекурсия

Кеши /в ответе клиенту/ устанавливают флаг RA, чтобы сказать, «я умею рекурсию», а не «я осуществил рекурсию». Прочувствуй разницу.

> а из udp сокета

Я не буду рассказывать про разницу между SOCK_STREAM и SOCK_DGRAM, хорошо?

> будет работать?

Будет, куда оно денется. Только геморроя много. Поправь меня, ты предлагаешь держать перманентное TCP соединение между клиентом и кешем, читать и рекурсивно ресолвить разные запросы в разных нитях кеша, отвечать обратно. Подумай, как будешь делать сериализацию ответов в случае существующего протокола DNS. С учетом того, что один ответ может быть доступен через пару миллисекунд, а другой через десяток секунд.

Сотни тысяч клиентов держат перманентные соединения к серверу, это у тебя какой-то IM получается, а не DNS. Соединения сервер-сервер тоже перманентные? Инфраструктуру предлагаешь оставить децентрализованной, или все данные держать в центральном хранилище, общем для всего интернета?

> Никогда не получали из poll() POLLIN|POLLHUP?

Это ничего, что poll() просто ждет изменения состояния сокета и выставляет POLLHUP как при переходе в FIN-WAIT, так и в CLOSED? В первом случае ты можешь вычитать остатки данных, во втором получишь от read() ошибку.

> если RST приходит во время вычитывания данных …

… то read() или recv() могут поместить в буфер /что-то/, но вернут -1, а в errno будет ECONNRESET. Тот, кто решит воспользоваться такими «данными» — ССЗБ.

> Конечно не ведут, когда нужно показать только часть протокола

Проблема решается просто: приведи протокол целиком. Желательно вместе с кодом, который его совместимо реализует на большинстве реализаций BSD сокетов (достаточно соответствия POSIX).

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>Прием данные в пакетах syn и syn+ack — стандартное поведение, описано в rfc. Работает в BSD, вот только Линукс так не умеет, и дропает данные. Ты опять будешь настаивать на частном случае, а не на общем знаменателе для /всеобщего/ сервиса? Почему тогда не предлагаешь посылать запрос вместе с syn, ответ с syn+ack, а завершать rst?

>Тестик уже написал? На разных системах погонял? Насладился tcpdump-ом?

Я регулярно вижу, как Linux принимает (и отправляет) данные в ack пакете после получения syn+ack. В Linux для этого есть специальная опция, насколько я помню, в bsd тоже. Об этом я говорил все время: это поведение стандартно, и поддерживается всеми, кому не лень реализовать протокол TCP согласно спецификации.

>Зачем? Лучше расскажи, как изнутри приложения универсальным способом заставить ip-стек послать rst.

Если в очереди уже есть данные, и сокет закрывается (close/exit, т.е. без shutdown), посылается RST. Согласно 2525 iirc.

>Кеши /в ответе клиенту/ устанавливают флаг RA, чтобы сказать, «я умею рекурсию», а не «я осуществил рекурсию». Прочувствуй разницу.

И снова тебе низачет :) Кэш либо умеет, либо не умеет делать рекурсивные запросы, и, о какой сюрприз, для всех зон, где он не авторитарный сервер, он обязан уметь делать рекурсию. И получается, что сервер, который умеет делать рекурсивные запросы, не станет в некоторых случаях выставлять RA. Противоречие с твоими словами, но т.к. это вполне очевидное поведение, спишем на то, что ты торопился :)

anonymous
()
Ответ на: комментарий от baka-kun

>Будет, куда оно денется. Только геморроя много. Поправь меня, ты предлагаешь держать перманентное TCP соединение между клиентом и кешем, читать и рекурсивно ресолвить разные запросы в разных нитях кеша, отвечать обратно. Подумай, как будешь делать сериализацию ответов в случае существующего протокола DNS. С учетом того, что один ответ может быть доступен через пару миллисекунд, а другой через десяток секунд.

Нет, я предлагаю в некоторых случаях (например дерево кэширующих серверов у провйдера) держать соединение между ними: запросы от клиентов принимать как угодно, но вверх по иерархии отдавать по одному (или несколько, неважно, главное, что они не создаются для каждого нового запроса) постоянному соединению. Кстати, такие схемы - очнь расространенная практика. По умолчанию она же используется при трансфере зон.

>Сотни тысяч клиентов держат перманентные соединения к серверу, это у тебя какой-то IM получается, а не DNS. Соединения сервер-сервер тоже перманентные? Инфраструктуру предлагаешь оставить децентрализованной, или все данные держать в центральном хранилище, общем для всего интернета?

Еще раз повторю, что не между клиентами, а серверами. Такая схема работает для ситуаций, когда инфраструктура сильно разделена, и каждый (назовем это так) отдел знает только о том, о чем должен знать, поэтому соответствующий DNS сервер содержит только нужную информацию о соседях и тех, с кем нужно связываться данному отделу. Примером может служить любой большой провайдер, у которого разные подсети не связаны друг с другом напрямую.

anonymous
()
Ответ на: комментарий от baka-kun

>Это ничего, что poll() просто ждет изменения состояния сокета и выставляет POLLHUP как при переходе в FIN-WAIT, так и в CLOSED? В первом случае ты можешь вычитать остатки данных, во втором получишь от read() ошибку.

Но мы-то говорим о случае, когда удаленная сторона прислала rst. Проверте, как работает tcp_rcv_established() и tcp_reset() - сокет просто помечается как dead и пара махинаций с флагами и wakeup. Никто не прерывает чтение или любую другую операцию (кроме сигнала конечно, но мы считаем, что он заблокирован).

>… то read() или recv() могут поместить в буфер /что-то/, но вернут -1, а в errno будет ECONNRESET. Тот, кто решит воспользоваться такими «данными» — ССЗБ.

Неверно, recv вернет столько, сколько прочитал, а _следующий_ уже вернет -1 и connection reset в errno. Если данных в сокете не было, то вернется сразу -1 и connection reset. Код же перед носом: проверь, как работает tcp_recvmsg() в случае, когда уже что-то скопировано (copied != 0) и есть ошибка, dead и т.п. (в районе 1370 строки в net/ipv4/tcp.c).

anonymous
()
Ответ на: комментарий от baka-kun

>Проблема решается просто: приведи протокол целиком. Желательно вместе с кодом, который его совместимо реализует на большинстве реализаций BSD сокетов (достаточно соответствия POSIX).

OMG, выше же написан кроме способа завершени соединения :) Ты правильно заметил, что там не было fin и ack в конце, я их не написал, т.к. мы говорили о части, где передаются данные.

Реализуется это просто через единственную опцию, которую я тоже выше описал. И кстати, для завершения протокола достаточно fin с одной стороны, fin+ack с другой, и ack c первой, а не 4 пакета, как ты написал.

anonymous
()
Ответ на: комментарий от anonymous

> Я регулярно вижу, как Linux принимает (и отправляет)…

Можно я ещё раз повторю, «интернет не начинается и не заканчивается Линуксом»? Спасибо.

> поддерживается всеми, кому не лень реализовать протокол TCP согласно спецификации.

Ты всё ещё веришь в Деда Мороза и идеальные реализации спецификаций? К сожалению, реальный мир ущербен, и хорошим тоном является принимать любые стандартные пакеты, а отправлять максимально понимаемые всеми. Линукс этому правилу следует не до конца: принимает не любые стандартные пакеты. Хорошо хоть отправляет максимально совместимые, если его не попросить делать иначе.

> Если в очереди уже есть данные, и сокет закрывается (close/exit, т.е. без shutdown), посылается RST

Стандарт разрешает полузакрытые «half-duplex» соединения, когда вызвавшее close() приложение уже не может /читать/ из сокета, но никто не мешает отправлять. Противоположная же сторона в это время может получать данные, но не должна отправлять.

Если в сокете во время вызова close() есть /входящие/ данные, или они приходят после закрытия, стек ДОЛЖЕН (но не ОБЯЗАН) послать RST.

>> Кеши /в ответе клиенту/ устанавливают флаг RA, чтобы сказать, «я умею рекурсию»
> И снова тебе низачет

Повторю ещё раз: флаг RA всегда выставляется /во всех/ ответах любым сервером, который умеет ответить на рекурсивный запрос. Этот флаг обозначает /доступность сервиса/, а не был ли он использован.

> Кэш либо умеет, либо не умеет делать рекурсивные запросы

Похоже мы говорим на разных языках. Кеш всегда умеет обрабатывать рекурсивные запросы — с установленным RD, но не делает их сам. Два разных термина:

а) «рекурсивный запрос» — запрос клиента к серверу, в запросе выставлен бит RD, тем самым клиент просит «сделать рекурсию», если это возможно;

б) «сделать рекурсию», «рекурсивный ресолвинг», «рекурсивное [раз]решение имени» — процесс последовательного опроса официальных серверов от корня по нисходящей до тех пор, пока не будет найдет официальный сервер для домена в запросе, и не получен ответ, либо пока не будет определена невозможность получения ответа.

DNS серверы делятся на два вида: authoritative (официальные, авторитетные, «авторитарные») и кеширующие (рекурсивные). Эти серверы ДОЛЖНЫ быть разделены.

С первыми всё просто: они отвечают только на запросы о своих доменах, игнорируя остальные. В принципе могут делать и абсолютно бесполезную работу: возвращать ссылку на корневые серверы (мусор, который выкидывают все нормальные ресолверы).

Вторые занимаются только тем, что рекурсивно — от корневых официальных серверов и дальше — ресолвят запросы своих клиентов, сохраняя результаты в локальном кеше на время до TTL записи для ускорения работы.

RD в запросе устанавливают /только клиентские ресолверы/, рекурсивные серверы опрашивают официальные со сброшенным флагом.

> Кэш … для всех зон, где он не авторитарный сервер

Кеш не должен быть официальным сервером /ни для одной/ зоны. Конечно, админ с руками из жопы может взять bind (или некоторые его производные), наплевать на документацию, рекомендации, советы Пола Викси наконец, и построить такое уродливое чудище.

> Нет, я предлагаю в некоторых случаях (например дерево кэширующих серверов у провйдера) держать соединение между ними…

Не надо забывать, что стандарты и рекомендации имеют отношение только к глобальному интернету, внутри своей сети ты можешь городить любых монстров, включая иерархии кешей и доставку датаграмм почтовыми голубями. Главное, чтобы всё это не светилось в глобальной сети.

baka-kun ★★★★★
()
Ответ на: комментарий от anonymous

>> Это ничего, что poll() просто ждет изменения состояния сокета?…
> Но мы-то говорим о случае, когда удаленная сторона прислала rst.

poll() не занимается чтением данных, и попытка что-то прочитать из сокета, который получил rst внутри poll(), закончится неудачей. Даже в Линуксе.

> recv вернет столько, сколько прочитал, а _следующий_ уже вернет -1 … проверь, как работает tcp_recvmsg()…

Ты правда не видел ничего, кроме Линукса?

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>Можно я ещё раз повторю, «интернет не начинается и не заканчивается Линуксом»? Спасибо.

>Ты всё ещё веришь в Деда Мороза и идеальные реализации спецификаций? К сожалению, реальный мир ущербен, и хорошим тоном является принимать любые стандартные пакеты, а отправлять максимально понимаемые всеми. Линукс этому правилу следует не до конца: принимает не любые стандартные пакеты. Хорошо хоть отправляет максимально совместимые, если его не попросить делать иначе.

Можно еще предположить, что существующие нестандартные стеки вообще не обрабатывают некоторые флаги, и поэтому нужно добавить например обязательное закрытие сокета с посылкой rst, а не fin. Ну так, на всякий случай... Есть стандарт, все, что в нем неоднозначно, должно быть реализовано, как ты написал, все остальное - кривые руки, и это должно быть исправлено.

>Повторю ещё раз: флаг RA всегда выставляется /во всех/ ответах любым сервером, который умеет ответить на рекурсивный запрос. Этот флаг обозначает /доступность сервиса/, а не был ли он использован.

Nope. Есть такой провайдер qwerty. Его серверы отвечают без RA на запросы *.qwerty.ru, и с RA на все остальные. Из-за того, что сервер одновременно авторитарный для своей зоны и кэширующий для всех остальных. Собственно, оно так для всех серверов, которые совмещают эти роли. Хорошо это или плохо, но так оно и есть. Собственно, поэтому и обратил внимание, что сервер по своему желанию выставляет RA, а не тогда, когда умеет рекурсивно опрашивать.

anonymous
()
Ответ на: комментарий от baka-kun

>> recv вернет столько, сколько прочитал, а _следующий_ уже вернет -1 … проверь, как работает tcp_recvmsg()…

>Ты правда не видел ничего, кроме Линукса?

Это поведение POSIX как минимум 2001. Есть аж в 4.2 BSD.

anonymous
()
Ответ на: комментарий от anonymous

> Можно еще предположить … нестандартные стеки … поэтому нужно …

Естественно, никто не будет ориентироваться на глюки /новых/ стеков, в общем текущая практика фиксирует историческое поведение «старичков» интернета. Всем прочим, включая Линукс, приходится подстраиваться.

> Есть стандарт, все, что в нем неоднозначно, должно быть реализовано, как ты написал, все остальное - кривые руки, и это должно быть исправлено.

Естественно. Например, Линукс делает допущение, «раз древняя солярка ведёт себя не по стандарту, в отличии от BSD, значит и нам так можно, ведь все этот момент обходят в целях совместимости». Можно считать, что это — кривые руки, и должно быть исправлено. Правда становится смешно и грустно, когда адепты Линукса ломают совместимость где-нибудь в другом месте, заявляя, «это баг в HP-UX, пусть они у себя чинят, и нам плевать, что все остальные в мире его обходят ради совместимости».

> Есть такой провайдер qwerty … сервер одновременно авторитарный для своей зоны и кэширующий для всех остальных

Передай им, что они Злобные Буратины. Так делать не надо, настоятельно не рекомендуется, и вообще вредно для здоровья. Фактически это два разных сервера в одном, и который из них в данный момент используется определяется только по попаданию запроса в зону ответственности официальной части. Клиенты думают, что перед ними кеш, а он вдруг бах!, и отвечает с выставленным AA. Вот засада.

baka-kun ★★★★★
()
Ответ на: комментарий от anonymous

> Это поведение POSIX как минимум 2001

Не все системы соответствуют POSIX. Ну и бог с ними. Я своё мнение высказал, имеешь полное право не соглашаться.

Вообще я ждал, что ты предложишь использовать для DNS протокол, который идеально подходит под гарантированную передачу транзакций — T/TCP. Тогда кратчайшая сессия будет выглядеть как:

syn+fin+data(запрос) >
syn+ack(на fin)+data(ответ) <
ack(на последний fin) >

baka-kun ★★★★★
()
Ответ на: комментарий от baka-kun

>> Есть стандарт, все, что в нем неоднозначно, должно быть реализовано, как ты написал, все остальное - кривые руки, и это должно быть исправлено.

>Естественно. Например, Линукс делает допущение, «раз древняя солярка ведёт себя не по стандарту, в отличии от BSD, значит и нам так можно, ведь все этот момент обходят в целях совместимости». Можно считать, что это — кривые руки, и должно быть исправлено. Правда становится смешно и грустно, когда адепты Линукса ломают совместимость где-нибудь в другом месте, заявляя, «это баг в HP-UX, пусть они у себя чинят, и нам плевать, что все остальные в мире его обходят ради совместимости».

Вообще-то Линукс всегда ведет себя согласно стандарту, либо это ошибка, и о ней нужно сообщить разработчикам, и я сильно сомневаюсь, что есть такие допущения, что "раз древняя солярка себя так ведет, то и нам можно". Максимум, что позволяет себе Линукс - это реализация неоднозначностей протокола согласно собственному видению. Например факт, что ip адрес принадлежит не интерфейсу, а системе в целом.

>Передай им, что они Злобные Буратины. Так делать не надо, настоятельно не рекомендуется, и вообще вредно для здоровья. Фактически это два разных сервера в одном, и который из них в данный момент используется определяется только по попаданию запроса в зону ответственности официальной части. Клиенты думают, что перед ними кеш, а он вдруг бах!, и отвечает с выставленным AA. Вот засада.

Вообще-то клиентам все равно, что за сервер перед ними, и совсем не понятно, почему использование одного сервера в качестве кэша и авторитарного сервера может привести к каким-либо плачевным последствиям. Введение кэширующих возможностей на том или онм сервере всего лишь добавление работы, и если с ней машина справляется, то никаких проблем я не вижу. Наличие или отсутствие RA флга в ответе ровным счетом ни о чем не говорит клиенту, т.к. в стандарте указано, что сервер может выставлять (а может и нет) этот флаг в ответе.

anonymous
()
Ответ на: комментарий от baka-kun

>Не все системы соответствуют POSIX. Ну и бог с ними. Я своё мнение высказал, имеешь полное право не соглашаться.

Вообще recv() как вызов описан только там, так что все, кто его реализует, поддерживают эту часть стандарта. Мы говорили о том, можно ли вычитать данные, когда приходит rst. TCP RFC говорит только о том, что сокет (tcb) должен перейти в другое состоянии.

>Вообще я ждал, что ты предложишь использовать для DNS протокол, который идеально подходит под гарантированную передачу транзакций — T/TCP.

Ага, sctp, dccp, xtp... Для массового использования существуют только два протокола: tcp и udp. Все остальные - только нишевые решения для той или иной задачи. DNS - система массовая.

anonymous
()
Ответ на: комментарий от anonymous

А воти и эксплоит нашелся, который за 10 часов по гигабитной сети пойзонит пропатченный BIND. Еще вопросы будут?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.