Добрый день.
Возник вопрос с правильной организацией протокола прикладного уровня. Для управления устройством предполагается использовать Ethernet + TCP/IP. Данные представляют собой управляющие команды (как следствие, планируется пакетная передача) и терять их никак нельзя.
Возникает главный вопрос: возможна ли теоретически потеря или порча данных в потоке TCP? Если допустить что раз в год и палка стреляет, то возможна такая ситуация, что будет испорчен заголовок команды. Тогда пакет будет принят некорректно, но самое страшное, что будет потеряно ожидаемое начало следующего пакета и т.п. Короче, возможен рассинхрон.
Во избежание, придется любо городить некие таймауты для восстановления синхронизации, что не очень хорошо скажется на скорости работы, либо делать стаффинг, но мне не очень нравится реализовывать логику по сути канального уровня поверх транспортного. Либо делать еще что-то, чего мне в голову пока не пришло.
Гуру, подскажите, как все таки правильно сделать надежный пакетный обмен по TCP/IP?
Здравствуйте, gladov, Вы писали:
G>Возник вопрос с правильной организацией протокола прикладного уровня. Для управления устройством предполагается использовать Ethernet + TCP/IP. Данные представляют собой управляющие команды (как следствие, планируется пакетная передача) и терять их никак нельзя. G>Возникает главный вопрос: возможна ли теоретически потеря или порча данных в потоке TCP? Если допустить что раз в год и палка стреляет, то возможна такая ситуация, что будет испорчен заголовок команды.
Она только ооооочень теоретически возможна. При зловредном атакующем, который умеет слушать и менять поток — уже реальна. Защититься можно с помощью шифрования, но это только при недоверяемой сети.
Здравствуйте, Cyberax, Вы писали:
C>Она только ооооочень теоретически возможна. При зловредном атакующем, который умеет слушать и менять поток — уже реальна. Защититься можно с помощью шифрования, но это только при недоверяемой сети.
Вопрос защиты от атак не стоит. Интересует лишь теоретическая возможность потери данных в связи с серьезными помехами на линии, т.к. оборудование будет стоять в очень "электрически шумном" цехе.
Здравствуйте, gladov, Вы писали:
G>Возник вопрос с правильной организацией протокола прикладного уровня. Для управления устройством предполагается использовать Ethernet + TCP/IP. Данные представляют собой управляющие команды (как следствие, планируется пакетная передача) и терять их никак нельзя. G>Возникает главный вопрос: возможна ли теоретически потеря или порча данных в потоке TCP? Если допустить что раз в год и палка стреляет, то возможна такая ситуация, что будет испорчен заголовок команды. Тогда пакет будет принят некорректно, но самое страшное, что будет потеряно ожидаемое начало следующего пакета и т.п. Короче, возможен рассинхрон.
И теоретически, и практически возможно. (Хоть и редко.)
Теоретически — контрольная сумма слабовата по современным меркам. Практически — порча данных замечалась, и неоднократно. В некоторых случаях не выяснили, что влияло, но во многих находили проблемы с памятью конечных устройств, разгоном и т.д. Самые сложные случаи были, когда единственное, на кого можно было грешить, были промежуточные маршрутизаторы — это при том, что вроде бы им не положено переписывать контрольные суммы.
Но судя по тому, что мало кто реально заморачивается такими проблемами сейчас, то, что раз в год и палка стреляет, мало кого волнует. А если кого волнует, он добавляет всякие SHA* для защиты данных.
Если вы строите свою систему, и предполагаете достаточную надёжность всех компонентов (например, проблемы порчи памяти устранены за счёт тотального ECC), то можно постараться обойтись минимальными мерами — вроде тех же таймаутов.
G>Во избежание, придется любо городить некие таймауты для восстановления синхронизации, что не очень хорошо скажется на скорости работы, либо делать стаффинг, но мне не очень нравится реализовывать логику по сути канального уровня поверх транспортного. Либо делать еще что-то, чего мне в голову пока не пришло. G>Гуру, подскажите, как все таки правильно сделать надежный пакетный обмен по TCP/IP?
Для начала предлагаю реализовать просто таймауты — на уровне протокола, и контрольные суммы понадёжнее (как минимум CRC32C, а можно и SHA1) — на уровне форматов пакетов. 99%, что этого хватит и даже они будут выстреливать пару раз в год.
Здравствуйте, gladov, Вы писали:
G>Вопрос защиты от атак не стоит. Интересует лишь теоретическая возможность потери данных в связи с серьезными помехами на линии, т.к. оборудование будет стоять в очень "электрически шумном" цехе.
Вы можете сами проверить в своих условиях — прогнав, например, гигабайт 100 UDP пакетами и сверяя полученное с ожидаемым. Контрольные суммы у них с TCP совпадают на всех уровнях (L2-3-4).
В общем случае я больше ожидаю проблем внутри устройства — генератора, чем от линий данных.
Здравствуйте, netch80, Вы писали:
N>Вы можете сами проверить в своих условиях — прогнав, например, гигабайт 100 UDP пакетами и сверяя полученное с ожидаемым. Контрольные суммы у них с TCP совпадают на всех уровнях (L2-3-4). N>В общем случае я больше ожидаю проблем внутри устройства — генератора, чем от линий данных.
Спасибо за ответ, уже есть над чем подумать.
А опыты я уже ставил: поток примерно 1Мбит пропихивал по UDP. Очень часто (раз в 1-10мин), бывали ошибки КС в пакете UDP, он выбрасывался, прикладной уровень это детектировал и пакет пересылался заново. Но иногда после нескольких часов работы UDP принимал битый пакет, т.е. он искажался так, что КС UDP протокола этот пакет пропускала. Один раз даже был замечен случай, что в моем принятом пакете, защищенном CRC16, эта КС была правильна, но данные явно испорчены. Однако, т.к. пакеты короткие (до 1кб) думаю, что CRC32 на уровне протокола будет вполне достаточно.
Здравствуйте, gladov, Вы писали:
G> Спасибо за ответ, уже есть над чем подумать. G>А опыты я уже ставил: поток примерно 1Мбит пропихивал по UDP. Очень часто (раз в 1-10мин), бывали ошибки КС в пакете UDP, он выбрасывался, прикладной уровень это детектировал и пакет пересылался заново.
Мнэээ... а какое количество этих пакетов вообще по сравнению с недошедшими? Если сбои вызваны помехами на линии связи, то количество битых кадров, детектированных на уровне L2 (Ethernet) через его CRC32, должно быть на порядки больше, чем количество кадров, в которых ошибка такая, что CRC32 уровня Ethernet ничего не нашла, но нашла контрольная сумма IP или UDP.
Если таких недошедших мало, то помехи на линии, скорее всего, ни при чём, а видимые Вами сбои имеют другое происхождение — сбои памяти/шины в устройствах, или даже программные ошибки.
G> Но иногда после нескольких часов работы UDP принимал битый пакет, т.е. он искажался так, что КС UDP протокола этот пакет пропускала. Один раз даже был замечен случай, что в моем принятом пакете, защищенном CRC16, эта КС была правильна, но данные явно испорчены. Однако, т.к. пакеты короткие (до 1кб) думаю, что CRC32 на уровне протокола будет вполне достаточно.
Всё равно тестировать надо. А серьёзные контрольные суммы стиля SHA сейчас не так и дороги.
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, gladov, Вы писали:
G>> Спасибо за ответ, уже есть над чем подумать. G>>А опыты я уже ставил: поток примерно 1Мбит пропихивал по UDP. Очень часто (раз в 1-10мин), бывали ошибки КС в пакете UDP, он выбрасывался, прикладной уровень это детектировал и пакет пересылался заново.
N>Мнэээ... а какое количество этих пакетов вообще по сравнению с недошедшими? Если сбои вызваны помехами на линии связи, то количество битых кадров, детектированных на уровне L2 (Ethernet) через его CRC32, должно быть на порядки больше, чем количество кадров, в которых ошибка такая, что CRC32 уровня Ethernet ничего не нашла, но нашла контрольная сумма IP или UDP. N>Если таких недошедших мало, то помехи на линии, скорее всего, ни при чём, а видимые Вами сбои имеют другое происхождение — сбои памяти/шины в устройствах, или даже программные ошибки.
N>Всё равно тестировать надо. А серьёзные контрольные суммы стиля SHA сейчас не так и дороги.
Да, Вы правы, я об этом как-то не подумал. Зациклился на простых КС L3-4, а про то, что L2 защищен CRC32 как-то позабыл. Отношение не дошедших совсем к тем, что ошибочно дошли примерно 100/1 (если не 10/1), т.е. явно не дотягивает до того, чтобы скомпрометировать L2. Значит будем повторять эксперимент.
Здравствуйте, gladov, Вы писали:
C>>Она только ооооочень теоретически возможна. При зловредном атакующем, который умеет слушать и менять поток — уже реальна. Защититься можно с помощью шифрования, но это только при недоверяемой сети. G>Вопрос защиты от атак не стоит. Интересует лишь теоретическая возможность потери данных в связи с серьезными помехами на линии, т.к. оборудование будет стоять в очень "электрически шумном" цехе.
TCP защищён примерно тремя уровнями контрольных сумм. Вместе они будут примерно около 100 бит. Т.е. шансы на то, что случайные ошибки в пакете приведут к тому, что изменятся данные, но не поменяются ВСЕ контрольные суммы будет примерно 1/2^100.
Здравствуйте, Cyberax, Вы писали:
C>>>Она только ооооочень теоретически возможна. При зловредном атакующем, который умеет слушать и менять поток — уже реальна. Защититься можно с помощью шифрования, но это только при недоверяемой сети. G>>Вопрос защиты от атак не стоит. Интересует лишь теоретическая возможность потери данных в связи с серьезными помехами на линии, т.к. оборудование будет стоять в очень "электрически шумном" цехе. C>TCP защищён примерно тремя уровнями контрольных сумм. Вместе они будут примерно около 100 бит.
Доказательство — в студию.
Я думаю, что ты просто прогнал. Даже если просто сложить CRC32 от Ethernet и две суммы (не циклические) по 16 от IP и TCP, получится всего-навсего 64 бита. А учитывая простейший характер сумм IP и TCP, их лёгкую подверженность воздействиям типа перестановки соседних слов — и того не будет.
C> Т.е. шансы на то, что случайные ошибки в пакете приведут к тому, что изменятся данные, но не поменяются ВСЕ контрольные суммы будет примерно 1/2^100.
Твоя методологическая ошибка в том, что ты считаешь, что
1) передающая и принимающая сторона заведомо идеальны в вычислениях
2) промежуточные участники ничего сами не модифицируют
Каждое из этих предположений соответствует сферической сети в вакууме, но не реальным установкам.
Здравствуйте, netch80, Вы писали:
N>И теоретически, и практически возможно. (Хоть и редко.)
А как обостоит дело с IPv6? Я так понял автор поста говорит про IPv4.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, netch80, Вы писали:
N>>И теоретически, и практически возможно. (Хоть и редко.) K>А как обостоит дело с IPv6? Я так понял автор поста говорит про IPv4.
Контрольные суммы те же и считаются так же.
Мелкое преимущество состоит в том, что для IPv6 в контрольную сумму IP не входит hop count (бывший TTL), и она не пересчитывается на каждом шаге. Поэтому меньше вероятность того, что в промежуточном маршрутизаторе что-то испортят, поставят новую сумму и отправят по принципу "а так оно и было". Но в сумму UDP или TCP оно и в IPv4 не входило.
G>Возникает главный вопрос: возможна ли теоретически потеря или порча данных в потоке TCP? Если допустить что раз в год и палка стреляет, то возможна такая ситуация, что будет испорчен заголовок команды. Тогда пакет будет принят некорректно, но самое страшное, что будет потеряно ожидаемое начало следующего пакета и т.п. Короче, возможен рассинхрон.
Теоретически невозможно построить 100% канал передачи данных поверх ненадёжного (Ethernet, память). Но используя определённые коды можно получить почти любую желаемую надёжность за счёт CPU и пропускной способности. Соответственно, ваш первый шаг должен быть — определить желаемую надёжность.
Касательно обнаружения ошибок конкретное предложение такое:
* 64/128 бит magic number чтобы проще найти следующий пакет в случае ошибок
* длина пакета
* содержимое пакета
* контрольная сумма, которая перекрывает слабые стороны IP/TCP, например, md5/sha
Касательно надёжной передачи конкретное предложение такое:
* 64/128 бит magic number чтобы проще найти следующий пакет в случае ошибок
* длина следующего поля
* содержимое пакета в ECC (кодированое с избыточностью) см. коды Хэмминга, Рида-Соломона и т.д.
Так же стоит рассмотреть:
* UDP (если пакеты гарантировано маленькие), SCTP — избавляемся от необходимости отслеживать длину и границы пакетов
* TCP_NODELAY
Ну и, конечно, последняя линия обороны от ошибок это таймауты и подтверждения (на уровне протокола приложения). Это не сразу очевидно, но TCP гарантирует только что байты в write() *когда-то* будут отправлены — принимающая сторона может их проигнорировать или обработать неизвестно когда — поэтому необходимо чтобы удалённая присылала подтверждение обработки команд.
Здравствуйте, netch80, Вы писали:
N>Мелкое преимущество состоит в том, что для IPv6 в контрольную сумму IP не входит hop count (бывший TTL), и она не пересчитывается на каждом шаге. Поэтому меньше вероятность того, что в промежуточном маршрутизаторе что-то испортят, поставят новую сумму и отправят по принципу "а так оно и было". Но в сумму UDP или TCP оно и в IPv4 не входило.
Небольшое уточнение. Контрольной суммы в заголовках IPv6 нет. Контроль за целостностью данных отдается верхним слоям и канальному уровню.