Встроенный HTTPS-сервер. Как следует обрабатывать перенаправление и предлагать ли HTTP?
Фон
Я реализовал HTTPS-сервер, который находится внутри аппаратного обеспечения с целью безопасной удаленной настройки устройства. Чтобы добиться этого, я использовал существующий облегченный встроенный стек TCP/IP вместе с библиотекой SSL с открытым исходным кодом. Веб-сервер, который находится на вершине этого, был написан мной полностью с нуля. (Это может показаться переизобретением колеса, но для наших целей он должен быть очень легковесным и иметь очень узкий набор специфических функций. Например, совместимость с используемой нами встроенной ОСРВ и "файловой системой" ПЗУ. Это система, в которой для сеансов HTTP(S) и контекстов SSL доступно всего несколько сотен килобайт, а не много мегабайт. После всего того, что было рассмотрено, и различных других предложений, было разумно создать свой собственный). Этот веб-сервер должен поддерживать только от 5 до 10 одновременных соединений сокетов (т. Е. От 5 до 10 одновременных или постоянных HTTP-соединений), что примерно столько же, сколько может выдержать аппаратное обеспечение. Это хорошо, потому что он предназначен для доступа только одного или двух человек, чтобы управлять коробкой.
В настоящее время все это прекрасно работает. Я кодировал его, чтобы реализовать столько RFC2616, которое я считаю необходимым для HTTP 1.1. На данный момент он просто прослушивает пять портов HTTPS (443), и я еще не реализовал ничего, чтобы перенаправить с порта 80.
Первый вопрос - Перенаправление
Я видел множество статей о перенаправлении с HTTP на HTTPS, но все, что я прочитал, касается того, как настроить существующие и обычные веб-серверы для этого. Я хочу выяснить, какие методы используются на уровне протокола, поскольку я должен реализовать это программно.
Обычный способ, по-видимому, заключается в выдаче ответа 301 / 302. Итак, стратегия, о которой я подумал, заключается в том, чтобы, для примера, у меня были ресурсы для восьми одновременных запросов:
Прослушивайте порт 443 для соединений HTTPS. Доступно до шести одновременных подключений HTTPS (шесть разъемов).
Прослушивайте порт 80 для HTTP-соединений, и доступно до двух HTTP-соединений (таким образом, два сокета на порту 80). Для сокетов на порте 80 настоящий веб-сервер не будет доступен. Вместо этого я просто продолжал бы читать из сокета, пока
\r\n\r\n
или же\n\n
виден (с указанием конца заголовка запроса) и затем отправляет обратно ответ 301 (или 302), который в моем коде был бы в значительной степени жестко закодированнымconst char*
строка. Затем закройте розетку. Эти два сокета порта 80 будут существовать исключительно для перенаправления.
Эта стратегия звучит разумно?
Единственное, в чем я сейчас не уверен, - это включение URL-адреса перенаправления в ответ 301 / 302. Этот аппаратный "ящик" представляет собой устройство, которое можно разместить в доме или где-то за маршрутизатором, возможно, получить к нему доступ через динамический DNS-сервис и т. Д. Итак, как бы я программно определил его URL-адрес HTTPS "внешнего мира"? Возможно, с помощью комбинации того, что в URI запроса и host:
поле исходного заголовка HTTP-запроса?
Если вышеизложенное создает какие-либо проблемы, то следующая лучшая идея, которую я имею, состоит в том, чтобы вместо этого вернуть небольшой фрагмент HTML, который содержит немного JavaScript, который выполняет перенаправление HTTPS путем извлечения URL-адреса из браузера (в частности, какие методы JavaScript я бы хотел позвонить, чтобы сделать это, я не могу вспомнить, но я сделал это давным-давно). (В настоящее время я также не уверен, как на самом деле будет работать SSL-сертификат, учитывая, что нет конкретного домена, который можно указать, но я собираюсь пересечь этот мост позже, возможно, в отдельном вопросе SO.)
Второй вопрос - предлагая HTTP и HTTPS
Это, пожалуй, гораздо больше вопроса о дизайне, или о том, что хочет заказчик, а не вопрос программирования - но я решил, что все равно оставлю этот вопрос здесь, чтобы узнать мнение людей. Моя проблема заключается в том, что клиент просто заявил, что поле "должно иметь SSL", но не более того. Чего я не знаю, так это того, могут ли они ожидать от конечного пользователя выбора, например, использовать или нет SSL. Теперь, прежде чем на самом деле спросить их, я просто ожидаю, что можно спросить, и я хотел бы заранее вооружиться некоторыми знаниями и ответами. Иными словами, люди, пишущие спецификацию для этого "просто хотят видеть замок" и "хотят SSL", что, очевидно, является хорошей вещью; но мне нужно подготовиться к глупым предложениям.
Прежде всего, я знаю, что не существует такого понятия, как промежуточное решение с SSL: вам нужно иметь все это или ничего. Другими словами, скажем, я решил попытаться уменьшить работу моего маленького процессора, обслуживая важные вещи через HTTPS, но я обслуживаю изображения и CSS-файлы через HTTP. После некоторого чтения я теперь точно знаю, почему это абсолютно нет-нет по многим причинам.
Что, если бы я сделал, однако, предложил конечному пользователю возможность выбрать либо HTTPS, либо HTTP на некоторой начальной странице входа? Выбор "HTTPS" будет перенаправлять на страницу безопасного входа в HTTPS. Это может быть полезным предложением, если пользователь решит скомпрометировать безопасность ради дополнительной скорости доступа, например, при доступе к устройству с мобильного телефона. Эта начальная страница может предлагать как "безопасный вход в систему", так и "стандартный незащищенный вход в систему - не рекомендуется" или подобное. Очевидно, что это открывает уязвимость с точки зрения пользователя, но также это ставит под угрозу соединение SSL? Под этим я подразумеваю то, что поскольку начальная страница входа в систему должна обслуживаться через HTTP, предположительно, злоумышленник теоретически может изменить ее так, чтобы кнопки менялись местами - такого рода вещи. Следовательно, должен ли HTTPS означать HTTPS с самого начала? Учитывая, что мне удалось включить HTTPS в эту штуку и заставить его работать, а также учитывая, что он специально разработан для использования с современным браузером (IE8/9, FF), есть ли практическая причина, почему нормальный доступ HTTP должен быть предлагается в качестве альтернативы?
1 ответ
На вопрос 1: я думаю, что оба метода являются надежными и регулярно используются коммерческими сайтами, однако чтение заголовка узла и возврат 301 определенно предпочтительнее, если пространство на стороне сервера действительно ограничено.
Что касается вопроса 2, то одним из возможных возражений против предложения обоих протоколов является то, что некоторые атаки типа "злоумышленник в середине" будут перенаправлять запрос / ответ https комм на http с точки зрения клиента во время сеанса. Большинство браузеров защищают от перенаправления в середине сеанса с помощью предупреждающего сообщения, но если злоумышленник заранее знает целевой сайт, он может обмануть пользователя, особенно если пользователь ожидает, что сайт может работать в любом режиме. По этой причине (и, возможно, по ряду причин, о которых я не знаю), имеет смысл ограничиться https, поскольку вы все равно уже сделали работу.