Добавление поддержки SSL в существующий код TCP и UDP?
Вот мой вопрос.
Сейчас у меня есть серверное приложение Linux (написанное с использованием С++ - gcc), которое общается с клиентским приложением Windows С++ (Visual Studio 9, Qt 4.5.)
Какой самый простой способ добавить поддержку SSL обеим сторонам, чтобы обеспечить связь, без полного уничтожения существующего протокола?
Это приложение VOIP, которое использует комбинацию UDP и TCP для первоначальной настройки соединения и создания туннелирования портов, а затем использует UDP для потоковых данных.
В прошлом у меня было много проблем с созданием сертификатов безопасности с нуля, необходимых для работы этого материала.
Существующий рабочий пример кода был бы идеальным.
Спасибо!
Ответы
Ответ 1
SSL очень сложный, поэтому вы захотите использовать библиотеку.
Существует несколько параметров, таких как Keyczar, Botan, cryptlib и т.д. Каждая из этих библиотек (или библиотек, предложенных другими, таких как Boost.Asio или OpenSSL) будет иметь пример кода для этого.
Отвечая на ваш второй вопрос (как интегрировать библиотеку в существующий код, не вызывая слишком большой боли): он будет зависеть от вашего текущего кода. Если у вас уже есть простые функции, которые вызывают методы Winsock или сокета для отправки/получения int
s, strings
и т.д., Тогда вам просто нужно переписать кишки этих функций. И, конечно же, измените код, который устанавливает сокет для начала.
С другой стороны, если вы вызываете функции Winsock/socket напрямую, вы, вероятно, захотите написать функции, которые имеют сходную семантику, но отправляют данные в зашифрованном виде и заменяют ваши вызовы Winsock этими функциями.
Однако вы можете подумать о переходе на что-то вроде Google Protocol Buffers или Apache Thrift (aka Facebook Thrift). В документации к буферам протоколов Google говорится: "До буферов протоколов был формат запросов и ответов, которые использовали ручную сортировку/разборки запросов и ответов и поддерживали несколько версий протокола, что привело к некоторому очень уродливому коду...."
В настоящее время вы находитесь в стадии маршаллинга/разборки рук. Он может работать, и на самом деле проект, над которым я работаю, действительно использует этот метод. Но гораздо лучше оставить это в библиотеке; особенно библиотеку, которая уже подумывала о необходимости обновления программного обеспечения в будущем.
Если вы пройдете по этому маршруту, вы настроите свои сетевые подключения с помощью библиотеки SSL, а затем вы будете передавать данные буфера Thrift/Protocol Buffer по этим соединениям. Это. Это связано с обширным рефакторингом, но в итоге вы получите меньше кода для поддержки. Когда мы представили протокольные буферы в кодовую базу этого проекта, о которой я упоминал, нам удалось избавиться от около 300 строк кода маршаллинга/демаршаллинга.
Ответ 2
Я рекомендую использовать GnuTLS как на стороне клиента, так и на стороне сервера, только для TCP-соединения. Забудьте о данных UDP. В документации GnuTLS есть пример кода для записи как клиентов, так и серверов. Пожалуйста, поймите, что по крайней мере серверная сторона (обычно ответчик TCP) должна иметь сертификат; клиентская сторона может работать с анонимной идентификацией (хотя есть даже пример без сертификата сервера, используя только обмен ключами DH, что позволило бы атаковать "человек в середине" ).
В целом, вполне вероятно, что вам нужно будет понять принципы SSL, независимо от того, какую библиотеку вы используете. Альтернативами библиотеки являются OpenSSL (как Unix, так и Windows) и SChannel (только Windows).
Ответ 3
Вы пробовали поддержку SSL в Boost.Asio или ACE? Оба используют OpenSSL под капотом и предоставляют аналогичные абстракции для TCP, UDP и SSL. Пример кода доступен как в дистрибутивах Boost.Asio, так и в ACE.
Возможно, вам стоит иметь в виду, что SSL ориентирован на запись, а не на потоковое (TCP и UDP). Это может повлиять на то, как вы мультиплексируете события, так как вы должны, например, прочитать полную запись SSL, прежде чем сможете завершить операцию чтения.
Ответ 4
Чтобы справиться с этим без изменений в приложении, вы можете посмотреть проект stunnel (http://www.stunnel.org/). Я не думаю, что он будет обрабатывать UDP для вас.
Ответ 5
Встроенные библиотеки SSL/TLS yaSSL и CyaSSL хорошо работали для меня в прошлом. Ориентируясь на встроенные системы, они оптимизированы как по скорости, так и по размеру. yaSSL написан на С++, а CyaSSL написан на C. Для сравнения, CyaSSL может быть в 20 раз меньше, чем OpenSSL.
Оба поддерживают самые современные отраслевые стандарты (вплоть до TLS 1.2), предлагают некоторые интересные функции, такие как потоковые шифры, и имеют двойную лицензию под лицензией GPLv2 и коммерческую лицензию (если вам нужна коммерческая поддержка).
У них есть учебник по SSL, который касается добавления CyaSSL в ваш уже существующий код: http://www.yassl.com/yaSSL/Docs-cyassl-manual-11-ssl-tutorial.html
Страница продукта: http://yassl.com/yaSSL/Products.html
С уважением,
Крис