Русский
Русский
English
Статистика
Реклама

Устройство пакетной системы OpenWRT

Операционная система OpenWRT обычно используется как прошивка для роутеров. Типичное применение заключается в том, чтобы установить и забыть. Но если вдруг вам чего-то не хватит, то придётся разбираться в устройстве дистрибутива.



OpenWRT использует OPKG в качестве пакетного менеджера, точнее, собственный форк. Дебианщикам он во многом покажется знакомым: похожие команды, похожий формат репозитория и пакетов.

Мне захотелось запатчить LUCI (этого в статье не будет), но адекватного быстрого введения я не нашёл, пришлось самостоятельно собирать отрывки сведений из разрозненной документации, статей и примеров, поглядывая в код и на результаты работы. Бонусом собрал примитивный (но бесполезный на практике) пакет, которого ещё нет в репозитории. Собранным ликбезом делюсь ниже.

Устройство репозитория


В файловой системе OpenWRT есть файл /etc/opkg/distfeeds.conf, в нём указывается системный (предоставленный разработчиками OpenWRT и OPKG) список репозиториев. Собственные и сторонние репозитории можно указать в /etc/opkg/customfeeds.conf. Формат однострочный, состоит из трёх слов:

  1. src или src/gz, от этого зависит, будет качаться файл Packages или Packages.gz. Судя по коду, есть другие опции для первого слова, но я не нашёл репозиториев, для которых это было бы актуально. Несмотря на src в названии, это репозиторий для бинарных пакетов. Специального формата репозиториев для пакетов с исходным кодом, аналогичного тому, что используется в Debian/APT, у OPKG не предусмотрено.
  2. Название репозитория или фида в терминологии OPKG/OpenWRT.
  3. URL, внутри которого лежит файл Packages/Packages.gz.

При выполнении opkg update к URL через / добавляется Packages или Packages.gz, список пакетов и подписи сохраняется в /tmp/opkg-lists, файл называется соответственно второму слову в списке репозиториев. Отсюда два важных вывода:

  1. При перезагрузке кэш очистится. На встроенных системах вроде роутеров это абсолютно разумно.
  2. В /etc/opkg/customfeeds.conf можно оверрайдить системные фиды своими собственными, дав им такое же название. OPKG ругнётся, но проглотит оверрайд, сложив нужный файлик вместо загруженного ранее.

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

  • Package, имя пакета;
  • Version, версия, при наличии нескольких пакетов с одинаковым именем можно выбрать версию, по умолчанию установится самая свежая;
  • Depends, зависимости от других пакетов, пакетный менеджер доустановит перечисленные пакеты в случае их отсутствия в системе;
  • Filename, путь к файлу относительно базового URL репозитория, обычно репозиторий плоский и всё лежит там же, где и `Packages.gz`;
  • SHA256sum, заявленный репозиторием хэш пакета.

Если хотите больше подробностей, можете просто прочитать один из таких списков прямо в браузере.

Бинарные пакеты


Бинарные пакеты почти аналогичны пакетам Debian. Разница следующая:

  1. Расширении .ipk вместо .deb.
  2. Упаковывается всё с помощью `tar` и сжимается с помощью gzip, это же справедливо для вложенных архивов. В Debian архив верхнего уровня упаковывается более примитивным ar, а вложенные архивы чаще всего имеют расширение .tar.xz, инструменты используются соответствующие.

Если вы поменяете расширение пакета для OpenWRT на .tar.gz и распакуете, то обнаружите внутри два архива и один текстовый файл. Файл называется debian-version, в нём содержится версия формата бинарного файла и она нам не очень интересна, в современных системах эта версия всегда равняется 2.0.

Архив data.tar.gz содержит исполняемые файлы, файлы конфигурации и всё, ради чего устанавливается пакет. Если распаковать его в корень ФС, вы получите все ожидаемые файлы на нужных местах, в /usr/bin/, /etc/ и так далее.

А в control.tar.gz находятся вспомогательные файлы для пакетного менеджера. Это скрипты, которые должны выполняться до или после установки и удаления (preinst, postinst, prerm, postrm), сведения о файлах, являющихся конфигурационными, и метаинформация о пакете, во многом повторяющая ту, что содержится в Packages.

Система сборки пакетов


Сборочная система (она же SDK) выполнена в виде Make-фреймворка. Фреймворк не подразумевает, что вы будете собирать пакеты по отдельности, его основная задача заключается в сборке целых репозиториев.

SDK для x86_64 лежит в git. Есть архив (ссылка скоро устареет, но найти свежий несложно), который сэкономит вам время на компиляции тулчейна для сборки. Внутри особый интерес представляет файл feeds.conf.default. Формат несложный, через пробел:

  1. Ключевое слово src-git. Поддерживается не только git, но сейчас репозиториев в иных VCS нет.
  2. Название фида.
  3. URL git-репозитория, в котором можно указать коммит или тег. Если вы знаете, как называется такая спецификация, подскажите, пожалуйста.

Сам репозиторий с пакетами устроен максимально просто: в корне репозитория категория пакета, на втором уровне директория с названием пакета, а внутри него лежит Makefile, опционально `Config.in` для дополнительных опций при выполнении make menuconfig и субдиректория patches с соответствующим содержимым. Для простейшего пакета достаточно только Makefile. Для примера можете заглянуть в зеркало основного репозитория.

Тестовая сборка


Я попробовал собрать GNU Hello, чтобы проверить, как работает SDK. Это сравнительно монструозный Hello World, написанный в строгом соответствии с гайдлайнами проекта GNU, его единственная задача заключается в иллюстрации этих гайдлайнов. Отдельный репозиторий для него не создавал, а вместо этого подсунул в базовые пакеты SDK, откуда и скомпилировал.

Для работы самого SDK в окружениии Debian понадобятся пакеты libncurses-dev (для меню сборки), build-essential (GCC и прочие стандартные зависимости программ на C), gawk, unzip, file, rsync и python3. Также для создания репозитория из собранных пакетов, потребуется утилита для генерации ключей usign. Её в репозитории нет, поэтому дополнительно потребуется `cmake` для сборки. Этот инструмент можно заменить как на GPG, так и на signify-openbsd, но она рекомендуется и разрабатывается проектом OpenWRT, а также гораздо приятней в использовании.

Компилируем и устанавливаем usign:

git clone https://git.openwrt.org/project/usign.gitcd usigncmake .makesudo make install 

Вместо установки (sudo make install) можете просто запомнить, где находится бинарь, чтобы в дальнейшем дёргать его руками.

Теперь базовая настройка SDK:

git clone https://git.openwrt.org/openwrt/openwrt.gitcd openwrt./scripts/feeds update -a./scripts/feeds install -a

Напоминаю, что вместо клонирования из git, можете скачать и распаковать архив с прекомпилированным тулчейном. Не забудьте только скачать свежую версию!

Выполняя ./scripts/feeds update -a мы клонируем/обновляем все репозитории из feeds.conf(.default), проверяем зависимости и готовим директорию staging_dir/host/bin с исполняемыми файлами (в основном это симлинки на системные утилиты). Следующая команда, ./scripts/feeds install -a, рассовывает симлинки в package/feeds, откуда они и будут браться для компиляции. Эти две команды не обязательны для сборки моего кастомного пакета.

Далее выполняется make menuconfig. Можно пропустить, но при компиляции пакета всё равно выдаст соответствующее окошко. В нём достаточно поменять таргет и сабтаргет, чтобы всё скомпилировалось под x86_64 и выйти, согласившись с сохранением конфига. Также потребуется собрать вспомогательный инструментарий для сборки (make tools/install) и тулчейн (make toolchain/install). Если вы качали SDK из архива, то make menuconfig вам не покажет опций для выбора таргета, а сборка инструментария и тулчейна не требуется всё уже есть на месте.

Теперь я создаю директорию package/devel/hello, в которой размещаю Makefile следующего содержания:

Makefile
include $(TOPDIR)/rules.mkPKG_NAME:=helloPKG_VERSION:=2.9PKG_RELEASE:=1PKG_LICENSE:=GPL-3.0-or-laterPKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gzPKG_SOURCE_URL:=@GNU/hello/PKG_HASH:=ecbb7a2214196c57ff9340aa71458e1559abd38f6d8d169666846935df191ea7include $(INCLUDE_DIR)/package.mkdefine Package/hello        SECTION:=devel        CATEGORY:=Development        TITLE:=GNU Hello        URL:=https://www.gnu.org/software/hello/endefdefine Package/hello/description        The GNU Hello program produces a familiar, friendly greeting. Yes,        this is another implementation of the classic program that prints        Hello, world! when you run it. However, unlike the minimal version        often seen, GNU Hello processes its argument list to modify its        behavior, supports greetings in many languages, and so on. The primary        purpose of GNU Hello is to demonstrate how to write other programs that        do these things; it serves as a model for GNU coding standards and GNU        maintainer practices.endefdefine Package/hello/install        $(INSTALL_DIR) $(1)/usr/bin        $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/hello $(1)/usr/bin/endef$(eval $(call BuildPackage,hello))

В основном всё должно быть понятно без пояснений. Подключаются файлы фреймворка, описываются основные параметры пакета, @GNU подменяется на зеркала проекта GNU (определены во фреймворке), а путь состоит из двух частей: PKG_SOURCE_URL, в котором указывается базовый URL для всех версий и расширяется конкатенацией именем файла из PKG_SOURCE через слэш. В Package/hello/install содержатся инструкции по сборке бинарей в архив data.tar.gz. Дополнительные опции для сборки, если потребуются, доступны в документации. Кстати, не забудьте, что make очень требователен к отступам, у меня вместо начальных пробелов были одиночные табы.

Снова вызываете make menuconfig, проверяете, что в обозначенной секции (Development в моём случае) отмечен пакет hello и выходим сохранив конфиг. Наконец, собираем пакет в три этапа; скачивание, распаковка и собственно компиляция:

make package/hello/downloadmake package/hello/preparemake package/hello/compile

В результате я получил пакет bin/packages/x86_64/base/hello_2.9-1_x86_64.ipk. Можно собирать репозиторий. Генерируем пару ключей (usign -G -c 'openwrt test repo' -s key-build -p key-build.pub, приватный ключ обязательно должен называться `key-build`), и собираем репозиторий: make package/index. На этом этапе сборка может ругнуться на отсутствие usign в директории со вспомогательными утилитами, я решил проблему симлинком: ln -s `which usign` staging_dir/host/bin/usign. Теперь рядом с пакетом лежит полный набор, необходимый для репозитория.

Проверяем репозиторий вместе с пакетом


Вы можете проверить всё на настоящем роутере (не забудьте только выбрать правильный таргет), но я воспользовался Докером. В Докерхабе есть образ OpenWRT для x86_84, который можно запустив, пробросив внутрь контейнера директорию с SDK: sudo docker run -it --name openwrt_test -v $PWD:/opt openwrtorg/rootfs. Потыкайте кнопку ввода пока не появится приглашение Баша.

Копирую ключ из проброшенной директории (cp /opt/key-build.pub /etc/opkg/keys/usign -F -p /opt/key-build.pub, название ключа обязательно должно совпадать с идентификатором), добавляю свой локальный репозиторий (echo src/gz local file:///opt/bin/packages/x86_64/base >> /etc/opkg/customfeeds.conf), обновляю репозиторий (opkg update). Вывод начинается с обнадёживающего текста, всё подписано верно:

# opkg updateDownloading file:///opt/bin/packages/x86_64/base/Packages.gzUpdated list of available packages in /var/opkg-lists/localDownloading file:///opt/bin/packages/x86_64/base/Packages.sigSignature check passed.

Осталось только установить и проверить:

root@34af2f6e849b:/# opkg install helloInstalling hello (2.9-1) to root...Downloading file:///opt/bin/packages/x86_64/base/hello_2.9-1_x86_64.ipkConfiguring hello.root@34af2f6e849b:/# helloHello, world!

Ура, готово! Несмотря на разбросанную по статьям документацию, процесс сборки пакетов довольно прост.



Источник: habr.com
К списку статей
Опубликовано: 02.12.2020 18:09:40
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании ruvds.com

Настройка linux

*nix

Разработка под linux

Diy или сделай сам

Openwrt

Opkg

Package management

Ruvds_статьи

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru