Как стать автором
Обновить

Установка программного обеспечения из исходников под МГТС роутер ZTE F-660 в chroot окружении

Время на прочтение 11 мин
Количество просмотров 60K

Привет всем! Во многом благодаря компании МГТС и ее оптической сети GPON, я познакомился с оптическим модемом-роутером ZTE f-660. Как только дома появился этот девайс, у меня сразу появилась мысль поставить туда какую-нибудь прошивку с софтом вроде dd-wrt или open-wrt.

При внешнем осмотре у роутера был обнаружен usb порт.
В голову пришли следующие способы применения роутера в бытовых целях:
  1. SipProxy server;
  2. Torrent client;
  3. Ftp-сервер;
  4. Dlna-сервер;
  5. Примитивный веб-хостинг.

Поиск в интернете ничего не дал. На различного рода форумах, идет в основном обсуждение как на стену вешать или как порты открыть, более того я даже не нашел “стоковой" прошивки для него. Но на роутер есть телнет доступ (root root). Начав изучать внутренности прошивки я понял, что не все так просто. Текущая прошивка намертво привязана к телефонии и оптическому модему, и сменив ее, я по всей видимости, лишусь и телефона и интернета в лучшем случае, а в худшем просто «окирпичу» роутер без возможности восстановления. К тому же это может привести к штрафным санкциям от МГТС за замену роутера в размере ~1500р.
Единственный вариант который мне виделся на тот момет, это запуск нужных мне программ в chroot окружении с флешки отформатированной в ntfs. Естественно мне хотелось использовать самые последние версии программ. Поэтому я решил собрать все из исходников.
Изучив аппаратную базу, я определил, что там стоит обычный mips-процессор работающий под линуксом 2.6.30. Соответственно нам необходимо собрать gcc-тулчан под данную архитектуру. Для сборки тулчана я выбрал обычную убунту.
Перед установкой нам необходимо поставить средства разработки
sudo apt-get install gcc g++ make grep gawk automake

Скрипт я приведу ниже, а тут я опишу общий план и то, на что необходимо обратить особое внимание:
Не нужны никакие патчи;
Синтаксис вызова имеет следующий вид ./make-mips-toolchan <полный путь создаваемого toolchan> ;
Для того что бы скачать все исходники используйте параметр get;
Не используйте опцию -j > 1, не соберется получите кучу недетерминированных ошибок (Под убунту и gcc 4.8.1);
CLFS=“$1” дирректория в которую мы поместим тулчан. SYSROOT=“$CLFS/root”, дирректория в которую будут устанавливатся результат работы тулчана;
Если с первого раза не соберется, комментируете в скрипте уже пройденные этапы и продолжаете дальше;
В скрипт вторым параметром передается путь по которому необходимо разместить тулчан;
Этапы установки такие:
  • Ставим исходники ядра 2.6.30;
  • Ставим утилиты для работы с бинарными файлами (линковщик) binutils;
  • Ставим mips крос-компилятор gcc (без поддержки потоков);
  • С его помощью собираем стандартную библиотеку С (eglibc);
  • С помощью стандартной библиотеки собранной в предыдущем пункте соберем полноценный с++ тулчан;

#!/bin/sh
TARGET="mips-unknown-linux-gnu"
CLFS="$1"
SYSROOT="$CLFS/root"
HOST="x86_64-pc-linux-gnu"
LINUX_VERSION=2.6.30
BINUTILS_VERSION=2.24
GCC_VERSION=4.8.2
EGLIB_VERSION=2.18-r24148
unset CFLAGS
unset CXXFLAGS
check_success() {
   if [ $? -ne 0 ]
   then
      echo Failed
      exit 1
   fi
   echo Done
}
if [ "$2" = "get" ]
then
echo -n "Download sources..."
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-$LINUX_VERSION.tar.bz2
wget http://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.gz
wget http://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.bz2
wget http://cross-lfs.org/files/eglibc-$EGLIB_VERSION.tar.xz
echo -n "Extract archives..."
tar -xjf linux-$LINUX_VERSION.tar.bz2
tar -xf binutils-$BINUTILS_VERSION.tar.gz
tar -xjf gcc-$GCC_VERSION.tar.bz2
tar -xf eglibc-$EGLIB_VERSION.tar.xz
cd ./gcc-$GCC_VERSION/
./contrib/download_prerequisites
cd ..
check_success
fi
if [ "$2" = "clear" ]
then
rm -rfv $CLFS
mkdir -p $SYSROOT
check_success
exit 1
fi
mkdir -p $SYSROOT



InstallKernelHeader()
{
echo -n "Install kernel headers..."
cd linux-$LINUX_VERSION/
make mrproper
make ARCH=mips headers_check
make ARCH=mips INSTALL_HDR_PATH=$SYSROOT/usr headers_install
cd ..
check_success
}

InstallBinutils()
{
echo -n "Install binutils..."
mkdir mips-binutils
cd mips-binutils
rm -rf ./*
../binutils-$BINUTILS_VERSION/configure --prefix=$CLFS --target=$TARGET --with-sysroot=$SYSROOT  --disable-nls --disable-static --disable-multilib --enable-plugins
make
check_success
make install
check_success
cd ..

}

InstallStaticGCC()
{
echo -n "Install static gcc..."
mkdir mips-static-gcc
cd mips-static-gcc
rm -rf ./*
../gcc-$GCC_VERSION/configure --target=$TARGET --prefix=$CLFS --with-sysroot=$SYSROOT --disable-nls  --disable-shared --without-headers --with-newlib --disable-decimal-float --disable-libgomp --disable-libmudflap --disable-libssp --disable-threads --disable-multilib --disable-libatomic --disable-libitm --disable-libsanitizer --disable-libquadmath --disable-target-libiberty --enable-languages=c --enable-checking=release
make all-gcc
check_success
make all-target-libgcc
check_success
make install-gcc install-target-libgcc
check_success
cd ..
}


InstallEGLIB()
{
echo -n "Install eglibs header files..."
mkdir mips-eglibs
cd mips-eglibs
rm -rf ./*
BUILD_CC="gcc" \
CC="$CLFS/bin/$TARGET-gcc" \
AR="$CLFS/bin/$TARGET-ar" \
RANLIB="$CLFS/bin/$TARGET-ranlib" \
../eglibc/libc/configure \
--prefix=/usr \
--with-headers=$SYSROOT/usr/include \
--build=$HOST \
--host=$TARGET \
--disable-profile --without-gd --without-cvs --enable-add-ons

check_success
make
check_success
make install install_root=$SYSROOT
check_success
cd ..

}
InstallFinallGCC()
{
echo -n "Install final gcc..."
mkdir mips-final-gcc
cd mips-final-gcc
rm -rf ./*
../gcc-4.8.2/configure --prefix=$CLFS \
--build=$HOST --target=$TARGET --host=$HOST \
--with-sysroot=$SYSROOT --enable-shared --disable-static --enable-languages=c,c++ \
--with-libs=$SYSROOT/lib \
--enable-__cxa_atexit --enable-c99 --enable-long-long --enable-threads=posix \
--disable-multilib \
--enable-checking=release \
--disable-nls \
--enable-libstdcxx-time
make  AS_FOR_TARGET="$CLFS/bin/$TARGET-as" LD_FOR_TARGET="$CLFS/bin/$TARGET-ld" -j 4
check_success
make install
check_success
cp $CLFS/mips-unknown-linux-gnu/lib/libgcc_s.so $SYSROOT/usr/lib
cd $SYSROOT/usr/lib
ln -s ./libgcc_s.so ./libgcc_s.so.1
cd -
cd ..
}

InstallKernelHeader
InstallBinutils
InstallStaticGCC
InstallEGLIB
InstallFinallGCC

С этого момента у вас есть полноценный gcc-тулчан который способен собирать программы под наш роутер. Для этого нам этапе конфигурирования программ нам необходимо указывать компилятор и линковщик из только что скомпилированного тулчана:
unset CFLAGS
unset CXXFLAGS
export LD="mips-unknown-linux-gnu-ld"
export CC="mips-unknown-linux-gnu-gcc"
export AR="mips-unknown-linux-gnu-gcc-ar"
export RANLIB="mips-unknown-linux-gnu-ranlib"
export STRIP=“mips-unknown-linux-gnu-strip”

Все инструменты готовы и мы можем приступать к сборке программ.
В качестве примера соберем торрент клиент Transsmission и сип-прокси Sipproxd. Общий план такой:
  1. Сборка статически слинкованного bash интерпетатора;
  2. Сборка сетевых утилит GnuInetCoreUtills;
  3. Сборка основных утилит GnuCoreUtills;
  4. Сборка библиотеки текстового интерфейса NCurses (Нужна для Nano);
  5. Сборка консольного блокнота необходимого для редактирования файлов конфигурации Nano;
  6. Сборка библиотеки сжатия Zlib;
  7. Сборка криптографической библиотеки openssl;
  8. Сборка сетевой библиотеки Curl (Нужна для transsmission);
  9. Сборка библиотеки событий LibEvent (Нужна для transsmission);
  10. Сборка торрент клиента Transsmission;
  11. Сборка библиотеки GnuSip;
  12. Сборка SipProxy.

В процессе сборки пришлось применить ряд патчей все они очень простые добавляют или удаляют не больше одной строчки.

Сам скрипт:
#!/bin/bash
check_success()
{
   if [ $? -ne 0 ]
   then
      echo Failed
      exit 1
   fi
   echo Done
}
if [ "$2" = "get" ]
then
echo -n "Download sources..."
wget "http://ftp.gnu.org/gnu/coreutils/coreutils-8.22.tar.xz"
wget "http://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz"
wget "http://www.openssl.org/source/openssl-1.0.1e.tar.gz"
wget "http://zlib.net/zlib-1.2.8.tar.gz"
wget "http://mirror.yandex.ru/pub/OpenBSD/OpenSSH/portable/openssh-6.4p1.tar.gz"
wget "http://curl.haxx.se/download/curl-7.34.0.tar.gz"
wget "http://download.transmissionbt.com/files/transmission-2.82.tar.xz"
wget "http://ftp.gnu.org/gnu/inetutils/inetutils-1.9.2.tar.gz"
wget "http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz"
wget "http://www.nano-editor.org/dist/v2.2/nano-2.2.6.tar.gz"
wget "https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz"
wget "http://siproxd.tuxworld.ch/siproxd-01Feb2014.tar.gz"
wget "http://ftp.gnu.org/gnu/osip/libosip2-4.1.0.tar.gz"


echo -n "Extract archives..."
tar -xf zlib-1.2.8.tar.gz && rm zlib-1.2.8.tar.gz*
tar -xf openssl-1.0.1e.tar.gz && rm openssl-1.0.1e.tar.gz*
tar -Jxf coreutils-8.22.tar.xz && rm coreutils-8.22.tar.xz*
tar -xf bash-4.2.tar.gz && rm bash-4.2.tar.gz*
tar -xf openssh-6.4p1.tar.gz && rm openssh-6.4p1.tar.gz*
tar -xf curl-7.34.0.tar.gz && rm curl-7.34.0.tar.gz*
tar -xf transmission-2.82.tar.xz && rm transmission-2.82.tar.xz*
tar -xf inetutils-1.9.2.tar.gz && rm inetutils-1.9.2.tar.gz*
tar -xf ncurses-5.9.tar.gz && rm ncurses-5.9.tar.gz*
tar -xf nano-2.2.6.tar.gz && rm nano-2.2.6.tar.gz*
tar -xf libevent-2.0.21-stable.tar.gz && rm libevent-2.0.21-stable.tar.gz*
tar -xf siproxd-01Feb2014.tar.gz && rm siproxd-21Jan2014.tar.gz*
tar -xf libosip2-4.1.0.tar.gz && rm libosip2-4.1.0.tar.gz*
check_success
fi


InstallCoreUtils()
{
cd coreutils-8.22
make clean
./configure --prefix=/ --host=$HOST
patch Makefile < ../dummymake.patch
patch ./man/dummy-man < ../dummyman.patch
make -j 4
make install DESTDIR=$SYSROOT
cd .. 
}


InstallBash()
{
cd bash-4.2
make clean
./configure --without-bash-malloc --prefix=/ --host=$HOST #--enable-static-link
patch execute_cmd.c <  ../bashjobcontrol.patch
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallInetUtils()
{
cd inetutils-1.9.2
make clean
./configure --prefix=/usr --host=$HOST
patch ./ifconfig/system/linux.c < ../inetutilpathprocspath.patch
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallZlib()
{
cd zlib-1.2.8
make clean
./configure --prefix=/usr
make  -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallOpenSSl()
{
cd openssl-1.0.1e
make clean
./Configure linux-elf --prefix=/usr  no-asm -fPIC
make
check_success
make install INSTALL_PREFIX=$SYSROOT
check_success
cd ..
}

InstallOpenSSH()
{
cd openssh-6.4p1
make clean
./configure --prefix=/usr --host=$HOST --sysconfdir=/etc/ssh
make LDFLAGS="-dynamic-linker /lib/ld.so.1 $SYSROOT/usr/lib/crt1.o $SYSROOT/usr/lib/crti.o $SYSROOT/usr/lib/crtn.o -L. -Lopenbsd-compat/ -L$SYSROOT/lib -lc -lgcc_s"  CFLAGS="-DHAVE_SETLOGIN -UHAVE_PROC_PID -fPIC -g -O2 -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -fno-builtin-memset -fstack-protector-all" -j 3
check_success  -j 4
make DESTDIR=$SYSROOT STRIP_OPT="--strip-program=mips-unknown-linux-gnu-strip" install-nokeys
check_success
cd ..
}


InstallCurl()
{
cd curl-7.34.0
make clean
./configure --prefix=/usr --host=$HOST
make
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}
InstallLibEvent()
{
cd libevent-2.0.21-stable
make clean
./configure --prefix=/usr --host=$HOST
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallTransmission()
{
cd transmission-2.82
make clean
with_ssl=$SYSROOT/usr CFLAGS="-w" \
LIBEVENT_CFLAGS="-I$SYSROOT/usr/include/curl" LIBEVENT_LIBS="-L$SYSROOT/usr/lib/ -levent" \
LIBCURL_CFLAGS="-I$SYSROOT/usr/include/event2" LIBCURL_LIBS="-L$SYSROOT/usr/lib/ -lcurl" \
LDFLAGS="-L$SYSROOT/usr/lib/ -lssl -ldl" \
./configure --prefix=/usr --host=$HOST --disable-gtk --disable-cli --disable-libnotify --disable-nls --disable-mac --disable-wx --disable-beos
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallNcurses()
{
cd ncurses-5.9
make clean
./configure --prefix=/usr --host=$HOST
make
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallNano()
{
cd nano-2.2.6
mkdir buidnano
cd buidnano
rm -rfv ./*
make clean
../configure --prefix=/usr --host=$HOST CFLAGS="-I$SYSROOT/usr/include/ncurses"
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ../..
}

InstallLibSip()
{
cd libosip2-4.1.0
make clean
./configure --prefix=/usr --host=$HOST
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}

InstallSipProxd()
{
cd siproxd-0.8.2dev
make clean
 ./configure --prefix=/usr --host=$HOST --with-libosip-prefix=$SYSROOT/usr
replacestr=$SYSROOT/usr/lib
sed -i -e 's|/usr/lib|'$replacestr'|g' $SYSROOT/usr/lib/libosipparser2.la
sed -i -e 's|/usr/lib|'$replacestr'|g' $SYSROOT/usr/lib/libosip2.la
patch ./src/dejitter.c < ../siproxytime.patch
make -j 4
check_success
make install DESTDIR=$SYSROOT
check_success
cd ..
}






CLFS="$1"
SYSROOT="$CLFS/root"
HOST="mips-unknown-linux-gnu"
export PATH=$CLFS/bin/:$PATH
unset CFLAGS
unset CXXFLAGS

export LD="mips-unknown-linux-gnu-ld"
export CC="mips-unknown-linux-gnu-gcc"
export AR="mips-unknown-linux-gnu-gcc-ar"
export RANLIB="mips-unknown-linux-gnu-ranlib"
export STRIP="mips-unknown-linux-gnu-strip"

InstallBash
InstallInetUtils
InstallCoreUtils

InstallNcurses
InstallNano

InstallZlib
InstallOpenSSl
#InstallOpenSSH

InstallCurl
InstallLibEvent
InstallTransmission

InstallLibSip
InstallSipProxd


Далее необходимо перенести нашу папку root которая находится в директории нашего тулчана на заранее отформатированную в nfts флешку. Также на флешку необходимо поместить статически слинкованный busybox готовый можно взять отсюда: www.busybox.net/downloads/binaries/latest/busybox-mips.
Далее нам нужно «запрыгнуть» в нашу песочницу, выполнив небольшой скрипт:
#!/bin/ash

export TERMINFO=/usr/share/terminfo
export HOME=/root
cp -rf /etc/* /mnt/usb1_1/root/etc

mkdir -p /mnt/usb1_1/root/root
mkdir -p /mnt/usb1_1/root/dev
mkdir -p /mnt/usb1_1/root/proc
mkdir -p /mnt/usb1_1/root/sys
mkdir -p /mnt/usb1_1/root/dev/pts

mount -o bind /dev /mnt/usb1_1/root/dev
mount -o bind /proc /mnt/usb1_1/root/proc
mount -o bind /sys /mnt/usb1_1/root/sys
mount -o bind /dev/pts /mnt/usb1_1/root/dev/pts

./busybox-mips chroot /mnt/usb1_1/root/ /bin/bash


Мы увидим командную строку интерпретатора bash. Выполним настройку динамических библиотек командой ldconfig -v
С этого момента мы можем делать все что угодно так как мы отделены от основной системы.
Запустим торрент-клиент transmission-daemon. Перейдите по адресу 192.168.1.1:9091. Видим стандартный ответ на неавторизированный доступ

Далее необходимо отредактировать файл настроек (он только что был создан)
nano /root/.config/transmission-daemon/settings.json

Замените настройки
«rpc-whitelist»: “127.0.0.1”
На
«rpc-whitelist»: “*.*.*.*”

Нажмите F2 что бы сохранить и выйти
Перезапустите демон. Зайдите по тому же адресу.

Далее я сделаю небольшое отступление и расскажу про Sip-Proxy и систему которая как я понимаю теперь применяется в МГТС. Сейчас МГТС практически полностью отказывается от аналоговой связи. Все звонки идут по сип-протоколу, те фактически наш роутер является по сути обычным сип-клиентом. Следовательно мы можем использовать любой сип-телефон и подключатся к сип-серверу и звонить с московского номера откуда угодно. Звучит заманчиво, но есть одна проблема. Дело в том что мы не можем подключится к сип-серверу так как мы находимся за натом (вот в этом суждении я не претендую на объективность просто одна из версий). В качестве решения мы можем использовать сип-прокси. Он будет заниматься передачей пакетов от клиентов до сервера делая вид что он и есть клиент, как собственно и делает обычный http-прокси.
Внесем некоторые изменения в конфигурационный файл.
cd /usr/etc/
cp ./siproxd.conf.example ./siproxd.conf
nano ./siproxd.conf
Внесем следующие изменнения:
if_inbound  = br0
if_outbound = nbif1
daemonize = 0
 outbound_proxy_host = 192.168.68.97
 outbound_proxy_port = 5060
F2-сохраним
Запустим сам прокси-сервер в режиме логирования
siproxd -d -1 0
Зайдем и настройки сип-клиента в самом роутере и укажем что прокси теперь является он сам. После нажатия на кнопку применить мы видим как логах идут пакеты от нашего клиента.

00:16:23 accessctl.c:99 access check =3
00:16:23 security.c:48 security_check_raw: size=440
00:16:23 siproxd.c:481 checking Max-Forwards (=70)
00:16:23 siproxd.c:526 received SIP type REQ:REGISTER
00:16:23 utils.c:129 DNS lookup — previous resolution failed: msk.ims.mgts.ru

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

Подведем итог: как видим нам удалось собрать из исходников достаточно большое количество программного обеспечения. Особенно хотелось бы отметить что все собранное программное обеспечение свежее, нам не пришлось ни прошивать устройство ни использовать какой либо древний репозиторий. При этом мы воспользовались очень простыми патчами. Если заметка вызовет достаточным интерес в хабра-сообществе и мне удастся решить проблему сип-прокси, то я в следующей своей заметки могу рассмотреть вопросы связанные установкой на многостродальный роутер openssh, softether VPN и вопросы запуска x11 приложений. Вообще мне бы хотелось получить обратную связь и возможно появятся другие статьи на данную тему от других авторов, ведь данный терминал очень распространен в Москве.

Скрипты и патчи лежат в архиве.
Update (Ссылки исправлены):
Для самых ленивых архив с корневой директории флешки, с установленными программами
Теги:
Хабы:
+43
Комментарии 35
Комментарии Комментарии 35

Публикации

Истории

Ближайшие события

PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн
Weekend Offer в AliExpress
Дата 20 – 21 апреля
Время 10:00 – 20:00
Место
Онлайн