Мой блог теперь доступен и по протоколу Gemini
Опубликовано 25.12.2024 в OpenBSD
Хотите поговорить про Господа наше^W^W Gemini? Нет, не про зодиакальное созвездие Близнецы и не про одноименную космическую программу NASA, а про Gemini из области этого вашего IT. Но нет, не про очередного AI-чат-бота от Google. А про Gemini - протокол прикладного уровня для передачи гипертекста. В общем, я уже всерьез подозреваю, что настолько неудачное название было выбрано намеренно, чтобы затруднить поиск информации и оставить это поделие игрушкой для гиков...
Дело было так: на LOR (почитываю изредка по старой памяти) вышла очередная новость про релиз очередной софтины с поддержкой протокола Gemini (видимо, там окопался какой-то евангелист оного). И стало мне интересно, а как с поддержкой этого "ненужно" в OpenBSD?
Что такое протокол Gemini
Давным-давно, когда этот ваш Web еще не был таким жирным, напичканным трекерами и рекламой до полной невозможности пользоваться (без толстого интернет-канала и применения изощренных решений для блокировки оного), существовал протокол-предшественник современного HTML под названием Gopher (вот как надо выбирать названия, хоть прикольно - не "site", а "gopherhole"). Собственно, формально-то он и сейчас существует, и кто-то даже пользуется, но последним из приличных браузеров поддержку протокола gopher выпилил Firefox, еще в 2010-м году. И настала эпоха современного Web - c HTML, скриптами, рекламой, трекерами и вот этим вот всем.
Но идея "мы запилим свой веб, с блекдж^W без рекламы, трекеров и скриптов" оказалась привлекательной и на руинах Gopher зародился протокол Gemini - простой протокол передачи файлов, с поддержкой MIME-типов, TLS и собственным языком гипертекстовой разметки gemtext (чем-то похожим на Markdown, но сильно урезанный). На самом деле комьюнити, развивавшее протокол, никогда не позиционировало его как замену HTTP или даже как замену Gopher - просто еще одно "чуть более другое" решение, призванное сосуществовать с вышеназванными и использоваться теми, кому оно интересно.
Протокол финализирован в 2022 году (хоть и не стал пока официально зарегистрированным стандартом) и более развиваться не будет - намеренное решение для сохранения духа "не усложняй". Принцип работы прост, как гвоздь: gemini-клиент (о них ниже) запрашивает у gemini-сервера (слушающего tcp-порт 1965) данные по урлу, например, так:
gemini://muu-online.ru/
и получает в ответ содержимое файла (указанного в URL или "index.gmi" если не указан) вроде такого:
20 text/gemini
# Это заголовок страницы (поддерживается 3 уровня заголовков)
Это текст страницы. Просто текст.
* Пример списка (вложенные и нумерованные не поддерживаются).
> Это цитата
=> gemini://link.to/another/resource Это ссылка (протокол возможен любой, ссылка всегда отдельной строкой)
Блок преформатированного текста, как и в Markdown, выделяется тремя `
Вот фактически и весь язык разметки gemtext. Кодировка всегда UTF-8 (вы можете использовать свою любимую эмодзи-какашку, ага). Размер запроса ограничен 1024 байтами. Используется TLS-шифрование по принципу "сертификат, полученный при первом обращении к серверу считается доверенным по умолчанию, если в дальнейшем сертификат изменится - клиентское приложение уведомит об этом пользователя" (так себе защита от MITM, но в SSH оно тоже так устроено, и никто не жалуется).
Чуть-чуть о терминологии: вся совокупность файлов, доступных по протоколу Gemini называется "Geminispace". Набор файлов, владельцем которых является одна персона/организация (аналог сайта в вебе) называется "capsule", а блог на протоколе Gemini принято называть "gemlog". У меня есть свой гемлог, ю-ху!
Как всегда с подобными гиковскими игрушками, gemini-серверов, клиентов и прочего связанного софта понаписано уже безумное количество - клиенты есть, например, под любые ОС (вплоть до plan9 и AmigaOS) и на любых языках - от чистого bash до всяких там Rust и Haskell. Кстати, в самом примитивном случае для общения с gemini-сервером вам не нужно ничего сложнее netcat: запускаете ncat -C --ssl muu-online.ru 1965
, набираете url gemini://muu-online.ru/
и наслаждайтесь!
Как в Gemini запросить контент у сервера - мы поняли, но как же насрать в комменты своим особо ценным мнением? Ведь Интернет создан именно для этого - анонимно (а значит, безнаказанно) гадить людям? Протокол ведь принципиально не поддерживает никакой авторизации для клиента, все клиенты анонимны и различить их можно разве что по IP, да и размер исходящего запроса ограничен 1024 байтами?
На самом деле, существуют форумы/bbs на протоколе Gemini, ссылка на пример ниже, и авторизация там - это просто еще один сертификат, генерируемый на стороне клиента (можно отдельно для каждого форума, можно совмещать, можно несколько для одного завести...). А для отправки, помимо запроса, еще и тела сообщения (практически неограниченной длины) существует родственный Gemini протокол Titan.
Форум bbs.geminispace.org
Описание протокола Titan
Ну и еще кучка ссылок для ознакомления:
Документация проекта Gemini
Набор софта для Gemini
Репозиторий gemini-awesome
Один из рабочих gemini-to-http прокси
Создаем свой гемлог на сервере с OpenBSD
В репозиториях OpenBSD нет прекомпилированных пакетов, связанных с Gemini, но в портах оно есть: и клиенты, и серверы. Серверов, собственно, два: gmid и vger. Мне приглянулся vger, как наиболее соответствующий юникс-вэю, эта программа умеет делать ровно одну вещь: принимать запрос из stdin и отдавать запрошенный файл в stdout, но умеет она это делать очень хорошо - запуск из-под непривилегированного пользователя, chroot, применение нативных для OpenBSD механизмов безопасности plegde и unveil... Однако для полноценной работы в качестве gemini-сервера нужно еще, чтобы кто-то слушал tcp-порт 1965, запускал при поступлении запроса на него, собственно, vger. А еще, поскольку протокол gemini требует обязательного применения TLS, кто-то должен и с сертификатами для этого самого TLS работать. И согласно юникс-философии, это тоже будут делать отдельные программы, делающие только это, но очень хорошо: inetd и relayd соответственно.
Перво-наперво, соберем сам vger хоть из портов, хоть из репозитория автора - легендарной Solène Rapenne (в русскоязычном комьюнити OpenBSD прозванной "Соленья" и недавно, к сожалению, принявшей решение перестать использовать OpenBSD, вот реально к большому сожалению).
Репозиторий vger и инструкции по установке тут
Далее, создадим каталог, где будут лежать наши .gmi-файлы (расположение по умолчанию /var/gemini) и добавим отдельного пользователя, под которым будет запускаться сервер: useradd -s /sbin/nologin _gemini
(пользователь должен иметь права на чтение из вышеупомянутого каталога).
Потом настроим собственно inetd, который будет слушать порт 11965 на локалхосте (создадим файл /etc/inetd.conf):
127.0.0.1:11965 stream tcp nowait _gemini /usr/local/bin/vger vger
Если нужны какие-то дополнительные параметры при запуске vger (см. man vger), их нужно дописать в конце этой же строчки, не забываем сделать doas rcctl enable inetd && doas rcctl start inetd
.
Теперь настроим relayd. Во-первых, нам нужны будут сертификаты - коль скоро у меня есть свой сайт, сертификаты от LetsEncript у меня уже есть и по cron они регулярно обновляются. Нужно лишь указать relayd, что их следует использовать при соединении с портом 1965, relayd ищет файлы сертификатов просто по имени, поэтому задача решается созданием софтлинков:
cd /etc/ssl
ln -s muu-online.ru.fullchain.pem muu-online.ru:1965.crt
ln -s muu-online.ru.ocsp muu-online.ru:1965.ocsp
cd private
ln -s muu-online.ru.key muu-online.ru:1965.key
Далее добавим настройки, собственно, проксирования, дописав в /etc/relayd.conf следующее:
tcp protocol "gemini" {
tls keypair muu-online.ru
}
relay "gemini" {
listen on egress port 1965 tls
protocol "gemini"
forward to 127.0.0.1 port 11965
}
Ну и последний шаг: рестартуем relayd (doas rcctl restart relayd
) и открываем в /etc/pf.conf порт 1965 наружу:
pass proto tcp from any to vio0 port 1965
Применяем новые настройки фаервола: doas pfctl -f /etc/pf.conf
и, собственно, всё уже должно работать: relayd слушает открытый наружу порт 1965 по TLS, проксирует запросы к inetd, а тот запускает vger для обработки запроса.
О клиентах: в портах OpenBSD присутствуют консольные клиенты bombadillo (консольный браузер с поддержкой протоколов Gopher, Gemini и Finger) и Amfora (консольный браузер для Gemini). Мне приглянулся второй. Кстати, если кому интересно, что такое Gopher и Finger, годное описание есть тут:
Интересная статья про "small web": Gopher, Gemini и Finger
А под Android весьма хорош Gemini-браузер Lagrange (есть на F-Droid).
P.S. В планах: написать конвертер, при помощи можно будет публиковать, с соответствующими изменениями форматирования, статьи сразу на https://muu-online.ru и на gemini://muu-online.ru, то есть вести бложик в двух форматах сразу.