Делаем Hyperboria hotspot. Пособие по ковырянию роутера

от автора

В этой статье я попытаюсь рассказать, как прошить на роутер OpenWrt и установить туда cjdns. По правде говоря, изучение тонкостей этого дела отняло у меня много времени и нервов. В основном потому, что многое в OpenWrt недодокументировано, и приходилось многое искать по форумам и додумывать. Думаю, это как раз тот случай, когда лучшей документацией являются исходники. Так что эту статью я попытаюсь написать такой, какую я хотел бы прочитать в самом начале этого пути.

Итак, первое, что следует сделать, это пойти на сайт OpenWrt и посмотреть список поддерживаемых устройств: wiki.openwrt.org/toh/start
Если не нашли вашу железку, не растраивайтесь. <sarcasm> Мы ведь всегда можем портировать OpenWrt на новое усекщйство, следуя этой инструкции: kamikaze.openwrt.org/docs/openwrt.html#x1-540002.3 </sarcasm> Хотя, сначала нужно как-то вытянуть исходники ядра у прооизводителя.

Теперь немного теории. В OpenWrt для хранения rootfs используется две файловые системы: SquashFS и JJFS2. Так же вожможно подключение других, но об этом позже.
SquashFS — сжатая статическая файловая система. Она — то, что собственно и прошивается. За счет своей статичности, сжатие в ней лучше.
JJFS2 — сжатая динамическая файловая система, в которую записываются изменения файлов. Она монтируется как-бы поверх SquashFS при помощи фичи ядра Linux Overlayfs. Появилась она начиная с версии ядра 3.11.

Среду для сборки OpenWRT можно скачать в 4-х вариантах.

  • OpenWrt Buildroot — эдакий монстр Франкенштейна, написаный на make, который сам качает исходники всего, что нужно, сам же патчит все это, сам собирает кросскомпилятор, собирает пакеты и образы для прошивки. Форк Buildroot Насчет формата этих makefil-ов. Тут достаточно процитировать документацию:
    «Глядя на Makefile из какого либо пакета, вы вряд ли узнаете в нем обычный Makefile. Это может быть охарактеризовано как вопиющее пренебрежение и жестокое обращение с традиционным форматом make, однако, преобразование Makefile пакета в объектно-ориентированный шаблон позволило упростить весь процесс портирования приложений.»
  • OpenWrt Image Builder — то же самое, но грузиту уже откомпиленые пакеты и собирает из них образ.
  • OpenWrt SDK — то же самое, но набор програм для кросскомпиляции уже собран и собирать образы оно уже не может. Предназначено для сборки отдельных пакетов.
  • OpenWrt based Toolchain — уже откомпиленый набор програм для кросскомпиляции, выдраный из Openwrt Buildroot.

Последние три могут быть собраны из OpenWrt Buildroot.

Как уже было сказано выше, в SquashFS сжатие лучше, так что у нас есть больше шансов уместить все, что нужно, собрав прошивку самостоятельно, чем скачав готовый образ и доставив нужный пакет. Для тех, кто собирается ставить готовую минимальную прошивку вот сборки от разработчиков. Они рассортированы по архитектурам (колонка target в списке поддерживаемого оборудования) и по типу памяти (nand и все остальные), названия файлов включают в себя названиероутера. Прошивки, содержащие в названии «sysupgrade» предназначены для перепрошивуи средствами уже установленой OpenWrt. Содержащие «factory» можно скормить вебформе заводской прошивки. Не перепутайте.

Приступим к сборке.

Внимание! Сборка не должна проводится от суперпользователя или в fakeroot.

Для начала загрузим buildroot. Здесь есть список веток и команд для их загрузки. Мы же будем собирать Attitude Adjustment stable:

git clone git://git.openwrt.org/12.09/openwrt.git 

Репозиториев с beta, beta2, rc1 и rc2, видимо, нету, а жаль, потому что пакет, собраный для stable на beta не стал, только ругнулся, что git commit id ядра не тот, который нужен (хотя верси совпадали).

Далее, следуя инструкции добавляем в список мест, откуда будут грузится исходники «репозиторий» с openwrt:

cd ./openwrt cp feeds.conf.default feeds.conf 

Добавляем в файл feeds.conf строку

src-git cjdns git://github.com/cjdelisle/cjdns-openwrt.git 

Далее, грузим исходники всех пакетов:

./scripts/feeds update -a ./scripts/feeds install -a 

Теперь запускаем

make menuconfig 

и настраиваем все, что нужно.

Выбираем «Target System» (ту, которая указана в списке поддерживаемых устройств возле названия вашего роутера), Subtarget (если в роутере постоянная память не NAND, смело выбираем Generic), «Target Profile» (ищем название роутера, под который будем собирать). В «Target Images» обычно ничего менять не надо. Выбираем пробелом.

На данном этапе все нужные драйверы уже отмечены (благодаря «Target Profile») Далее ходим по остальным веткам и выбираем нужные нам пекеты (Именно нам. По идее, и так работать будет). Поиска здесь не предусмотрено, так что искать будем так:

find ./feeds/ -name nano 

Благо, большинство пакетов рассортировано по разделам. Хотя они могут находится и в ./package и тогда вы их таким образом не найдете. В выводе видим ./feeds/packages/utils/nano, что значит, что nano нам нужно искать в разделе «Utilities». Для полной уверенности можно почитать makefile пакта. Для nano это ./feeds/packages/utils/nano/Makefile. В нем мы видим такой фрагмент:

define Package/nano   SUBMENU:=Editors   SECTION:=utils   CATEGORY:=Utilities   TITLE:=An enhanced clone of the Pico text editor   URL:=http://www.nano-editor.org/   MAINTAINER:=Bernhard Loos <bernhardloos@googlemail.com>   DEPENDS:=+libncurses endef 

«CATEGORY» — название раздела, «SUBMENU» — название подраздела. Кстати, такая запись может быть не одна. Дело в том, что из одного набора исходников может собиратся несколько разных пакетов.

Итак, пакеты, которые нам могут понадобится.

  • nano — чтобы не пришлось править конфиги с помощью vi или cat/echo
  • htop — просмотрщик процесов
  • iftop — програмка для отслеживания сетевой активности (кто, с кем, на какой порт, с какой скоростью)
  • tcpdump — ну куда ж без него?
  • kmod-usb-storage — модуль ядра для подключения внешних носителей памяти по usb
  • kmod-usb-storage-extras — модуль ядра для подключения некоторых экзотических внешних носителей памяти по usb (например, кардридера)
  • block-mount — набор скриптов для автоматического монтирования по /etc/fstab. Для автомонтирования файловых систем по конфигам в формате uci (об этом позже) хватит и mount из busybox, но swap автоматически без них не монтируется.
  • swap-utils — необходим для монтирования swap
  • Всевозможные драйверы файловых систем. Найти можно в «Kernel modules»->«Filesystems»
  • shadow-groopadd, shadow-groupdel, shadow-groupmod, shadow-groups, shadow-passwd, shadow-su, shadow-useradd, shadow-userdel, shadow-usermod — набор утилит для управления пользователями и группами. Обычно можно обойтись и без них.
  • ip,iw,iptables,ip6tables — для ручной настройки сети
  • bind-dig — dns-клиент

Следует отметить, что все может и не поместится. В таком случае одраз для роутера собран не будет, но пакеты соберутся. Пакет можно отметить и так, чтобы он собрался, но в образ не включался. Для этого нужно нажать клавишу m.

А теперь расскажу одном баге, который мешает сборке cjdns. В зависимостях cjdns есть пакет с чудным названием nacl. Он используется при сборке других пакетов, но при этом бинарный пакет из него не собирается. В то же время, он появляется и в зависимостях бинарного пакета cjdns. В результате, чтобы установить уже собраный пакет с cjdns, нужно перед єтим установить не существующий в собраном виде пакет nacl.

Теперь, как его обойти. Открываем ./openwrt/feeds/cjdns/cjdns/Makefile в текстовом редакторе, находим этот фрагмент:

define Package/cjdns   SECTION:=net   CATEGORY:=Network   SUBMENU:=Routing and Redirection   TITLE:=Experimental self configuring routing protocol.   DEPENDS:=+kmod-tun +kmod-ipv6 +libnl +nacl +libpthread   MAINTAINER:=cjd -- #cjdns on irc.efnet.org endef 

и убераем из «DEPENDS» "+nacl". Должно получится так:

define Package/cjdns   SECTION:=net   CATEGORY:=Network   SUBMENU:=Routing and Redirection   TITLE:=Experimental self configuring routing protocol.   DEPENDS:=+kmod-tun +kmod-ipv6 +libnl +libpthread   MAINTAINER:=cjd -- #cjdns on irc.efnet.org endef 

В menuconfig находим nacl (в разделе «Libraries») и устанавливаем в <M>.

Далее собираем nacl отдельно:

make package/nacl/compile 

Советую при сборке использовать не какой-то mate-terminal, а, к примеру tmux. Будет не очень приятно, если за время сборки, к примеру, упадут иксы.

Еще один нюанс. Чтобы после прошивки поднялась сеть, в прошивке должны быть конфиги настройки сети. Однако, для некоторых роутеров при сборке прошивки соответствующий конфиг не генерируется. В результате, роутер вроде-бы работает, но сеть не поднялась и мы получаем прекрасно работающий кирпич. Я, когда в первый раз собирал прошивку под свой tl-mr3220, столкнулся с этим и потом довольно долго искал нужный кабель и паял так называемый serial hack adapter, чтобы достучатся до железки.
Теперь о формате конфигов. В OpenWrt используется самопальный собственный формат конфигов UCI, общий для всего. Насколько я понял, они потом преобразуются в нормальные. Он, как мне кажется, достаточно хорошо документирован, так что останавливатся на нем не буду. Скажу только, что хранятся они в папке /etc/config/.
Чтобы добавить какие-то свои файлы, в том числе и конфиги, в прошивку, в папке с Buildroot нужно создать папку files и положить в нее нужные файлы. Например, тот же конфиг сети я положил в файл ./files/etc/config/network. Вот и сам конфиг для tl-mr3220 v1.2:

config interface 'loopback'         option ifname 'lo'         option proto 'static'         option ipaddr '127.0.0.1'         option netmask '255.0.0.0'  config interface 'lan'         option type 'bridge'         option proto 'static'         option netmask '255.255.255.0'         option _orig_ifname 'eth0 radio0.network1'         option _orig_bridge 'true'         option ifname 'eth0'         option ipaddr '192.168.5.1'         option gateway '192.168.5.2'         option broadcast '192.168.5.255'         option dns '192.168.5.2'  config switch         option name 'eth0'         option reset '1'         option enable_vlan '1'  config switch_vlan         option device 'eth0'         option vlan '1'         option ports '0 1 2 3 4' 

Его я извлек из прошивки, взятой с сайта OpenWrt и немножко подправил. Что значат поля _orig_ifname и _orig_bridge не спрашивайте, сам не знаю. Отмечу, что этот конфиг предусматривает, что роутер торчит в одну и ту же сеть всеми своими портами, а не, например, каким-то одним в интернет.

Теперь вернемся к cjdns. Чтобы пакет таки собрался, нужно его отметить в menuconfig: «Network»->«Routing and Redirection»->«cjdns».

Итак, настал торжественный момент:

make 

После сборки файлы должны оказатся в ./bin, рассортированые по target-ам (пока он у нас один). К примеру, у меня собраные образы лежат в ./bin/ar71xx, а пакеты в ./bin/ar71xx/packages/. Теперь открываем архив ./bin/ar71xx/openwrt-ar71xx-generic-rootfs.tar.gz (или аналогичный для вашего target) и проверяем, действительно ли там есть конфиг сети.

Теперь можно прошивать.
Как уже говорилось выше, openwrt-ar71xx-generic-tl-mr3220-v1-squashfs-factory.bin можно скормить вебморде заводской прошивки. Еще раз повторю уже стандартное предупреждение, встречаемое чуть ли не везде, где пишут о процесе прошивки: ни в коем случае не прошивайте по wi-fi!

Прошивка при помощи уже установленого OpenWrt.

Заходим по ssh, проверяем, сколько оперативной памяти свободно:

free 

Файл с новой прошивкой должен будет лежать в tmpfs.
Далее правим файл /etc/sysupgrade.conf. В нем должны лежать имена файлов и папок, которые сохранятся при перепрошивке (путем занесения в jffs2). Комментарии выделяются символом #. При сохранении конфигов таким образом возможны разные казусы, так как их формат может поменятся.
Копируем в /tmp на роутере (туда примонтирован tmpfs):

scp ./bin/ar71xx/openwrt-ar71xx-generic-tl-mr3220-v1-squashfs-sysupgrade.bin root@192.168.5.1:/tmp  

Проверяем целостность образа. На роутере считаем хеш файла образа:

cd /tmp md5sum openwrt-ar71xx-generic-tl-mr3220-v1-squashfs-sysupgrade.bin 

и сверяем с хешем файла на компьютере.

Скрещиваем пальцы и прошиваем:

sysupgrade -v /tmp/openwrt-ar71xx-generic-tl-mr3220-v1-squashfs-sysupgrade.bin 

Если все прошло хорошо, роутер должен перезапустится. Заходим по ssh и с помощью passwd устанавливаем пароль root.

Существуют так же и другие способы прошивки, которые вариируются в зависимости от модели роутера. На части роутеров возможна прошивка с помощью загрузчика, есть и более хардкорные методы, предаологающие работу с паяльником.

Пакетный менеджер.

В OpenWrt в качестве пакетного менеджера используется opkg. Опции:

  • update — Загрузить список пакетов в репозитории. Загружается он в /tmp/opkg-lists/snapshots, а в /tmp примонтирована tmpfs. Так что, после прерзагрузки для каких-либо действий с пакетами прийдется опять грузить список пакетов.
  • upgrade — Начнем с того, что эта опция вам, скорей всего, не понадобится. Пакеты в репозиториях разработчиков меняются только в trunc. Если прописать другой репозиторий от другой версии, возможны казусы. Крайне не рекомендуется обновлять таким образом модули ядра (названия их пакетов начинаются на kmod-). Действия «обновить все под ряд» opkg не умеет вообще.
  • install принимает название пакета, имя файла или url для скачивания:
    opkg install hiawatha opkg install http://downloads.openwrt.org/snapshots/trunk/ar71xx/packages/hiawatha_7.7-2_ar71xx.ipk opkg install /tmp/hiawatha_7.7-2_ar71xx.ipk
  • configure — Не совсем понятно, что делает. По видимому, еще раз выполняет конфигурационные скрипты пакета.
  • remove — Удалить пакет.
  • list — список пакетов.
  • list-installed — список установленніх пакетов.

Полный список опций здесь: wiki.openwrt.org/doc/techref/opkg
Чтобы добавить репозиторий, в файл /etc/opkg.conf нужно добавить строку вида

src/gz <название репозитория> <url репозитория>

Пример:

src/gz attitude_adjustment http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/packages

Чтобы добавить репозиторий, находящийся в папке, нужно дописать

src/gz local file:////путь/к/папке

Отмечу, что подписывание пакетов, как в apt-get, не предусмотрено, как и забирание их по https. Насчет https, конечно, можно извернутся, но все упирается в неправильно подписаный сертификат на downloads.openwrt.org. Хотя, он не самоподписный, а значит, что, извернувшись вдвойне, может что-то получится.

Монтируем дополнителную память с флешки (если нужно).

На флешке должны быть соответствующие разделы. Для монтирования файловой системы лучше всего подойдет ext4. Итак, у нас есть размеченая флешка, которую мы втыкаем в порт на роутере. Проверяем, появились ли в /dev файлы раделов флешки. Если нет, доставляем нужные модули.
Далее, пытаемся монтировать:

mount /dev/sda1 /mnt 

Если не получилось, опять же, ставим нужные пакеты. Далее

rm -rf /mnt/* tar -C /overlay -cvf - . | tar -C /mnt -xf - # копируем содержимое overlay 

Почему именно tar, а не по-нормальному? Должно быть, чтобы сохранить атрибуты файлов. Именно этот способ предлагается в wiki.openwrt.org/doc/howto/extroot#installation1.
Далее, отмонтирываем и правим /etc/config/fstab. В него дописываем или меняем соответствующую секцию на это:

config mount         option target   /overlay         option device   /dev/sda1 #       option uuid     <uuid>         option fstype   ext4         option options  rw,sync         option enabled  1         option enabled_fsck 0 

Чтобы изменения вступили в силу, делаем

uci commit fstab 

Можно так-же монтировать по uuid, чтобы не было казусов при подключении нескольких устройств по usb. Для этого нужно убрать параметр «device» и добавить «uuid» с, собственно, uuid раздела.
Подробнее о параметрах здесь: wiki.openwrt.org/doc/uci/fstab#mounting.filesystem

Монтируем swap.

Для этого нужно, чтобы в конфиге было нечто вроде этого:

config swap         option device   /dev/sda2 #       option uuid    <uuid>         option enabled  1 

Здесь все аналогично. По поводу выбора размера swap. Для linux на десктопах часто советуют делать swap немного больше, чем размер оперативной памяти, чтобы при переходе в «спящий режим» (или как там оно называется?) все, что есть в оперативной памяти, поместилось в swap. Согласитесь, для роутера «спящий режим» — это бред. Так что для них действует другое правило — выделяйте побольше. 512 MiB, думаю, хватит всегда и всем!
Просмотреть обьем оперативной памяти и swap можно с помощью команды free.
И не забываем про uci commit.

Cтавим cjdns (если он не поместился в squashfs).

Копируем пакет с помощью scp в /tmp на роутере и устанавливаем с помощью opkg. Далее создаем конфиг cjdns. На некоторых роутерах это может длится долго. Далее добавляем в конфиг ноды, раскомментирываем раздел ETHInterface и прописываем интерфейс br-lan вместо eth0.

Настраиваем wi-fi в режиме ad-hoc.

Открываем /etc/config/wireless и добамляем секцию вроде этой:

config wifi-iface         option device radio0         option mode adhoc         option ssid hype         option bssid 66:77:55:88:44:aa         option disabled 0 

Опция «device» должна содержать название «устройства», обозначеного в секции «wifi-device». У меня она выглядит так:

config wifi-device 'radio0'         option type 'mac80211'         option macaddr 'ab:cd:ef:ab:cd:ef'         option hwmode '11ng'         option htmode 'HT40+'         list ht_capab 'SHORT-GI-40'         list ht_capab 'TX-STBC'         list ht_capab 'RX-STBC1'         list ht_capab 'DSSS_CCK-40'         option channel 'auto'         option txpower '18'         option country 'RU' 

Тут есть один нюанс. Не все роутеры умеют поднимать несколько беспроводных сетей с одного физического устройства. Так что если после uci commit wireless; /etc/init.d/wireless restart одна из сетей не поднялась, то прийдется обойтись одной. Чтобы отключить одну из сетей, достаточно установить опцию disabled в 1.
Теперь проверяем, не попала ли новосозданная сеть в bridge с нашей локальной сетью. Сначала определяем, какому интерфейсу какая сеть соответствует:

iw dev </code> А потом проверяем мосты: <source> brctl show 

Если наш ad-hoc таки слинковался с локальной сетью, идем править /etc/config/network. Ищем секцию interface с опцией «type» установленой в «bridge» вроде этой:

config interface 'lan'         option type 'bridge'         option proto 'static'         option netmask '255.255.255.0'         option _orig_ifname 'eth0, radio0.network1'         option _orig_bridge 'true'         option ifname 'eth0 wlan0'         option ipaddr '192.168.5.1'         option gateway '192.168.5.2'         option broadcast '192.168.5.255'         option dns '192.168.5.2' 

Для этого случая нужно убрать из "_orig_ifname" «radio0.network1», а из «ifname» — «wlan0»

Теперь прописываем нужный интерфейс в конфиге cjdns. Секция ETHInterface, кстати, может выглядеть и так:

        "ETHInterface":         [             {             "bind": "wlan0",             "beacon": 2,             },             {             "bind":"br-lan",             "beacon": 2             }         ] 

На десктопе такое работает, но на роутере, почему-то, с таким конфигом cjdroute падает. Так что, если у вас тоже это не работает, то прописываем что-то одно.

Создаем скрипт автозапуска.

Скрипты запуска должны лежать в папке /etc/init.d/. Создаем файл /etc/init.d/cjdns:

#!/bin/sh /etc/rc.common  START=93 STOP=51  start() {         cjdroute < /etc/cjdroute.conf         } stop()  {         killall cjdroute         } 

$START и $STOP определяют последовательность запуска скриптов при старте и выключении роутера. «start()» — набор команд, выполняемый для запуска чего-либо. «stop()» — для остановки. Честно говоря, я слабо понимаю, чем может может помочь функционал запуска скриптов при выключении, если роутеры принято выключать, просто выдергивая из розетки, а соответствующей кнопки обычно не предусмотрено. Вообще-то, в последних версиях cjdns предусмотрена опция конфига «pidFile», но это изменение пока не в ветке «master», из которой он собирается под OpenWrt.
Теперь осталось сделать
chmod u+rwx /etc/init.d/cjdns /etc/init.d/cjdns enable
Подробнее о стартовых скриптах в OpenWrt можно почитать здесь: wiki.openwrt.org/doc/techref/initscripts

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

ссылка на оригинал статьи http://habrahabr.ru/post/202536/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *