CivetWeb
CivetWeb is an easy to use, powerful, C/C++ embeddable web server with optional CGI, SSL and Lua support.
CivetWeb can be used by developers as a library, to add web server functionality to an existing application. CivetWeb uses an MIT license.
It can also be used by end users as a stand-alone web server. It is available as single executable, no installation is required.
To find the latest stable release, visit https://github.com/civetweb/civetweb/releases. A list of selected changes can be found in the release notes.
End users can download CivetWeb at SourceForge https://sourceforge.net/projects/civetweb/
Developers can contribute to CivetWeb via GitHub https://github.com/civetweb/civetweb
New releases are announced at Google Groups https://groups.google.com/d/forum/civetweb
Formerly some support question and discussion threads have been at Google groups. Recent questions and discussions use GitHub issues.
A security policy can be found in SECURITY.md.
CivetWeb is free of charge, however, donations for maintenance are welcome:
Documentation
- Installing.md — Install Guide (for end users using pre-built binaries)
- UserManual.md — End User Guide
- Building.md — Building the Server (quick start guide)
- Embedding.md — Embedding (how to add HTTP support to an existing application)
- OpenSSL.md — Adding HTTPS (SSL/TLS) support using OpenSSL.
- Docker.md — Use CivetWeb in a Docker container.
- APIReference.md — Additional documentation on the civetweb application programming interface (civetweb.h).
civetweb is maintained by civetweb
This page was generated by GitHub Pages.
Civetweb что это
Пример Secure Login демонстрирует использование паттерна Information Obscurity. Пример демонстрирует возможность передачи критической для системы информации через недоверенную среду.
В примере имитируется получение удаленного доступа к IoT-устройству посредством передачи этому устройству учетных данных пользователя (имени пользователя и пароля). Недоверенной средой внутри IoT-устройства является веб-сервер, который обслуживает запросы пользователей. Практика показывает, что такой веб-сервер является легко обнаруживаемым и зачастую успешно атакуемым, так как IoT-устройства не имеют встроенных средств защиты от проникновения и других атак. Кроме того, пользователи получают доступ к IoT-устройству через недоверенную сеть. Очевидно, что в таких условиях для защиты учетных данных пользователя от компрометации необходимо использовать криптографические алгоритмы.
С точки зрения архитектуры в таких системах можно выделить следующие субъекты:
- Источник данных: браузер пользователя.
- Точка коммуникации с устройством: веб-сервер.
- Подсистема обработки информации от пользователя: подсистема аутентификации.
При этом для использования криптографической защиты необходимо выполнить следующие шаги:
- Обеспечить взаимодействие источника данных и устройства по протоколу HTTPS. Это позволит избежать «прослушивания» HTTP-трафика и атак типа MITM (man in the middle).
- Выработать между источником данных и подсистемой обработки информации общий секрет.
- Использовать этот секрет для шифрования информации на стороне источника данных и расшифровки на стороне подсистемы обработки информации. Это позволит избежать компрометации данных внутри устройства (в точке коммуникации).
Пример Secure Login включает следующие компоненты:
- Веб-сервер Civetweb (недоверенный компонент, программа WebServer ).
- Подсистему аутентификацию пользователей (доверенный компонент, программа AuthService ).
- TLS-терминатор (доверенный компонент, программа TlsEntity ). Этот компонент поддерживает транспортный механизм TLS (transport layer security). TLS-терминатор совместно с веб-сервером поддерживают протокол HTTPS на стороне устройства (веб-сервер взаимодействует с браузером через TLS-терминатор).
Процесс аутентификации пользователя происходит по следующей схеме:
- Пользователь открывает в браузере страницу по адресу https://localhost:1106 (при запуске примера на QEMU) или по адресу https://:1106 (при запуске примера на Raspberry Pi 4 B). HTTP-трафик между браузером и TLS-терминатором будет передаваться в зашифрованном виде, а веб-сервер будет работать с открытым HTTP-трафиком. В примере используется самоподписанный сертификат, поэтому большинство современных браузеров сообщит о незащищенности соединения. Нужно согласиться использовать незащищенное соединение, которое тем не менее будет зашифрованным. В некоторых браузерах возможно возникновение сообщения «TLS: Error performing handshake: -30592: errno = Success» .
- Веб-сервер Civetweb , запущенный в программе WebServer , отображает страницу index.html , содержащую приглашение к аутентификации.
- Пользователь нажимает на кнопку Log in .
- Программа WebServer обращается к программе AuthService по IPC для получения страницы, содержащей форму ввода имени пользователя и пароля.
- Программа AuthService выполняет следующие действия:
- генерирует закрытый ключ, открытые параметры, а также вычисляет открытый ключ по алгоритму Диффи-Хеллмана;
- создает страницу auth.html с формой ввода имени пользователя и пароля (код страницы содержит открытые параметры и открытый ключ);
- передает полученную страницу программе WebServer по IPC.
- Веб-сервер Civetweb , запущенный в программе WebServer , отображает страницу auth.html с формой ввода имени пользователя и пароля.
- Пользователь заполняет форму и нажимает на кнопку Submit (корректные данные для аутентификации содержатся в файле secure_login/auth_service/src/authservice.cpp ).
- Код страницы auth.html , который исполняется на стороне браузера, осуществляет следующие действия:
- генерирует закрытый ключ, вычисляет открытый ключ и общий секретный ключ по алгоритму Диффи-Хеллмана;
- выполняет шифрование пароля операцией XOR с использование общего секретного ключа;
- передает веб-северу имя пользователя, зашифрованный пароль и открытый ключ.
- Программа WebServer обращается к программе AuthService по IPC для получения страницы, содержащей результат аутентификации, передавая имя пользователя, зашифрованный пароль и открытый ключ.
- Программа AuthService выполняет следующие действия:
- вычисляет общий секретный ключ по алгоритму Диффи-Хеллмана;
- расшифровывает пароль с использованием общего секретного ключа;
- возвращает страницу result_err.html или страницу result_ok.html в зависимости от результата аутентификации.
- Веб-сервер Civetweb , запущенный в программе WebServer , отображает страницу result_err.html или страницу result_ok.html .
Таким образом, конфиденциальные данные передаются через сеть и веб-сервер только в зашифрованном виде. Кроме того, весь HTTP-трафик передается через сеть в зашифрованном виде. Для передачи данных между компонентами используются взаимодействия по IPC, которые контролируются модулем Kaspersky Security Module.
Unit-тестирование с использованием фреймворка GoogleTest
Помимо паттерна Information Obscurity пример Secure Login демонстрирует использование фреймворка GoogleTest для выполнения unit-тестирования программ, разработанных под KasperskyOS (KasperskyOS Community Edition содержит в своем составе этот фреймворк).
Исходный код тестов находится по следующему пути:
Эти unit-тесты предназначены для верификации некоторых cpp-модулей подсистемы аутентификации и веб-сервера.
Чтобы запустить тестирование, выполните следующие действия:
- Перейдите в директорию с примером Secure Login .
- Удалите директорию build с результатами предыдущей сборки, выполнив команду: sudo rm -rf build/
- Откройте файл скрипта cross-build.sh в текстовом редакторе.
- Добавьте в скрипт флаг сборки -D RUN_TESTS=»y» \ (например, после флага сборки -D CMAKE_BUILD_TYPE:STRING=Release \ ).
- Сохраните файл скрипта, а затем выполните команду: $ sudo ./cross-build.sh
Тесты выполняются в программе TestEntity . Программы AuthService и WebServer не запускаются, поэтому при выполнении тестирования пример нельзя использовать для демонстрации паттерна Information Obscurity.
После завершения тестирования выводятся результаты выполнения тестов.
Код примера и скрипты для сборки находятся по следующему пути:
Сборка и запуск примера
Чтобы запустить пример на QEMU, перейдите в директорию с примером, соберите пример и выполните следующие команды:
# Перед выполнением следующей команды убедитесь, что путь к
# директории с исполняемым файлом qemu-system-aarch64 сохранен в
# переменной окружения PATH. В случае отсутствия
# добавьте его в переменную PATH.
$ qemu-system-aarch64 -m 2048 -machine vexpress-a15 -nographic -monitor none -net nic,macaddr=52:54:00:12:34:56 -net user,hostfwd=tcp::1106-:1106 -sd sdcard0.img -kernel kos-qemu-image
циветвеб
Это приложение для Linux под названием civetweb, последний выпуск которого можно загрузить как CivetWeb_Win32+64_V1.15.zip. Его можно запустить онлайн на бесплатном хостинг-провайдере OnWorks для рабочих станций.
Загрузите и запустите онлайн это приложение под названием civetweb с OnWorks бесплатно.
Следуйте этим инструкциям, чтобы запустить это приложение:
— 1. Загрузил это приложение на свой компьютер.
— 2. Введите в нашем файловом менеджере https://www.onworks.net/myfiles.php?username=XXXXX с желаемым именем пользователя.
— 3. Загрузите это приложение в такой файловый менеджер.
— 4. Запустите онлайн-эмулятор OnWorks Linux или Windows или онлайн-эмулятор MACOS с этого веб-сайта.
— 5. В только что запущенной ОС OnWorks Linux перейдите в наш файловый менеджер https://www.onworks.net/myfiles.php?username=XXXXX с желаемым именем пользователя.
— 6. Скачайте приложение, установите его и запустите.
Миниатюрное десктопное GUI приложение на PHP — 2 МБ хватит для всех
Я часто заморачиваюсь на тему минимизации размера своих GUI приложений. Прошлая моя статья была про Nuklear. Но сейчас захотелось более современных технологий. Чтоб HTML5, CSS3 и PHP. Чтоб приложение ни от чего не зависело, т.е. построено по принципу «всё включено». И чтоб конечный размер приложения не превысил 2 мегабайта. Получится ли?
В Linux я часто пользуюсь утилитой df. Мне её очень не хватает в Windows, а искать аналоги лень. А уж тем более было лень запускать всякие там Explorer, Powershell и т.п. — это слишком нормально :-). Так что было сделано волевое решение сделать свою утилиту, на РНР 5, с бутстрапом и JQuery.
Краткое решение моей задачи: CivetWeb + WebView + PH7.
Т.е. результирующее приложение это и веб-сервер, который раздаёт статические файлы и выполняет скрипты (CivetWeb). И непосредственно браузер, который к этому веб-серверу подключается (WebView). PHP выполняется как СGI-BIN, через сторонний интерпретатор PH7.
Здесь заключена основная фишка связки — в качестве интерпретатора СGI-BIN может быть использован любой язык/компилятор/интерпретатор. Хоть Haxe используй, хоть Go, хоть на Powershell веб-страницы генерируй, хоть полноценный PHP возьми. Так же прямо в CivetWeb встроен интерпретатор Lua, который позволяет делать легковесные, но полноценные приложения.
Хватит лирики, перейдём к коду. PHP не самый лучший язык для создания системных приложений. Например, в нём нет функции для получения системных дисков. Но когда это нас останавливало? В Windows воспользуемся перебором всего алфавита и проверкой существования директории. В Linux же функция построчно читает файл /etc/fstab , разбивает каждую строку по пробелам чтоб получить столбцы, и проверяет на существование директории:
function fs_get_roots() < static $roots = null; if ($roots === null) < if (strncasecmp(PHP_OS, 'WIN', 3) === 0) < $driveLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; for ($i = 0; $i < strlen($driveLetters); $i++) < $curDrive = $driveLetters[$i].':\\'; if (is_dir($curDrive)) < $roots[] = $curDrive; >> > else < foreach (file('/etc/fstab') as $line) < if ($line[0] != '#') < $line = str_replace('\t', ' ', $line); do $line = str_replace(' ', ' ', $line, $count); while($count); $rows = explode(' ', $line); if (count($rows) && is_dir($rows[1])) < $roots[] = $rows[1]; >> > > > return $roots; >
Корни файловой системы кэшируются в статической переменной $roots . Т.е. если несколько раз вызвать эту функцию при генерации страницы, то последующий вызов отработает очень быстро, повторно диск сканироваться не будет.
С одной стороны, код получился не очень красивым. Прямой парсинг системных файлов используется в Linux для написания низкоуровневых утилит. Например, какая-нибудь из реализаций df вполне может читать /etc/fstab , такой код нормален для программ написанных на Си. Но не для высокоуровневых языков программирования. Угадывание имени диска по алфавиту — вообще злостный хак. Например, если в DVD-приводе будет вставлен диск, то при каждом обращении он будет раскручиваться. А ещё диски могут быть двухбуквенными, смонтированными в директорию, быть доступными только по GUID и т.д. и т.п. — все они будут пропущены.
С другой стороны, результат достигнут. PHP предназначен для генерирования веб-страниц. Но при желании даже на нём можно писать системное программное обеспечение.
JQuery
В качестве отображения использую пример прогрессбара на бутстрапе. Здесь вам и сам Bootstrap, и HTML5, и ещё и JQuery зачем-то подключен.
Одним из желаний было чтобы в приложение была встроена система локализации. Чтоб русскоязычные пользователи видели приложение на русском, чехи — на чешском и т.д. Система локализации будет сделана на JQuery. Ну надо же его хоть для чего-нибудь использовать:
$(document).ready(function() < var userLang = (navigator.language || navigator.userLanguage)?.substring(0, 2)?.toLowerCase(); $('[data-' + userLang + ']').each(function(element) < var localized = $(this).data(userLang); $(this).text(localized); >); >);
В переменной userLang хранится 2 буквы языка браузера пользователя. Например, ru . Далее перебираем все теги у которых есть атрибут data-ru . Далее просто устанавливается текст текущего элемента, полученный из данных.
Пример HTML разметки для использования такой системы локализации:
System Drives
Здесь сразу же виден основной недостаток такой системы локализации — код становится очень перегруженным, все пользователи всегда загружают данные для всех языков. Такая локализация подходит если в проекте нужно перевести порядка десятка коротких фраз и на малое количество языков. Т.е. годится только для примера.
PH7
PH7 — альтернативная реализация PHP для встраиваемых систем. PH7 разрабатывалась чтоб оживить интерфейс в роутерах, где до этого часто HTML-коды встраивались прямо в прошивку, написанную на Си.
PH7 бесплатен для проектов с открытым исходным кодом. Основным преимуществом является крайне малый размер — у меня получилось скомпилировать ph7-cgi в приложение размером порядка 300 килобайт.
Недостатков у PH7 чуть больше чем достоинств. Основные:
- Устаревшая версия PHP. Версия 5.3 вышла в 2009 году.
- Нет поддержки регулярных выражений. Это автоматически отметает возможность использования многих библиотек (Smarty, Twig и т.д.)
- Не все функции работают кроссплатформенно.
- Не все функции работают.
Например, функции disk_total_space и disk_free_space всегда возвращают пустое значение в Linux, что видно на скриншоте. Я не стал делать альтернативную реализацию этих функций (например через разбор выхлопа df ) т.к. это не является целью данной публикации. Да и в принципе проблематично вызывать сторонние утилиты, т.к. на месте функции exec стоит заглушка всегда возвращающая пустое значение.
В общем, PHP в данной публикации скорее элемент юмора, чем реальной пользы.
CivetWebView
Краткое решение уже было написано выше. Рассмотрим клиентско-серверную часть: CivetWeb + WebView.
CivetWeb (бывший Mongoose до смены лицензии) является стандартом де-факто когда нужно что-то быстро раздать по HTTP на десктопе. Это не промышленное решение типа Nginx — моему локальному серверу не нужно раздавать миллионы файлов в секунду. И сотни злобных хакеров не будут пытаться его взломать. И очень большой вопрос, будет ли он вообще когда-либо пущен во внешнюю сеть.
WebView же — просто возможность встроить системный браузер в своё приложение. Для Windows это будет Edge, для Linux — GTK WebKit, для мака — Cocoa или WebKit. Т.е. какой-нибудь однозначно современный браузер, который хорошо поддерживает и HTML5, и CSS3, и JavaScript. При этом результирующее приложение не разрастётся на сотни мегабайт, т.к. непосредственно движок в полученное приложение встроен не будет.
Обе эти технологии для меня выглядят хорошо. Единственное, я так и не нашёл ни одного проекта, объединяющих их. Поэтому пришлось делать свой: CivetWebView — https://github.com/DeXP/CivetWebView
По сути CivetWebView — это объединение кода двух примеров: CivetWeb и WebView. На текущий момент проект скорее в стадии прототипа — реализован лишь необходимый мне функционал. Многие вещи заданы просто как константы в коде.
Пример развития проекта: умение загружать значения из файла конфигурации, поддержка полноэкранного режима, возможность динамической установки заголовка окна и его размеров.
Размер
Полное Win32 приложение занимает 1.53МБ. Самым объёмным компонентом является CivetWebView, который занимает почти мегабайт. Следующим идёт интерпретатор РНР размером 282 килобайта. Завершают тройку лидеров Bootstrap и JQuery, которые в сумме занимают 274 килобайта (без отладочных map-файлов). Сам код приложения (PHP + HTML + CSS) занимает порядка 5 килобайт.
Исходные коды и архивы с бинарными файлами можно скачать на гитхабе: https://github.com/DeXP/CivetWebView-PH7-Example
Лицензии
Всё кроме PH7 лицензировано под «да делайте с этим что хотите, нам абсолютно всё равно». Т.е. если исключить из связки PH7, то можно делать коммерческие приложения. Кто-нибудь мне объяснит, зачем?)
Зачем всё это надо
Изначально у меня не стояла задача создания сферического GUI проекта в вакууме. Был проект онлайн интерпретатора визуальных новелл с консоли DS — VNDS-Online. И мне сразу хотелось иметь возможность запускать эти игры не только на каком-нибудь сайте, но и локально на своём компьютере. Или на каком-нибудь другом устройстве.
vnds-online не может работать без серверной части. Как минимум, нужно иметь возможность получать список имеющихся игр. Этот функционал было не слишком сложно переписать на LUA.
Кроме того, хотелось дать возможность запускать игры простым двойным кликом по ЕХЕ-файлу. Чтоб даже самый далёкий от веб-разработки человек мог играть.
Проект в итоге получился компактным за счёт того, что большая часть кода подразумевает исполнение в браузере. Который уже установлен в систему, хорошо отлажен и оптимизирован. В общем, спасибо большое ВаЮрику за замечательный движок.
Однако vnds-online тоже есть куда развиваться. Например, в движок явно нужно встроить возможность локализации. Ещё хотелось бы возможность адаптировать картинку под современные широкие экраны. Ну и отладка существующих багов разумеется.
Вопросы вместо выводов
Вместо вывода хочу задать сообществу два вопроса:
- Кому-нибудь нужен CivetWebView? Стоит ли его развивать? Вы бы им пользовались? Для чего? Есть ли какие-нибудь настоящие сценарии использования, где бы оно пригодилось? Или мир уже захватили Electron на пару с Node.js?
- Кому-нибудь нужен ещё один интерпретатор VNDS? Возможно под какие-нибудь странные платформы, но с современным браузером. Стоит ли вообще развивать vnds-online?
Полезные ссылки
- GitHub: CivetWebView
- GitHub: CivetWebView пример PH7 (герой данной статьи)
- Эта публикация на английском