Старые методы и их недостатки


Я думаю, никому уже не интересно читать во второй раз (а может быть и в третий), о том, как Yota определяет, пользуется ли человек телефоном в режиме модема или точки доступа. «Зачем нам ещё одна статья?» — спросите вы.

Дело в том, что методы обхода, приведённые по ссылкам, не позво��яют настроить телефон таким образом, чтобы позже при подключении любых устройств не потребовалось ничего настраивать заново. Кроме того, пользователь будет испытывать серьёзные неудобства, если он подключает несколько устройств с разными TTL. Придётся как минимум менять TTL на одном из них.

Именно эти причины мотивировали меня копать дальше в поисках ответа на вечный вопрос «Как же всё-таки нахаляву раздать интернет всему офису?». И найти такой ответ удалось (только для android, у меня нет яблока).

Готовая программа


Когда я узнал, что Yota следит за TTL, то предположил, что наверняка где-то в других странах есть провайдеры, которые поступают так же. Пробуем ввести TTL в поиске Play Market'а.

Я был прав: тут же нашлась программа TTLEditor. Очень приятно, что она мало того, что бесплатная, так ещё и с открытым исходным кодом.
Пользоваться очень просто: выбрать интерфейс (лучше всего выбирать интерфейс через который телефон связан с провайдером, у меня это rmnet0) и нажать кнопку OK. Можно также поставить программу срабатывать при загрузке телефона.



Только одна проблема возникла: программа выдала ошибку «TTL update failed». Прежде чем ругать автора в комментариях и минусовать на Play Market'е, я решил почитать исходный код.

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

Причина ошибки


Основное действие программы — запуск от имени root следующей команды:
iptables -t mangle -A POSTROUTING -o <интерфейс> -j TTL --ttl-set <значение TTL>
Много мозгов не нужно, чтобы понять, что делает эта команда (к тому же в программе написано об этом): она устанавливает заданное значение TTL всем пакетам, проходящим через определённый интерфейс (то есть как раз то, что нам требуется).

Я попробовал выполнить команду вручную и увидел вот такую ошибку: iptables: No chain/target/match by that name. Пара минут гугления показала, что эту ошибку iptables готов выдать почти на любые неверные параметры. Гуглим применительно к TTL и что-то всё же находим. Смотрим, насколько подходящую информацию мы нашли.

Команда cat /proc/net/ip_tables_matches выдаёт списо��, в котором есть ttl, то есть проверять TTL наше ядро умеет. А вот в списке, который выдаёт команда cat /proc/net/ip_tables_targets, нет TTL, поэтому модифицировать TTL наше ядро не умеет. Сдаваться перед таким наглым сговором мобильных провайдеров и производителей мы не станем, поэтому идём собирать модуль ядра, которого не хватает.

Я думаю, на этом этапе пользователи CyanogenMod уже злобно похихикивают, но мне не хотелось так просто отказываться от штатной системы, а хотелось добавить именно в неё новые возможности (даже не заменяя ядро).

Отступление


Далее я предполагаю, что читатель умеет пользоваться Linux, понимает, что такое ядро и модули ядра, а также знает, как с помощью adb перекидывать файлы (adb push/pull) и как открыть на компьютере терминал телефона (adb shell). Если нет — срочно в гугл! Если да — не забудьте включить отладку по USB.

Из чего собирать и чем


Это самый сложный шаг: нужно найти подходящий кросс-компилятор и исходники ядра. Старайтесь искать именно для своего телефона, так как иначе, скорее всего, ничего не заработает (а об этом станет известно только на последнем шаге). Я сделал несколько неудачных попыток, допустив ошибку именно на этом этапе.

Модель моего телефона Sony Xperia Z1 Compact, операционная система моего компьютера Ubuntu 14.04. Ниже на их примере я покажу, как можно действовать.

  • Команда cat /proc/version может подсказать, какая версия gcc использовалась для сборки ядра на телефоне (у меня: 4.7).

  • Скачиваем подходящий кросс-компилятор (toolchain). Я нашёл его здесь. Выполняю на компьютере команду:
    git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7
    и он у меня в папке arm-eabi-4.7 (для клонирования git-репозитория не забудьте установить git).

  • Номер сборки прошивки можно посмотреть в настройках телефона «О телефоне». У меня: 14.4.A.0.108.
    Найти нужные исходники ядра удалось в соответствующем архиве здесь и в репозитории здесь. Я взял из архива, потому что раньше отыскал.
    Если я хоть что-то понимаю в мире лицензий, то производитель обязан предоставлять исходные коды ядра, работающего на андроидофоне.


Настройка и сборка


Те, кто сталкивается с процессом сборки ядра впервые, не поддавайтесь панике, с гуглом мы богоподобны всегда.

  • Для начала, открываем консоль в папке с исходниками ядра и настраиваем среду окружения, чтобы ядро собиралось добытым кросс-компилятором:
    export ARCH=arm
    export CROSS_COMPILE=/путь/к/arm-eabi-4.7/bin/arm-eabi-
    На конце переменной среды CROSS_COMPILE должен находиться общий префикс большинства (или всех) исполняемых файлов в папке bin.

  • Затем нужно создать для вашей модели телефона дефолтную конфигурацию ядра (файл .config). Нужная для этого команда обычно написана в каком-нибудь README поблизости. В моём случае, в папке с исходниками ядра был файл README_Xperia.
    make rhine_amami_row_defconfig    # создание дефолтной конфигурации ядра для Sony Xperia Z1 Compact

  • А вот теперь нужно сделать шаг, который обычно не приводится в описаниях сборки ядра для Android.
    make menuconfig
    Откроется конфигуратор ядра.

    Жмём «/» и вводим в поиск «TARGET_TTL».



    Ага, теперь стало ясно, где находится нужная нам возможность ядра. Переходим к ней в конфигураторе и нажимаем кнопку «M». Это значит, что мы хотим скомпилировать эту возможность как модуль ядра.



    Выходим из конфигуратора, сохраняя изменения.

  • Собираем ядро и модули:
    make -j8
    make modules
    Если произошли какие-то ошибки, то это значит, что вы, скорее всего, нашли неподходящие исходники ядра или кросс-компилятор.

  • Нужный нам собранный модуль находится здесь: net/netfilter/xt_HL.ko


Использование модуля на телефоне


Перекидываем модуль xt_HL.ko на телефон и пытаемся подключить его к ядру командой insmod.
Если эта команда выдаёт ошибку, то подробности можно узнать в выводе команды dmesg (скорее всего, это будет конфликт версий ядра и модуля или что-то похожее — это значит, что были взяты неподходящие исходники ядра или кросс-компилятор).

Если команда insmod выполнится успешно, то значит модуль удалось подключить к ядру (проверить можно командой lsmod).
После этого попробуем запустить команду, которую безуспеш��о пытался использовать TTLEditor. Ошибку не выдаёт? Значит правило добавилось в список. Можно проверить командой iptables -t mangle -L:



Пробуем раздавать интернет любым устройствам и радуемся.

Настройка автозагрузки


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

Создадим файл setup_ttl_editing.sh со следующий содержимым:
#!/system/bin/sh

insmod /storage/sdcard0/xt_HL.ko
iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set 64

Закидываем его на телефон, ставим программу Script Manager и в ней настраиваем, чтобы скрипт запускался при загрузке системы и от пользователя root.



Всё настроено, можно забыть о проблеме раздачи интернета с телефона!

Примечание. Программа TTLEditor нам не нужна. Всё необходимое уже написано в скрипте.

Заключение


Я не буду писать «йота, не будьте жадинами», потому что по сравнению со многими другими мобильными провайдерами они всё-таки достаточно щедрые. Я лучше скажу: йота, оставайтесь такими же как вы есть.

Скачать файл xt_HL.ko, который у меня получился для Xperia Z1 Compact, можно по этой ссылке.
Возможно, он подойдёт и для похожих моделей телефонов.

UPD от 13.03.2015. Спасибо пользователю CTE6EJIb за файл xt_HL.ko для Xperia V Android 4.3, версия прошивки 9.2.A.2.5.
UPD от 01.08.2015. Скомпилил для Xperia Z1 Compact под Android 5, версия прошивки 14.5.A.0.270. Скачать.