Цей посібник описує, як налаштувати OpenWrt для використання зовнішнього носія (USB, SATA, SD-картки або іншого) для розширення кореневої файлової системи, щоб мати змогу встановлювати всі необхідні пакети.
У більшості підтримуваних пристроїв OpenWrt розділяє внутрішню пам’ять на розділи rootfs та rootfs_data або ubifs, які об'єднуються в єдину придатну для запису файлову систему типу overlay.
| Розділ | Точка монтування | Стиснення | Запис |
|---|---|---|---|
rootfs | /rom | Так | Ні |
rootfs_dataubifs | /overlay/rom/overlay | Ні | Так |
overlay | / | Незмінені файли | Так |
Таким чином, OpenWrt може працювати навіть на пристроях із дуже обмеженим обсягом внутрішньої пам’яті (від 4 МіБ), залишаючи можливість зберігати налаштування та встановлювати деякі пакети.
Extroot працює шляхом монтування нової розділу overlay з зовнішнього носія поверх внутрішнього під час завантаження. Це дозволяє легко повернутись до внутрішньої overlay у разі відключення зовнішнього накопичувача — пристрій завантажиться з власної overlay та працюватиме так само, як до налаштування extroot.
Відомо, що OpenWrt ігнорує конфігурацію fstab на пристроях, у яких відсутній розділ overlay у ``/proc/mtd``. Обхідним шляхом є використання ``/`` як точки монтування.
Наступні інструкції передбачають, що ви вже маєте доступ до shell на вашому пристрої OpenWrt. Більшість команд можна виконати через веб-інтерфейс, але це не рекомендується.
Доступ до shell зазвичай отримують через SSH або послідовний порт.
Пристрої з флеш-пам’яттю 8 МіБ або більше зазвичай мають достатньо місця для встановлення необхідних пакетів. В іншому разі створіть кастомний образ.
Видаліть усі пакети, встановлені для вторинного функціоналу — вони просто займають місце. Якщо ви не пам’ятаєте, що саме встановлювали — спробуйте видалити 'ntfs', це може звільнити простір.
Залиште лише ті пакети, які потрібні для доступу до Інтернету та extroot.
У деяких випадках достатньо буде використати офіційний OEM-образ (наприклад, OpenWRT GL.inet для GL.inet Mango).
Extroot може бути будь-яким пристроєм, який може монтувати утиліта ``block``. Підтримувані файлові системи: ext2/3/4, f2fs, btrfs, ntfs або ubifs (зверніть увагу, що FAT16/32 не підтримуються).
Найчастіше це USB-накопичувач, але також це може бути SD-картка, SATA-диск, мережевий пристрій тощо.
Якщо ви використовуєте USB-пристрій, налаштуйте його згідно з інструкцією зі встановлення за допомогою USB.
Нижче передбачено, що extroot створюється на USB-накопичувачі з файловою системою EXT4.
Установка необхідних пакетів вимагає значного обсягу вільного місця. Якщо система переповниться — доведеться прошивати все заново.
Встановіть необхідні пакети:
opkg update
opkg install block-mount kmod-fs-ext4 e2fsprogs parted kmod-usb-storage
Якщо ви використовуєте SSD в USB-кейсі, можливо, також потрібно встановити `kmod-usb-storage-uas`.
Перевірте назву USB-диска:
ls -l /sys/block
Розмітьте диск та створіть файлову систему:
DISK="/dev/sda" parted -s ${DISK} -- mklabel gpt mkpart extroot 2048s -2048s DEVICE="${DISK}1" mkfs.ext4 -L extroot ${DEVICE}
Увага: ці команди зітруть усі дані на диску.
Налаштуйте монтування extroot:
eval $(block info ${DEVICE} | grep -o -e 'UUID="\S*"') eval $(block info | grep -o -e 'MOUNT="\S*/overlay"') uci -q delete fstab.extroot uci set fstab.extroot="mount" uci set fstab.extroot.uuid="${UUID}" uci set fstab.extroot.target="${MOUNT}" uci commit fstab
Додайте запис для монтування оригінальної внутрішньої overlay:
ORIG="$(block info | sed -n -e '/MOUNT="\S*\/overlay"/s/:\s.*$//p')" uci -q delete fstab.rwm uci set fstab.rwm="mount" uci set fstab.rwm.device="${ORIG}" uci set fstab.rwm.target="/rwm" uci commit fstab
Це дозволить вам мати доступ до внутрішньої overlay (rootfs_data / ubifs) за шляхом `/rwm`.
Скопіюйте поточну overlay на extroot:
mount ${DEVICE} /mnt tar -C ${MOUNT} -cvf - . | tar -C /mnt -xf -
Перезавантажте пристрій:
reboot
overlay.
Розділ USB повинен бути змонтований у /overlay. Вільне місце на / повинно відповідати /overlay.
# grep -e /overlay /etc/mtab /dev/sda1 /overlay ext4 rw,relatime,data=ordered overlayfs:/overlay / overlay rw,noatime,lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work # df /overlay / Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 7759872 477328 7221104 6% /overlay overlayfs:/overlay 7759872 477328 7221104 6% /
preinit у журналі завантаження:block info; uci show fstab; logread | sed -n -e "/- preinit -/,/- init -/p"
.extroot-uuid з диску:mount /dev/sda1 /mnt rm -f /mnt/.extroot-uuid /mnt/etc/.extroot-uuid umount /mnt
uci set fstab.@global[0].delay_root="15" uci commit fstab
force_space у ``/etc/opkg.conf``, щоб дозволити встановлення пакетів, які більші за вільне місце у ``/rom``:echo option force_space >> /etc/opkg.conf
export PREINIT=1 mount_root
mmc_core mmc_block sdhci mtk_sd
Зберігайте списки `opkg` у директорії /usr/lib/opkg/lists на extroot-носії, замість оперативної памʼяті.
Це дозволить зберегти списки після перезавантаження і зменшить використання RAM.
/var/opkg-lists на /usr/lib/opkg/lists.sed -i -e "/^lists_dir\s/s:/var/opkg-lists$:/usr/lib/opkg/lists:" /etc/opkg.conf opkg update
Якщо ваш пристрій має мало оперативної памʼяті (наприклад 32MB) і не вдається зчитати списки, увімкніть підкачку:
# Створення swap-файлу DIR="$(uci -q get fstab.extroot.target)" dd if=/dev/zero of=${DIR}/swap bs=1M count=100 mkswap ${DIR}/swap # Увімкнення swap-файлу uci -q delete fstab.swap uci set fstab.swap="swap" uci set fstab.swap.device="${DIR}/swap" uci commit fstab service fstab boot # Перевірка статусу cat /proc/swaps
Рекомендується включити утиліту usb-modeswitch у прошивку.
Однак існує важливе застереження: якщо /overlay монтується з картки пам’яті, що вставлена в кардрідер USB-донгла — то конфігурація pivot overlay, яка інакше працює, зламається на пізніших етапах завантаження системи.
Це відбувається тому, що usb-modeswitch (вимикаючи CDROM і вмикаючи модем) тимчасово впливає на кардрідер, порушуючи файлову систему.
Щоб уникнути цієї проблеми, використовуйте донгл, який можна попередньо сконфігурувати так, щоб модем або мережевий адаптер (та кардрідер) активувалися автоматично при подачі живлення — без використання usb-modeswitch на маршрутизаторі.
1. Вставте донгл у настільний ПК. 2. Відкрийте термінал і надішліть AT-команди.
Перевірте початкову конфігурацію донгла:
at^setport? ^SETPORT:A1,A2;1,3,2,A1,A2 OK
Пояснення кодів доступних функцій:
at^setport=? ^SETPORT:A1: CDROM ^SETPORT:A2: SD ^SETPORT:A: BLUETOOTH ^SETPORT:B: FINGER PRINT ^SETPORT:D: MMS ^SETPORT:E: PC VOICE ^SETPORT:1: MODEM ^SETPORT:2: PCUI ^SETPORT:3: DIAG ^SETPORT:4: PCSC ^SETPORT:5: GPS ^SETPORT:6: GPS CONTROL ^SETPORT:16: NCM OK
У прикладі вище:
;) містить CDROM (A1) і кардрідер (A2).;) — модем (1), діагностику (3), інтерфейс керування (2) та знову CDROM (A1) і кардрідер (A2).Саме між цими двома конфігураціями usb-modeswitch перемикає пристрій.
Вимкнути CDROM (A1), увімкнути модем (1) або мережевий адаптер (16), та залишити активним кардрідер (A2).
ВАЖЛИВО: Ніколи не вимикайте PCUI (2) — ви втратите доступ до модему!
Деякі модеми підтримують спеціальну команду 'disable all' (код FF), яка очищає наявні конфігурації.
Нижче наведено приклад для повного вимкнення та задання бажаних інтерфейсів:
at^setport="ff;1,2,3,a2" OK at^reset OK at^setport? ^SETPORT:;1,2,3,A2 OK
У результаті:
;.Модем Huawei E3131s-2 з прошивкою v21.158.47.00.1094 підтримує попереднє конфігурування.
Ви можете захотіти розмістити файлову систему extroot у зашифрованому контейнері LUKS. Починаючи з OpenWrt 22.03.2, це не підтримується належним чином. OpenWrt не має офіційного способу для розшифрування LUKS-розділів до того, як відбудеться перевірка extroot під час стандартного процесу завантаження. Отже, під час цієї перевірки зашифрований extroot буде невидимий, і процес завантаження продовжиться, як ніби extroot не налаштований.
Нижче описано два методи, які дозволяють запустити систему на зашифрованому extroot. Перший метод є кращим, оскільки має менше побічних ефектів і є більш елегантним рішенням.
Перш ніж продовжити, необхідно створити LUKS-контейнер, в якому буде розміщено файлову систему extroot.
Скористайтеся документацією шифрування диска, щоб налаштувати LUKS-контейнер на вашому пристрої.
Вам потрібно мати достатньо вільного місця у розділі rootfs_data для встановлення пакету cryptsetup та його залежностей.
Коли LUKS-контейнер буде готовий, дотримуйтесь інструкцій зі створення файлової системи extroot на розблокованому пристрої, включаючи копіювання файлів з /overlay до новоствореного extroot.
У фазі PREINIT процесу завантаження виконується команда mount_root, яка спочатку перевіряє наявність конфігурації extroot на ROM-пристрої, а потім на пристрої ''rootfs_data'' (див. Схема флеш-пам'яті OpenWrt для деталей).
У стандартній прошивці OpenWrt конфігурація extroot у ROM відсутня.
Для перевірки файлової системи rootfs_data mount_root монтує її у тимчасовий каталог (/tmp/overlay), потім перевіряє файл /tmp/overlay/etc/config/fstab — той самий, що був налаштований раніше, — на наявність extroot.
Якщо конфігурація знайдена, послідовно шукаються виконувані файли /tmp/overlay/upper/sbin/block, /tmp/overlay/sbin/block та /sbin/block. Знайдений файл виконується з аргументом extroot — це відбувається тут.
Тому для роботи extroot потрібно встановити пакет block-mount.
Оскільки mount_root під час PREINIT запускається з ROM, але намагається виконати block з overlay-файлової системи, цим можна скористатися, щоб вставити власні команди у фазу PREINIT до перевірки extroot.
Це реалізується створенням скрипта, який замінює оригінальний бінарник block. Цей скрипт:
block.
Скрипт використовує decrypt.sh з посібника зі шифрування дисків.
Спершу виконайте install-decrypt.sh.
Щоб встановити скрипт:
/sbin/block у /sbin/block.bin;block-скрипт у /sbin/block і зробіть його виконуваним.
Скрипт перевіряє наявність файлу /.use_crypt_extroot у змонтованому overlayfs (або /upper/.use_crypt_extroot у /overlay) — якщо файл відсутній, extroot не буде налаштований.
Це дозволяє легко відключити зашифрований extroot у разі потреби, наприклад, у failsafe-режимі.
Коли:
block скрипт встановлено;decrypt.sh присутній;/etc/crypttab;/.use_crypt_extroot існує —можна перезавантажити пристрій для входу в зашифрований extroot.
#!/bin/sh # Залежності: # * пакети: # * block-mount # * cryptsetup # * перемістіть /sbin/block → /sbin/block.bin # * встановіть decrypt.sh у /sbin/decrypt.sh з правами на виконання # Цей скрипт повинен бути у /upper/sbin/block (UBIFS overlay) # або у /sbin/block, якщо overlay вже активний. export DEBUG= SDIR=${0%/*} BLOCK="${SDIR}/block.bin" LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-.} LD_LIBRARY_PATH="${SDIR}/../usr/lib:${LD_LIBRARY_PATH}" PATH=$PATH:${SDIR}:${SDIR}/../usr/sbin:${SDIR}/../usr/bin block() { ( exec -a ${0} ${BLOCK} "$@" ) } if [ "$PREINIT" != "1" ]; then exec block "$@" fi get_jiffies() { head -n3 /proc/timer_list | tail -n1 | cut -d' ' -f 3 } if [ -z "$BLOCK_LOG" ] && [ -n "$DEBUG" ]; then TIME=$(get_jiffies) export BLOCK_LOG="/tmp/block.$(printf '%016d' ${TIME:-9999999999}).log" exec 2>"$BLOCK_LOG" set -x fi if [ ! -x "$BLOCK" ]; then echo "Error: ${BLOCK} is not an executable" >&2 return 1 fi if [ "$1" = "extroot" ] && [ -e ${SDIR}/../.use_crypt_extroot ]; then for SYSDEVPATH in /sys/class/block/sd*; do [ ! -f "$SYSDEVPATH"/dev ] && continue [ -e "/dev/${SYSDEVPATH##*/}" ] && continue MAJMIN=$(cat "$SYSDEVPATH"/dev | tr ':' ' ') mknod /dev/${SYSDEVPATH##*/} b $MAJMIN done KVER=$(uname -r) insmod ${SDIR}/../lib/modules/${KVER}/af_alg.ko insmod ${SDIR}/../lib/modules/${KVER}/algif_rng.ko insmod ${SDIR}/../lib/modules/${KVER}/algif_hash.ko insmod ${SDIR}/../lib/modules/${KVER}/algif_skcipher.ko find /dev -type b | grep -E "/(sd|mmcblk).*" | while read DEVPATH; do cryptsetup --disable-locks isLuks $DEVPATH || continue export ACTION=add DEVNAME="${DEVPATH##*/}" ALTROOT="${SDIR}/.." "$SDIR"/decrypt.sh || "$SDIR"/decrypt.sh done fi block "$@"
Існує ще один спосіб обійти існуючі обмеження. Однак його слід використовувати лише тоді, коли попередній метод не працює, оскільки цей підхід менш стабільний і може мати побічні ефекти.
Суть у тому, що extroot буде налаштований, як описано у інструкціях вище, але не буде змонтований під час стандартного завантаження, оскільки зашифрована extroot-файлова система не буде доступна. Це очікувано.
Зміни у файлі /etc/rc.local дозволять розблокувати LUKS розділ наприкінці процесу завантаження, коли ми маємо більше контролю над системою. Після цього буде повторно викликано mount_root, і extroot буде виявлено та змонтовано.
Ваш файл конфігурації fstab має містити секцію монтування з таргетом /overlay.
Краще використовувати параметр uuid замість device, щоб не синхронізувати вручну /etc/rc.local з /etc/config/fstab.
Нижче наведено приклад скрипта для вставлення в /etc/rc.local.
Цей скрипт не підтримує розблокування LUKS за паролем (stdin працює неправильно у цьому контексті).
Необхідно використовувати файл-ключ, наприклад: /root/extroot.key. Оцініть загрози, щоб визначити безпечність такого підходу.
# Виконується лише якщо існує /.use_crypt_extroot у rootfs_data. mkdir -p /mnt/tmp if [ -e /.use_crypt_extroot ]; then cryptsetup open -d /root/extroot.key /dev/sda1 cextroot umount /overlay mount --bind /tmp /mnt/tmp sleep 5 PREINIT=1 mount_root umount -l /tmp mount --bind /rom/mnt/tmp /tmp block mount service rpcd reload fi
Цей метод фактично повторює частину процесу завантаження, тому він трохи повільніший. На моєму пристрої веб-інтерфейс доступний на 20–30 секунд пізніше. SSH-з'єднання не затримується.
Цей розділ стосується лише snapshot-збірок OpenWrt, не релізів. У релізах kernel-пакети й пов'язані з ними отримують лише патчі безпеки.
НЕ використовуйте команду opkg upgrade для оновлень — це призведе до неконсистентного стану системи або soft-brick'у:
/rom або /rwm може змінитися після оновлення, що призведе до помилок монтування extroot.iptables можуть зламатися.Також, якщо UUID ROM-партіції зміниться, можливо доведеться знову виконати кроки 3 та 4 з інструкцій.
Рекомендовано: після оновлення системи перевстановлювати всі пакети, особливо kernel-модулі.
Цей метод корисний для пристроїв з 4 МіБ флеш-пам'яті або менше. У типовому образі OpenWrt немає інструментів для extroot, оскільки система збірки створює лише мінімальні образи.
Єдиний варіант — зібрати прошивку самостійно за допомогою Image Builder.
Image Builder працює лише в 64-бітних Linux-системах. Якщо у вас немає такої — скористайтесь VirtualBox і встановіть Ubuntu 64-bit.
На сторінці завантаження прошивки для вашого пристрою знайдіть файл, що починається з “OpenWrt-imagebuilder”. Завантажте та розпакуйте його у папку в Linux-системі.
Відкрийте термінал у цій папці й виконайте:
make info
Це виведе список доступних профілів для збірки.
Приклад:
tl-wr1043nd-v1:
TP-LINK TL-WR1043N/ND v1
Packages: kmod-usb-core kmod-usb2 kmod-ledtrig-usbdev
Перший рядок — це назва профілю. Другий — опис пристрою. Третій — список пакетів за замовчуванням.
У моєму випадку назва профілю — tl-wr1043nd-v1. Для створення прошивки введіть:
make image PROFILE=tl-wr1043nd-v1 PACKAGES="block-mount kmod-fs-ext4 kmod-usb-storage kmod-usb-ohci kmod-usb-uhci"
Це створить прошивку з підтримкою ext4.
⚠️ Пакет e2fsprogs занадто великий для 4 МіБ flash, тому форматування USB-диска потрібно виконати заздалегідь на іншій системі.
Після збірки прошивки:
factory або sysupgrade).Щоб відформатувати USB у ext4, скористайтесь LiveCD або GParted Live.
Ви можете скористатися frontend-інструментом openwrt-auto-extroot для ImageBuilder, щоб зібрати кастомну прошивку, яка автоматично відформатує та налаштує extroot на будь-якому підключеному, але ще не налаштованому пристрої зберігання.
Налаштуйте Hotplug extras та Opkg extras.
Пакети, необхідні для роботи Extroot, мають бути збережені у профілі Opkg init і автоматично відновлені після оновлення за допомогою скрипта для повторного налаштування Extroot.
cat << "EOF" > /etc/uci-defaults/90-extroot-restore if uci -q get fstab.extroot > /dev/null \ && [ ! -e /etc/extroot-restore ] \ && [ -e /etc/opkg-restore-init ] \ && lock -n /var/lock/extroot-restore then UUID="$(uci -q get fstab.extroot.uuid)" DIR="$(uci -q get fstab.extroot.target)" DEV="$(block info | sed -n -e "/${UUID}/s/:.*$//p")" if touch /etc/extroot-restore \ && grep -q -e "\s${DIR}\s" /etc/mtab \ && mount "${DEV}" /mnt then BAK="$(mktemp -d -p /mnt -t bak.XXXXXX)" mv -f /mnt/etc /mnt/upper "${BAK}" cp -f -a "${DIR}"/. /mnt umount "${DEV}" fi lock -u /var/lock/extroot-restore reboot fi exit 1 EOF cat << "EOF" >> /etc/sysupgrade.conf /etc/uci-defaults EOF