UDP безопасность и идентификация входящих данных - PullRequest
7 голосов
/ 11 мая 2010

Я создаю приложение, использующее UDP для передачи и получения информации. Проблема, с которой я сталкиваюсь - это безопасность. Прямо сейчас я использую IP / socketid для определения того, кому какие данные принадлежат.

Однако я читал о том, как люди могут просто подделать свой IP, а затем просто отправить данные в виде определенного IP. Так что это кажется неправильным способом сделать это (небезопасно). Так как еще мне определить, какие данные принадлежат тем или иным пользователям? Например, у вас есть 10 подключенных пользователей, у всех есть конкретные данные. Сервер должен сопоставить данные пользователя с полученными нами данными.

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

Любая информация будет оценена. Спасибо.

Ответы [ 6 ]

4 голосов
/ 11 мая 2010

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

Однако использование TCP или UDP в качестве транспортного уровня все еще оставляет вас открытыми для других атак, таких как Sniffing и Man in the Middle атаки с использованием arp spoofing или dns кеширование . Другая проблема заключается в том, что если и злоумышленник, и геймеры находятся на одной локальной сети, например, в беспроводной сети или в другой широковещательной сети, вы можете получать трафик независимо от адреса источника / адресата, и ТОЛЬКО ПОТОМ делает подделка трехстороннего рукопожатия становится возможной (и hmac не может помочь!). Лучшее решение - использовать SSL / TLS в качестве транспортного уровня, который решает все эти проблемы.

Вы не должны заново изобретать wheal, но если по какой-то причине вам необходимо зашифровать UDP, вам следует использовать потоковый шифр, например RC4-drop1024, или даже лучше блочный шифр, например AES 256, в режиме OFB . Это сэкономит пропускную способность по сравнению с другими режимами шифрования, поскольку они округляются до наибольшего размера блока.

EDIT: Основываясь на комментарии Marts для DTLS (Datagram Transport Layer Security), я немного покопался и обнаружил, что существует официальный RFC , и он поддерживается OpenSSL и должен быть выставлен с использованием библиотеки pyOpenSSL . Я рекомендую использовать комплект шифров RC4-SHA, чтобы уменьшить накладные расходы, этот комплект поддерживается SSL 3.0 (самый новый). Однако DTLS, вероятно, будет иметь больше накладных расходов (LAG!), Чем TCP.

1 голос
/ 11 мая 2010

Вы можете посмотреть на HMAC

Википедия:

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

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

0 голосов
/ 27 августа 2011

Я бы заглянул в сетевую библиотеку Garage Games. Он написан на C ++ и использует UDP. Он разработан для малой задержки и считается одним из лучших для игр.

Если я правильно помню, они фактически рассчитали бы вероятную позицию игрока как на стороне клиента, так и на стороне сервера. Это сделало бы это для многих аспектов, чтобы гарантировать целостность данных. Это также сделало бы проверку crc на клиентском программном обеспечении и сравнило бы с серверным программным обеспечением, чтобы убедиться, что они соответствуют.

Я не уверен, что вы можете лицензировать его отдельно, поэтому вам, возможно, придется лицензировать игровой движок (100 баксов). По крайней мере, это даст вам некоторое представление о проверенном подходе к UDP для игр. Другая возможность - изучить сетевой код PyGame. Возможно, оно уже решило проблемы, с которыми вы сталкиваетесь.

0 голосов
/ 12 мая 2010

Я делю это на четыре уровня безопасности.

  • Чрезвычайно небезопасно - Любой в сети может подделать действительный запрос / ответ с общедоступными предварительными знаниями. (т.е. системный журнал)

  • Очень небезопасно - Любой в сети может подделать действительный запрос / ответ только в том случае, если у него есть хотя бы доступ для чтения к проводной сети. (Пассивный MITM) (т. Е. Http-доступный форум с файлами cookie браузера)

  • Несколько небезопасно - любой в сети может подделать действительный запрос / ответ, если он может читать и вносить изменения в канал (Active MITM) (т. Е. Https-сайт с самоподписанным сертификатом)

  • Безопасный - Запросы / ответы не могут быть подделаны даже при полном доступе к провод. (т. е. https доступный сайт электронной коммерции)

Для интернет-игр очень небезопасное решение может быть приемлемым (это мой выбор). Оно не требует криптографии. Просто поле в вашем UDP-формате пакета приложений с каким-то случайным, практически не угадываемым идентификатором сеанса, перебираемым на время игры.

В некоторой степени небезопасно требуется немного крипто, но ни одно из доверия / PKI / PSK не требуется для предотвращения Active-MITM безопасного решения. С некоторой небезопасностью, если полезная нагрузка данных не была чувствительной, вы могли бы использовать шифр только целостности с (TCP) TLS / (UDP) DTLS, чтобы уменьшить накладные расходы обработки и задержки на клиенте и сервере.

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

В конце дня я бы порекомендовал перейти очень ненадежно или несколько небезопасно / только с целостностью DTLS.

0 голосов
/ 11 мая 2010

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

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

Учитывая общий ключ, каждый пакет может содержать AES256_CBC( <random starter block for CBC><user-id><sequence_number><application data> ) Если при расшифровке удается получить ожидаемый идентификатор пользователя, пакет аутентифицируется как исходящий от вашего пользователя, и порядковый номер может использоваться для избежания атак воспроизведения.

Одним из недостатков SRP является то, что в Python сжатие чисел происходит довольно медленно. Я изменил демонстрационный код Python на что-то более удобное для использования и обнаружил, что для выполнения одного обмена SRP клиент-сервер (процессор 2 ГГц) потребовалось около 300 мс. Однако прямая реализация в C ++ алгоритма SRP с использованием поддержки BigNumber в OpenSSL заняла всего 2 мс. Так что, если вы собираетесь пойти по этому пути, я настоятельно рекомендую использовать реализацию C / C ++ алгоритма для производственного кода. В противном случае вы, вероятно, сможете обрабатывать только несколько входов в секунду.

0 голосов
/ 11 мая 2010

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

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

...