Протокол сокет устойчивый сокет сервер - PullRequest
0 голосов
/ 01 июля 2011

Я разрабатываю сервер на C # (используя * асинхронные методы).Все работает нормально, пока одна сторона не нарушит протокол (например, атака на сервер).

Клиент и сервер обмениваются сообщениями следующей структуры:

  1. Первые 4 байта определяют длину (N) тела сообщения в байтах
  2. Следующие N байтов определяют тело сообщения

Если кто-то передает неправильную длину - вся связь между этим клиентом и сервером становится непредсказуемой.

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

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

Я хочу использовать для этого TCP, поэтому пакет будет таким же, как сегмент TCP,Но есть несколько ловушек:

  • MTU (который определяет MSS) может отличаться, и нет предопределенного значения для размера буфера, который я мог бы использовать (поправьте меня, если я ошибаюсь)
  • Я не смог найти способ манипулирования TCP-сегментами напрямую (без абстракции «потока»).

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

Я занимаюсь разработкой под .NET и не хочу использоватьлюбой P / вызывает, если этого можно избежать.

Ответы [ 4 ]

2 голосов
/ 05 июля 2011

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

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

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

Вы можете разработать протокол, который допускает повторную синхронизацию - самый простой пример - использование разделителей на границе между последующими сообщениями протокола (сам разделитель не допускается в сообщении). Многие из старых «основанных на строках» интернет-протоколов, такие как FTP, SMTP и IRC, работают таким образом (в данном случае в качестве разделителя используется символ перевода строки).

1 голос
/ 01 июля 2011

Здесь есть два отдельных вопроса.

  1. Как вы справляетесь с протоколом нарушения?
  2. Как вы планируете защитить ваш сервер?

Вы не можете защитить свой сервер, встроив исправление ошибок в обработчик протокола. Вам нужны безопасные методы кодирования, чтобы сделать это. Для начала загляните в SSL - если вы попытаетесь обезопасить сервер самостоятельно a) этого не произойдет, и b) это займет много времени.

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

0 голосов
/ 01 июля 2011

отключить плохо себя ведущий клиент

0 голосов
/ 01 июля 2011

Возможно, вы захотите прочитать о реализации RPC protobuf-c :

Клиент выдает 12-байтовый заголовок, за которым следует полезная нагрузка сообщения в кодировке protobuf:

  • индекс метода (закодированный как 4-байтовое число с прямым порядком байтов)
  • длина сообщения: длина полезной нагрузки в кодировке protobuf (закодированный 4-байтовый байтовый код)
  • идентификатор запроса: значение, выбранное клиентом, чтобы он знал, какой ответ сервера соответствует какому запросу в случае нескольких невыполненных запросов). (кодируется 4 байтами)

Сервер в итоге выдает аналогичный 16-байтовый ответ:

  • код состояния (в виде 4-байтового числа с прямым порядком байтов). Одно из следующих значений:
    0: успех
    1: сбой службы (т. Е. Передан в NULL для сообщения на закрытие)
    2: слишком много ожидающих (клиентское соединение имеет слишком много ожидающих запросов)
  • индекс метода (такой же, как для запроса)
  • длина сообщения (такая же, как для запроса)
  • идентификатор запроса (такой же, как для запроса)

Еще одна вещь, о которой стоит подумать, добавленная, если вы попытаетесь сделать это по не-TCP / IP (то есть каналу без ошибок), это добавить проверку CRC в заголовок и полезную нагрузку.

...