UPD 14.03.2020:
Raspberry Pi + Fedora (aarch64) = Wi-Fi Hotspot (или малиновый роутер в синей шляпе)
В Интернете огромное количество информации по созданию Wi-Fi точек доступа на базе одноплатного ПК Raspberry. Как правило, подразумевается использование родной для «малинки» операционной системы — Raspbian.
Являясь адептом RPM-based систем, я не мог пройти мимо этого маленького чуда и не попробовать на нем мою любимую CentOS.
В статье представлена инструкция по изготовлению 5GHz/AC Wi-Fi роутера из Raspberry Pi 3 Model B+ на базе операционной системы CentOS. Будет несколько стандартных, но малоизвестных трюков, а в качестве бонуса — чертеж подключения к «малинке» дополнительного Wi-Fi оборудования, позволяющего ей одновременно работать в нескольких режимах (2,4+5GHz).
![image](https://habrastorage.org/r/w1560/webt/mp/yb/fz/mpybfz6gzojqkaftnuljhpzx5da.png)
(микс изображений из свободного доступа)
Отметим сразу, что каких-то космических скоростей не получится. Я выжимаю из своей «малинки» по воздуху максимум 100 Мбит, и это покрывает скорость моего Интернет провайдера. Зачем нужен такой вялый AC, если даже на N в теории можно получить полгигабита? Если вы задались таким вопросом, то ступайте в магазин за настоящим роутером с восемью внешними антеннами.
Небольшой комментарий по последнему пункту. «Что появилось первым, яйцо или...» как сделать Wi-Fi роутер при отсутствии какого бы то ни было оборудования доступа в Интернет? Оставим за рамками статьи это занимательное упражнение и просто допустим, что Raspberry подключена к локальной сети проводом и имеет выход в Интернет. В этом случае нам не понадобятся дополнительные телевизор и манипулятор для настройки «малинки».
Домашняя страница проекта
На момент написания этой статьи, работающая версия CentOS на устройстве — 32-битная. Где-то на просторах всемирной Сети мне попадались мнения о снижении производительности таких ОС на 64-битной архитектуре ARM аж на 20%. Оставлю этот момент без комментария.
На Linux-е качаем минимальный образ с ядром "-RaspberryPI-" и записываем его на microSD:
Перед началом использования образа удалим из него раздел SWAP, расширим корень на весь доступный объем и избавимся от SELinux. Алгоритм — простой: делаем копию корня на Linux, удаляем с microSD все разделы кроме первого (/boot), создаем новый корневой и возвращаем его содержимое из копии.
Переставляем microSD в «малинку», запускаем и получаем к ней сетевой доступ по ssh (root/centos).
Первые три незыблемые движения: passwd, yum -y update, reboot.
Управление сетью отдаем networkd:
Создаем файл (вместе с каталогами) /etc/systemd/network/eth0.network:
Перезагружаем «малинку» и снова получаем к ней сетевой доступ по ssh (IP-адрес может измениться). Обратите внимание на то, что используется /etc/resolv.conf, созданный ранее Network Manager-ом. Поэтому, в случае проблем с resolve, отредактируйте его содержимое. Использовать systemd-resolved мы не будем.
Удаляем «лишнее», чиним и ускоряем загрузку ОС:
Кому нужен cron и кто не переваривает встроенные таймеры systemd, могут установить недостающее. /var/log-и смотрим через journalctl. Если потребуется история журнала (по умолчанию хранятся сведения только с момента старта системы):
Актуальность времени на «малинке» — важная штука. Так как «из коробки» отсутствует аппаратная возможность сохранять текущее состояние часов при перезагрузке, то нужна синхронизация. Очень хороший и быстрый демон для этого — chrony — уже установлен и запускается автоматически. Можно изменить NTP-серверы на ближайшие.
/etc/chrony.conf:
Для установки часового пояса будем использовать трюк. Так как наша цель — создание Wi-Fi роутера, работающего на 5GHz частотах, то заранее подготовимся к сюрпризам регулятора:
Эта злобная конструкция, ориентируясь в том числе на часовой пояс, «запрещает» использование (в России) 5GHz частот и каналов с «большими» номерами. Трюк заключается в установке тайм зоны без использования названий материков/городов, то есть вместо:
Вдавливаем:
И финальные штрихи в прическе системы:
/root/.bash_profile:
Все, о чем было сказано выше, можно считать законченной инструкцией по установке «ванильного» CentOS на Raspberry Pi. У вас должен получиться ПК, который (пере)загружается менее чем за 10 секунд, использует менее 15 Мегабайт оперативной памяти и 1.5 Гигабайта microSD (на самом деле менее 1 Гигабайта из-за неполного /boot, но будем честными до конца):
![](https://habrastorage.org/r/w780q1/webt/mu/0g/cf/mu0gcfyiokq0x_2dysrb1ieh0ke.jpeg)
![](https://habrastorage.org/r/w780q1/webt/xx/l3/_g/xxl3_gukovfw0zawwvvy8ua0dtw.jpeg)
![](https://habrastorage.org/r/w780q1/webt/wt/yc/-9/wtyc-9erdcdx-rvqnnjite7c9ru.jpeg)
Для установки ПО Wi-Fi точки доступа на эту систему потребуется немного расширить возможности стандартного дистрибутива CentOS. Прежде всего «прокачаем» драйвер(прошивку) встроенного Wi-Fi адаптера. На домашней странице проекта сказано:
Что нельзя проекту CentOS, то не запрещено нам для личного использования. Заменяем дистрибутивную Wi-Fi прошивку в CentOS на соответствующую от разработчиков Broadcom (те самые ненавистные бинарные блобы...). Это, в частности, позволит использовать AC в режиме точки доступа.
Ну и конечно же EPEL:
Как мы договорились выше, «малинка» подключена «проводом» к локальной сети. Предположим, что и провайдер предоставляет доступ в Интернет точно таким же способом: адрес в публичной сети выдается динамически DHCP сервером (может быть с привязкой к MAC). В этом случае, после окончательной настройки «малинки», достаточно «воткнуть» в нее кабель провайдера и все готово. Авторизация с помощью systemd-networkd — тема отдельной статьи и здесь не рассматривается.
Wi-Fi интерфейс(ы) у Raspberry — это локальная сеть, а встроенный Ethernet адаптер (eth0) — внешняя. Локальную сеть пронумеруем статически, например: 192.168.0.0/24. Адрес «малинки»: 192.168.0.1. Во внешней сети (Интернет) будет работать DHCP сервер.
Проблема единообразия именования и известный гватемальский программист — две неприятности, поджидающие каждого, кто занимается настройкой сетевых интерфейсов и служб в systemd-дистрибутивах.
Создаем два виртуальных интерфейса-моста (bridge) с постоянными именами: lan и wan. К первому «подключим» Wi-Fi адаптер(ы), ко второму — eth0 «малинки».
/etc/systemd/network/lan.netdev:
/etc/systemd/network/lan.network:
/etc/systemd/network/wan.netdev:
/etc/systemd/network/wan.network:
IPForward=yes избавляет от необходимости через sysctl намекать ядру о включении маршрутизации.
MACAddress= раскомментируем и изменим при необходимости.
Сначала «подключаем» eth0. Помним о «проблеме единообразия» и используем только MAC адрес этого интерфейса, узнать который можно, например, так:
Создаем /etc/systemd/network/eth.network:
Удаляем предыдущий файл конфигурации eth0, перезагружаем «малинку» и получаем к ней сетевой доступ (IP адрес скорее всего изменится):
Для изготовления точек доступа Wi-Fi ничего лучше сладкой парочки из dnsmasq + hostapd еще не придумали. По моему мнению.
Начинаем с dnsmasq:
Шаблон /etc/resolv.conf:
редактируем его по своему вкусу.
Минималистичный /etc/dnsmasq.conf:
«Магия» здесь заключается в параметре bind-dynamic, который указывает демону dnsmasq дожидаться появления в системе interface=lan, а не падать в обморок от приступа гордого одиночества после старта.
И наконец, волшебные конфигурации hostapd. Не сомневаюсь, что кто-то читает эту статью в поиске именно этих заветных строчек.
Перед установкой hostapd нужно побороться с «проблемой единообразия». Встроенный Wi-Fi адаптер wlan0 может легко изменить свое имя на wlan1 при подключении дополнительного USB Wi-Fi оборудования. Поэтому зафиксируем имена интерфейсов следующим способом: придумаем (беспроводным) адаптерам уникальные названия и привяжем их к MAC адресам.
Для встроенного Wi-Fi адаптера, который пока еще wlan0:
Создаем /etc/systemd/network/wl0.link:
Теперь мы будем уверены, что wl0 — это встроенный Wi-Fi. Перезагружаем «малинку», чтобы в этом убедиться.
Устанавливаем:
Конфигурационный файл /etc/hostapd/hostapd.conf:
Ни на минуту не забывая о ГКЧП, изменяем необходимые нам параметры и вручную проверяем на работоспособность:
hostapd запустится в интерактивном режиме, транслируя на консоль свое состояние. Если ошибок не будет, то к точке доступа уже можно будет подключаться клиентам, поддерживающим AC-режим. Для остановки hostapd — Ctrl-C.
Осталось включить hostapd в автозагрузку системы. Если поступить стандартно (systemctl enable hostapd), то после очередной перезагрузки можно получить «валяющегося в крови» демона с диагнозом "интерфейс wl0 не найден". В результате «параллельного хаоса» hostapd завелся быстрее, чем ядро нашло беспроводной адаптер.
В Интернете полно лекарств: от принудительного таймаута перед стартом демона (сколько-то минут), до еще одного демона, который мониторит появление интерфейса и (пере)запускает hostpad. Решения вполне себе рабочие, но ужасно некрасивые. Призываем на помощь великого systemd с его «целями» и "задачами" «зависимостями».
Копируем дистрибутивный service-файл в /etc/systemd/system/hostapd.service:
и приводим его содержимое к следующему виду:
Магия обновленного сервисного файла заключается в динамической привязке hostapd к новой цели — интерфейсу wl0. При появлении интерфейса — демон запускается, при пропадании — останавливается. И это все в онлайне — без перезагрузки системы. Особенно эта техника будет полезной при подключении к «малинке» USB Wi-Fi адаптера.
Вот теперь можно:
«Шта???» © Да-да! Никакого systemd. Никаких новомодных комбайнов (в виде firewalld), которые в итоге делают одно и тоже.
Используем старый добрый iptables, службы которого после своего старта загрузят в ядро сетевые правила и спокойно завершат работу, не оставаясь резидентно и не потребляя ресурсов. У systemd есть элегантный IPMasquerade=, но трансляцию адресов (NAT) и файервол поручим все-таки iptables.
Устанавливаем:
Конфигурацию iptables я предпочитаю хранить в виде скрипта (пример):
Выполняем вышеприведенный скрипт и теряем возможность устанавливать новые проводные ssh-соединения с «малинкой». Все правильно, мы изготовили Wi-Fi роутер, доступ к которому «через Интернет» по умолчанию запрещен — теперь только «по воздуху». Подключаем кабель провайдера в Ethernet и начинаем сёрфинг!
Когда по вышеописанному чертежу я собрал первый Raspberry роутер, то обнаружил у себя в хозяйстве некоторое количество гаджетов, которые в силу своих конструктивных ограничений Wi-Fi не могли увидеть «малинку» вообще. Перенастраивать роутер на работу в 802.11b/g/n было неспортивно, так как максимальная скорость «по воздуху» в таком случае не превышала 40 Мбит, а мой любимый Интернет провайдер предлагает мне 100 (по кабелю).
На самом деле, решение проблемы было уже придумано: второй Wi-Fi интерфейс, работающий на частоте 2,4GHz, и вторая точка доступа. В ближайшем ларьке я приобрел не первый, а второй попавшийся мне USB Wi-Fi «свисток». Продавец был истерзан вопросами о чипсете, совместимости с ARM-ядрами Linux и о возможности работы в режиме AP (он первый начал).
Конфигурируем «свисток» по аналогии со встроенным Wi-Fi адаптером.
Сначала — переименуем его в wl1:
/etc/systemd/network/wl1.link:
Управлять новым Wi-Fi интерфейсом поручим отдельному демону hostapd, который будет запускаться и останавливаться в зависимости от наличия в системе строго определенного «свистка»: wl1.
Конфигурационный файл /etc/hostapd/hostapd2.conf:
Содержимое этого файла напрямую зависит от модели USB Wi-Fi адаптера, поэтому банальный copy/paste может вас подвести.
Копируем дистрибутивный service-файл в /etc/systemd/system/hostapd2.service:
и приводим его содержимое к следующему виду:
Осталось включить новый экземпляр hostapd:
Вот и все! Подергайте «свисток» и саму «малинку», посмотрите на беспроводные сети вокруг.
И напоследок хочу предупредить о качестве USB Wi-Fi адаптера и электропитания Raspberry. Подключенный «на горячую свисток», иногда может вызвать «зависание малинки» из-за кратковременных электрических неприятностей.
Raspberry Pi + Fedora (aarch64) = Wi-Fi Hotspot (или малиновый роутер в синей шляпе)
В Интернете огромное количество информации по созданию Wi-Fi точек доступа на базе одноплатного ПК Raspberry. Как правило, подразумевается использование родной для «малинки» операционной системы — Raspbian.
Являясь адептом RPM-based систем, я не мог пройти мимо этого маленького чуда и не попробовать на нем мою любимую CentOS.
В статье представлена инструкция по изготовлению 5GHz/AC Wi-Fi роутера из Raspberry Pi 3 Model B+ на базе операционной системы CentOS. Будет несколько стандартных, но малоизвестных трюков, а в качестве бонуса — чертеж подключения к «малинке» дополнительного Wi-Fi оборудования, позволяющего ей одновременно работать в нескольких режимах (2,4+5GHz).
![image](https://habrastorage.org/webt/mp/yb/fz/mpybfz6gzojqkaftnuljhpzx5da.png)
(микс изображений из свободного доступа)
Отметим сразу, что каких-то космических скоростей не получится. Я выжимаю из своей «малинки» по воздуху максимум 100 Мбит, и это покрывает скорость моего Интернет провайдера. Зачем нужен такой вялый AC, если даже на N в теории можно получить полгигабита? Если вы задались таким вопросом, то ступайте в магазин за настоящим роутером с восемью внешними антеннами.
0. Что понадобится
- Собственно, само «малиновое изделие» калибра: Pi 3 Model B+ (для достижения заветных 5GHz скоростей и каналов);
- Добротная microSD >= 4GB;
- Рабочая станция с Linux и читателем/писателем microSD;
- Наличие достаточных скиллов в Linux, статья — для подготовленного Гика;
- Проводная сетевая (eth0) связанность между Raspberry и Linux, работающий DHCP-сервер в локальной сети и доступ в Интернет с обоих устройств.
Небольшой комментарий по последнему пункту. «Что появилось первым, яйцо или...» как сделать Wi-Fi роутер при отсутствии какого бы то ни было оборудования доступа в Интернет? Оставим за рамками статьи это занимательное упражнение и просто допустим, что Raspberry подключена к локальной сети проводом и имеет выход в Интернет. В этом случае нам не понадобятся дополнительные телевизор и манипулятор для настройки «малинки».
1. Установка CentOS
Домашняя страница проекта
На момент написания этой статьи, работающая версия CentOS на устройстве — 32-битная. Где-то на просторах всемирной Сети мне попадались мнения о снижении производительности таких ОС на 64-битной архитектуре ARM аж на 20%. Оставлю этот момент без комментария.
На Linux-е качаем минимальный образ с ядром "-RaspberryPI-" и записываем его на microSD:
# xzcat CentOS-Userland-7-armv7hl-RaspberryPI-Minimal-1810-sda.raw.xz | \
dd of=/dev/mmcblk0 bs=4M
# sync
Перед началом использования образа удалим из него раздел SWAP, расширим корень на весь доступный объем и избавимся от SELinux. Алгоритм — простой: делаем копию корня на Linux, удаляем с microSD все разделы кроме первого (/boot), создаем новый корневой и возвращаем его содержимое из копии.
Пример необходимых действий (суровый консольный вывод)
После распаковки содержимого корневого раздела самое время внести в него некоторые изменения.
Отключаем SELinux в /mnt/etc/selinux/config:
Редактируем /mnt/etc/fstab, оставляя в нем только две записи о разделах: загрузочный (/boot, без изменений) и корневой (изменяем значение UUID, которое можно узнать, изучив вывод команды blkid на Linux-е):
Наконец, изменяем параметры загрузки ядра: указываем новое расположение корневого раздела, отключаем вывод отладочной информации и (опционально) запрещаем ядру назначать IPv6 адреса на сетевых интерфейсах:
Приводим содержимое /mnt/cmdline.txt к следующему виду (одна строка без переносов):
Готово:
# mount /dev/mmcblk0p3 /mnt
# cd /mnt
# tar cfz ~/pi.tgz . --no-selinux
# cd
# umount /mnt
# parted /dev/mmcblk0
(parted) unit s
(parted) print free
Model: SD SC16G (sd/mmc)
Disk /dev/mmcblk0: 31116288s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
63s 2047s 1985s Free Space
1 2048s 1370111s 1368064s primary fat32 boot, lba
2 1370112s 2369535s 999424s primary linux-swap(v1)
3 2369536s 5298175s 2928640s primary ext4
5298176s 31116287s 25818112s Free Space
(parted) rm 3
(parted) rm 2
(parted) print free
Model: SD SC16G (sd/mmc)
Disk /dev/mmcblk0: 31116288s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
63s 2047s 1985s Free Space
1 2048s 1370111s 1368064s primary fat32 boot, lba
1370112s 31116287s 29746176s Free Space
(parted) mkpart
Partition type? primary/extended? primary
File system type? [ext2]? ext4
Start? 1370112s
End? 31116287s
(parted) set
Partition number? 2
Flag to Invert? lba
New state? on/[off]? off
(parted) print free
Model: SD SC16G (sd/mmc)
Disk /dev/mmcblk0: 31116288s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
63s 2047s 1985s Free Space
1 2048s 1370111s 1368064s primary fat32 boot, lba
2 1370112s 31116287s 29746176s primary ext4
(parted) quit
# mkfs.ext4 /dev/mmcblk0p2
mke2fs 1.44.6 (5-Mar-2019)
/dev/mmcblk0p2 contains a swap file system labelled '_swap'
Proceed anyway? (y,N) y
Discarding device blocks: done
Creating filesystem with 3718272 4k blocks and 930240 inodes
Filesystem UUID: 6a1a0694-8196-4724-a58d-edde1f189b31
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
# mount /dev/mmcblk0p2 /mnt
# tar xfz ~/pi.tgz -C /mnt --no-selinux
После распаковки содержимого корневого раздела самое время внести в него некоторые изменения.
Отключаем SELinux в /mnt/etc/selinux/config:
SELINUX=disabled
Редактируем /mnt/etc/fstab, оставляя в нем только две записи о разделах: загрузочный (/boot, без изменений) и корневой (изменяем значение UUID, которое можно узнать, изучив вывод команды blkid на Linux-е):
UUID=6a1a0694-8196-4724-a58d-edde1f189b31 / ext4 defaults,noatime 0 0
UUID=6938-F4F2 /boot vfat defaults,noatime 0 0
Наконец, изменяем параметры загрузки ядра: указываем новое расположение корневого раздела, отключаем вывод отладочной информации и (опционально) запрещаем ядру назначать IPv6 адреса на сетевых интерфейсах:
# cd
# umount /mnt
# mount /dev/mmcblk0p1 /mnt
Приводим содержимое /mnt/cmdline.txt к следующему виду (одна строка без переносов):
root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait quiet ipv6.disable_ipv6=1
Готово:
# cd
# umount /mnt
# sync
Переставляем microSD в «малинку», запускаем и получаем к ней сетевой доступ по ssh (root/centos).
2. Настройка CentOS
Первые три незыблемые движения: passwd, yum -y update, reboot.
Управление сетью отдаем networkd:
# yum install systemd-networkd
# systemctl enable systemd-networkd
# systemctl disable NetworkManager
# chkconfig network off
Создаем файл (вместе с каталогами) /etc/systemd/network/eth0.network:
[Match]
Name=eth0
[Network]
DHCP=ipv4
Перезагружаем «малинку» и снова получаем к ней сетевой доступ по ssh (IP-адрес может измениться). Обратите внимание на то, что используется /etc/resolv.conf, созданный ранее Network Manager-ом. Поэтому, в случае проблем с resolve, отредактируйте его содержимое. Использовать systemd-resolved мы не будем.
Удаляем «лишнее», чиним и ускоряем загрузку ОС:
# systemctl set-default multi-user.target
# yum remove GeoIP Network* aic* alsa* cloud-utils-growpart \
cronie* dhc* firewal* initscripts iwl* kexec* logrotate \
postfix rsyslog selinux-pol* teamd wpa_supplicant
Кому нужен cron и кто не переваривает встроенные таймеры systemd, могут установить недостающее. /var/log-и смотрим через journalctl. Если потребуется история журнала (по умолчанию хранятся сведения только с момента старта системы):
# mkdir /var/log/journal
# systemd-tmpfiles --create --prefix /var/log/journal
# systemctl restart systemd-journald
# vi /etc/systemd/journald.conf
Отключаем использование IPv6 основными службами (если требуется)
/etc/ssh/sshd_config:
/etc/sysconfig/chronyd:
AddressFamily inet
/etc/sysconfig/chronyd:
OPTIONS="-4"
Актуальность времени на «малинке» — важная штука. Так как «из коробки» отсутствует аппаратная возможность сохранять текущее состояние часов при перезагрузке, то нужна синхронизация. Очень хороший и быстрый демон для этого — chrony — уже установлен и запускается автоматически. Можно изменить NTP-серверы на ближайшие.
/etc/chrony.conf:
server 0.ru.pool.ntp.org iburst
server 1.ru.pool.ntp.org iburst
server 2.ru.pool.ntp.org iburst
server 3.ru.pool.ntp.org iburst
Для установки часового пояса будем использовать трюк. Так как наша цель — создание Wi-Fi роутера, работающего на 5GHz частотах, то заранее подготовимся к сюрпризам регулятора:
# yum info crda
Summary: Regulatory compliance daemon for 802.11 wireless networking
Эта злобная конструкция, ориентируясь в том числе на часовой пояс, «запрещает» использование (в России) 5GHz частот и каналов с «большими» номерами. Трюк заключается в установке тайм зоны без использования названий материков/городов, то есть вместо:
# timedatectl set-timezone Europe/Moscow
Вдавливаем:
# timedatectl set-timezone Etc/GMT-3
И финальные штрихи в прическе системы:
# hostnamectl set-hostname router
/root/.bash_profile:
. . .
# User specific environment and startup programs
export PROMPT_COMMAND="echo -n $(($(</sys/class/thermal/thermal_zone0/temp) / 1000))\'C\ "
export LANG=en_US.UTF-8
export PATH=$PATH:$HOME/bin
3. Дополнения CentOS
Все, о чем было сказано выше, можно считать законченной инструкцией по установке «ванильного» CentOS на Raspberry Pi. У вас должен получиться ПК, который (пере)загружается менее чем за 10 секунд, использует менее 15 Мегабайт оперативной памяти и 1.5 Гигабайта microSD (на самом деле менее 1 Гигабайта из-за неполного /boot, но будем честными до конца):
![](https://habrastorage.org/webt/mu/0g/cf/mu0gcfyiokq0x_2dysrb1ieh0ke.jpeg)
![](https://habrastorage.org/webt/xx/l3/_g/xxl3_gukovfw0zawwvvy8ua0dtw.jpeg)
![](https://habrastorage.org/webt/wt/yc/-9/wtyc-9erdcdx-rvqnnjite7c9ru.jpeg)
Для установки ПО Wi-Fi точки доступа на эту систему потребуется немного расширить возможности стандартного дистрибутива CentOS. Прежде всего «прокачаем» драйвер(прошивку) встроенного Wi-Fi адаптера. На домашней странице проекта сказано:
Wifi on the Raspberry 3B and 3B+
The Raspberry PI 3B/3B+ firmware files are not allowed to be distributed by the CentOS Project. You can use the following articles to understand the issue, get the firmware and set up the wifi.
Что нельзя проекту CentOS, то не запрещено нам для личного использования. Заменяем дистрибутивную Wi-Fi прошивку в CentOS на соответствующую от разработчиков Broadcom (те самые ненавистные бинарные блобы...). Это, в частности, позволит использовать AC в режиме точки доступа.
Wi-Fi firmware upgrade
Выясняем модель устройства и текущую версию прошивки:
Видим, что прошивка версии 7.45.18 от 01.03.2015, и запоминаем следующий набор цифр: 43455 (brcmfmac43455-sdio.bin).
Качаем актуальный образ Raspbian. Ленивые могут записать образ на microSD и оттуда забрать файлы с прошивкой. А можно смонтировать корневой раздел образа в Linux и скопировать нужное оттуда:
Полученные файлы прошивки Wi-Fi адаптера нужно скопировать с заменой на «малинку» в каталог /usr/lib/firmware/brcm/
Перезагружаем будущий роутер и довольно улыбаемся:
Версия: 7.45.154 от 27.02.2018.
# journalctl | grep $(basename $(readlink /sys/class/net/wlan0/device/driver))
Jan 01 04:00:03 router kernel: brcmfmac: F1 signature read @0x18000000=0x15264345
Jan 01 04:00:03 router kernel: brcmfmac: brcmf_fw_map_chip_to_name: using brcm/brcmfmac43455-sdio.bin for chip 0x004345(17221) rev 0x000006
Jan 01 04:00:03 router kernel: usbcore: registered new interface driver brcmfmac
Jan 01 04:00:03 router kernel: brcmfmac: brcmf_c_preinit_dcmds: Firmware version = wl0: Mar 1 2015 07:29:38 version 7.45.18 (r538002) FWID 01-6a2c8ad4
Jan 01 04:00:03 router kernel: brcmfmac: brcmf_c_preinit_dcmds: CLM version = API: 12.2 Data: 7.14.8 Compiler: 1.24.9 ClmImport: 1.24.9 Creation: 2014-09-02 03:05:33 Inc Data: 7.17.1 Inc Compiler: 1.26.11 Inc ClmImport: 1.26.11 Creation: 2015-03-01 07:22:34
Видим, что прошивка версии 7.45.18 от 01.03.2015, и запоминаем следующий набор цифр: 43455 (brcmfmac43455-sdio.bin).
Качаем актуальный образ Raspbian. Ленивые могут записать образ на microSD и оттуда забрать файлы с прошивкой. А можно смонтировать корневой раздел образа в Linux и скопировать нужное оттуда:
# wget https://downloads.raspberrypi.org/raspbian_lite_latest
# unzip -p raspbian_lite_latest > raspbian.img
# fdisk -l raspbian.img
Disk raspbian.img: 2 GiB, 2197815296 bytes, 4292608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x17869b7d
Device Boot Start End Sectors Size Id Type
raspbian.img1 8192 532480 524289 256M c W95 FAT32 (LBA)
raspbian.img2 540672 4292607 3751936 1.8G 83 Linux
# mount -t ext4 -o loop,offset=$((540672 * 512)) raspbian.img /mnt
# cp -fv /mnt/lib/firmware/brcm/*43455* ...
'/mnt/lib/firmware/brcm/brcmfmac43455-sdio.bin' -> ...
'/mnt/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob' -> ...
'/mnt/lib/firmware/brcm/brcmfmac43455-sdio.txt' -> ...
# umount /mnt
Полученные файлы прошивки Wi-Fi адаптера нужно скопировать с заменой на «малинку» в каталог /usr/lib/firmware/brcm/
Перезагружаем будущий роутер и довольно улыбаемся:
# journalctl | grep $(basename $(readlink /sys/class/net/wlan0/device/driver))
Jan 01 04:00:03 router kernel: brcmfmac: F1 signature read @0x18000000=0x15264345
Jan 01 04:00:03 router kernel: brcmfmac: brcmf_fw_map_chip_to_name: using brcm/brcmfmac43455-sdio.bin for chip 0x004345(17221) rev 0x000006
Jan 01 04:00:03 router kernel: usbcore: registered new interface driver brcmfmac
Jan 01 04:00:03 router kernel: brcmfmac: brcmf_c_preinit_dcmds: Firmware version = wl0: Feb 27 2018 03:15:32 version 7.45.154 (r684107 CY) FWID 01-4fbe0b04
Jan 01 04:00:03 router kernel: brcmfmac: brcmf_c_preinit_dcmds: CLM version = API: 12.2 Data: 9.10.105 Compiler: 1.29.4 ClmImport: 1.36.3 Creation: 2018-03-09 18:56:28
Версия: 7.45.154 от 27.02.2018.
Ну и конечно же EPEL:
# cat > /etc/yum.repos.d/epel.repo << EOF
[epel]
name=Epel rebuild for armhfp
baseurl=https://armv7.dev.centos.org/repodir/epel-pass-1/
enabled=1
gpgcheck=0
EOF
# yum clean all
# rm -rfv /var/cache/yum
# yum update
4. Сетевая конфигурация и предстоящие трудности
Как мы договорились выше, «малинка» подключена «проводом» к локальной сети. Предположим, что и провайдер предоставляет доступ в Интернет точно таким же способом: адрес в публичной сети выдается динамически DHCP сервером (может быть с привязкой к MAC). В этом случае, после окончательной настройки «малинки», достаточно «воткнуть» в нее кабель провайдера и все готово. Авторизация с помощью systemd-networkd — тема отдельной статьи и здесь не рассматривается.
Wi-Fi интерфейс(ы) у Raspberry — это локальная сеть, а встроенный Ethernet адаптер (eth0) — внешняя. Локальную сеть пронумеруем статически, например: 192.168.0.0/24. Адрес «малинки»: 192.168.0.1. Во внешней сети (Интернет) будет работать DHCP сервер.
Проблема единообразия именования и известный гватемальский программист — две неприятности, поджидающие каждого, кто занимается настройкой сетевых интерфейсов и служб в systemd-дистрибутивах.
Параллельный хаос (лирическое отступление)
Леннарт Поттеринг составил свою программу systemd очень хорошо. Эта systemd запускает другие программы так быстро, что те, не успев опомниться от судейского пинка свистка, спотыкаются и падают на старте даже не начав свой бег с препятствиями.
Ну а если серьезно, то агрессивное распараллеливание запускаемых процессов при старте systemd-ОС является неким «ослиным мостиком» для матерых последовательных LSB-шников. К счастью, привести в порядок этот «параллельный хаос» оказывается простым, правда не всегда очевидным делом.
Ну а если серьезно, то агрессивное распараллеливание запускаемых процессов при старте systemd-ОС является неким «ослиным мостиком» для матерых последовательных LSB-шников. К счастью, привести в порядок этот «параллельный хаос» оказывается простым, правда не всегда очевидным делом.
Создаем два виртуальных интерфейса-моста (bridge) с постоянными именами: lan и wan. К первому «подключим» Wi-Fi адаптер(ы), ко второму — eth0 «малинки».
/etc/systemd/network/lan.netdev:
[NetDev]
Name=lan
Kind=bridge
/etc/systemd/network/lan.network:
[Match]
Name=lan
[Network]
Address=192.168.0.1/24
IPForward=yes
/etc/systemd/network/wan.netdev:
[NetDev]
Name=wan
Kind=bridge
#MACAddress=xx:xx:xx:xx:xx:xx
/etc/systemd/network/wan.network:
[Match]
Name=wan
[Network]
DHCP=ipv4
IPForward=yes
IPForward=yes избавляет от необходимости через sysctl намекать ядру о включении маршрутизации.
MACAddress= раскомментируем и изменим при необходимости.
Сначала «подключаем» eth0. Помним о «проблеме единообразия» и используем только MAC адрес этого интерфейса, узнать который можно, например, так:
# cat /sys/class/net/eth0/address
Создаем /etc/systemd/network/eth.network:
[Match]
MACAddress=b8:27:eb:xx:xx:xx
[Network]
Bridge=wan
Удаляем предыдущий файл конфигурации eth0, перезагружаем «малинку» и получаем к ней сетевой доступ (IP адрес скорее всего изменится):
# rm -fv /etc/systemd/network/eth0.network
# reboot
5. DNSMASQ
Для изготовления точек доступа Wi-Fi ничего лучше сладкой парочки из dnsmasq + hostapd еще не придумали. По моему мнению.
Если кто забыл, то...
hostapd — это штука, которая управляет Wi-Fi адаптерами (в частности, возьмет на себя труд по их подключению к виртуальному lan «малинки»), авторизует и регистрирует беспроводных клиентов.
dnsmasq — настраивает сетевой стек клиентов: выдает IP-адреса, DNS-серверы, шлюз по умолчанию и тому подобные прелести.
dnsmasq — настраивает сетевой стек клиентов: выдает IP-адреса, DNS-серверы, шлюз по умолчанию и тому подобные прелести.
Начинаем с dnsmasq:
# yum install dnsmasq
Шаблон /etc/resolv.conf:
nameserver 1.1.1.1
nameserver 1.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 77.88.8.8
nameserver 77.88.8.1
domain router.local
search router.local
редактируем его по своему вкусу.
Минималистичный /etc/dnsmasq.conf:
domain-needed
bogus-priv
interface=lan
bind-dynamic
expand-hosts
domain=#
dhcp-range=192.168.0.100,192.168.0.199,255.255.255.0,24h
conf-dir=/etc/dnsmasq.d
«Магия» здесь заключается в параметре bind-dynamic, который указывает демону dnsmasq дожидаться появления в системе interface=lan, а не падать в обморок от приступа гордого одиночества после старта.
# systemctl enable dnsmasq
# systemctl start dnsmasq; journalctl -f
6. HOSTAPD
И наконец, волшебные конфигурации hostapd. Не сомневаюсь, что кто-то читает эту статью в поиске именно этих заветных строчек.
Перед установкой hostapd нужно побороться с «проблемой единообразия». Встроенный Wi-Fi адаптер wlan0 может легко изменить свое имя на wlan1 при подключении дополнительного USB Wi-Fi оборудования. Поэтому зафиксируем имена интерфейсов следующим способом: придумаем (беспроводным) адаптерам уникальные названия и привяжем их к MAC адресам.
Для встроенного Wi-Fi адаптера, который пока еще wlan0:
# cat /sys/class/net/wlan0/address
b8:27:eb:xx:xx:xx
Создаем /etc/systemd/network/wl0.link:
[Match]
MACAddress=b8:27:eb:xx:xx:xx
[Link]
Name=wl0
Теперь мы будем уверены, что wl0 — это встроенный Wi-Fi. Перезагружаем «малинку», чтобы в этом убедиться.
Устанавливаем:
# yum install hostapd wireless-tools
Конфигурационный файл /etc/hostapd/hostapd.conf:
ssid=rpi
wpa_passphrase=1234567890
channel=36
country_code=US
interface=wl0
bridge=lan
driver=nl80211
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
macaddr_acl=0
hw_mode=a
wmm_enabled=1
# N
ieee80211n=1
require_ht=1
ht_capab=[MAX-AMSDU-3839][HT40+][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]
# AC
ieee80211ac=1
require_vht=1
ieee80211d=0
ieee80211h=0
vht_capab=[MAX-AMSDU-3839][SHORT-GI-80]
vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=42
Ни на минуту не забывая о ГКЧП, изменяем необходимые нам параметры и вручную проверяем на работоспособность:
# hostapd /etc/hostapd/hostapd.conf
hostapd запустится в интерактивном режиме, транслируя на консоль свое состояние. Если ошибок не будет, то к точке доступа уже можно будет подключаться клиентам, поддерживающим AC-режим. Для остановки hostapd — Ctrl-C.
Осталось включить hostapd в автозагрузку системы. Если поступить стандартно (systemctl enable hostapd), то после очередной перезагрузки можно получить «валяющегося в крови» демона с диагнозом "интерфейс wl0 не найден". В результате «параллельного хаоса» hostapd завелся быстрее, чем ядро нашло беспроводной адаптер.
В Интернете полно лекарств: от принудительного таймаута перед стартом демона (сколько-то минут), до еще одного демона, который мониторит появление интерфейса и (пере)запускает hostpad. Решения вполне себе рабочие, но ужасно некрасивые. Призываем на помощь великого systemd с его «целями» и "
Копируем дистрибутивный service-файл в /etc/systemd/system/hostapd.service:
# cp -fv /usr/lib/systemd/system/hostapd.service /etc/systemd/system
и приводим его содержимое к следующему виду:
[Unit]
Description=Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
After=sys-subsystem-net-devices-wl0.device
BindsTo=sys-subsystem-net-devices-wl0.device
[Service]
Type=forking
PIDFile=/run/hostapd.pid
ExecStart=/usr/sbin/hostapd /etc/hostapd/hostapd.conf -P /run/hostapd.pid -B
[Install]
WantedBy=sys-subsystem-net-devices-wl0.device
Магия обновленного сервисного файла заключается в динамической привязке hostapd к новой цели — интерфейсу wl0. При появлении интерфейса — демон запускается, при пропадании — останавливается. И это все в онлайне — без перезагрузки системы. Особенно эта техника будет полезной при подключении к «малинке» USB Wi-Fi адаптера.
Вот теперь можно:
# systemctl enable hostapd
# reboot
7. IPTABLES
«Шта???» © Да-да! Никакого systemd. Никаких новомодных комбайнов (в виде firewalld), которые в итоге делают одно и тоже.
Используем старый добрый iptables, службы которого после своего старта загрузят в ядро сетевые правила и спокойно завершат работу, не оставаясь резидентно и не потребляя ресурсов. У systemd есть элегантный IPMasquerade=, но трансляцию адресов (NAT) и файервол поручим все-таки iptables.
Устанавливаем:
# yum install iptables-services
# systemctl enable iptables ip6tables
Конфигурацию iptables я предпочитаю хранить в виде скрипта (пример):
#!/bin/bash
#
# Disable IPv6
#
ip6tables --flush
ip6tables --delete-chain
ip6tables --policy INPUT DROP
ip6tables --policy FORWARD DROP
ip6tables --policy OUTPUT DROP
ip6tables-save > /etc/sysconfig/ip6tables
systemctl restart ip6tables
#
# Cleaning
#
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
#
# Loopback, lan
#
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i lan -j ACCEPT
#
# Ping, Established
#
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#
# NAT
#
iptables -t nat -A POSTROUTING -o wan -j MASQUERADE
#
# Saving
#
iptables-save > /etc/sysconfig/iptables
systemctl restart iptables
Выполняем вышеприведенный скрипт и теряем возможность устанавливать новые проводные ssh-соединения с «малинкой». Все правильно, мы изготовили Wi-Fi роутер, доступ к которому «через Интернет» по умолчанию запрещен — теперь только «по воздуху». Подключаем кабель провайдера в Ethernet и начинаем сёрфинг!
8. Бонус: +2,4GHz
Когда по вышеописанному чертежу я собрал первый Raspberry роутер, то обнаружил у себя в хозяйстве некоторое количество гаджетов, которые в силу своих конструктивных ограничений Wi-Fi не могли увидеть «малинку» вообще. Перенастраивать роутер на работу в 802.11b/g/n было неспортивно, так как максимальная скорость «по воздуху» в таком случае не превышала 40 Мбит, а мой любимый Интернет провайдер предлагает мне 100 (по кабелю).
На самом деле, решение проблемы было уже придумано: второй Wi-Fi интерфейс, работающий на частоте 2,4GHz, и вторая точка доступа. В ближайшем ларьке я приобрел не первый, а второй попавшийся мне USB Wi-Fi «свисток». Продавец был истерзан вопросами о чипсете, совместимости с ARM-ядрами Linux и о возможности работы в режиме AP (он первый начал).
Конфигурируем «свисток» по аналогии со встроенным Wi-Fi адаптером.
Сначала — переименуем его в wl1:
# cat /sys/class/net/wlan0/address
b0:6e:bf:xx:xx:xx
/etc/systemd/network/wl1.link:
[Match]
MACAddress=b0:6e:bf:xx:xx:xx
[Link]
Name=wl1
Управлять новым Wi-Fi интерфейсом поручим отдельному демону hostapd, который будет запускаться и останавливаться в зависимости от наличия в системе строго определенного «свистка»: wl1.
Конфигурационный файл /etc/hostapd/hostapd2.conf:
ssid=rpi2
wpa_passphrase=1234567890
#channel=1
#channel=6
channel=11
interface=wl1
bridge=lan
driver=nl80211
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
macaddr_acl=0
hw_mode=g
wmm_enabled=1
# N
ieee80211n=1
require_ht=1
ht_capab=[HT40][SHORT-GI-20][SHORT-GI-40][DSSS_CCK-40]
Содержимое этого файла напрямую зависит от модели USB Wi-Fi адаптера, поэтому банальный copy/paste может вас подвести.
Копируем дистрибутивный service-файл в /etc/systemd/system/hostapd2.service:
# cp -fv /usr/lib/systemd/system/hostapd.service /etc/systemd/system/hostapd2.service
и приводим его содержимое к следующему виду:
[Unit]
Description=Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
After=sys-subsystem-net-devices-wl1.device
BindsTo=sys-subsystem-net-devices-wl1.device
[Service]
Type=forking
PIDFile=/run/hostapd2.pid
ExecStart=/usr/sbin/hostapd /etc/hostapd/hostapd2.conf -P /run/hostapd2.pid -B
[Install]
WantedBy=sys-subsystem-net-devices-wl1.device
Осталось включить новый экземпляр hostapd:
# systemctl enable hostapd2
Вот и все! Подергайте «свисток» и саму «малинку», посмотрите на беспроводные сети вокруг.
И напоследок хочу предупредить о качестве USB Wi-Fi адаптера и электропитания Raspberry. Подключенный «на горячую свисток», иногда может вызвать «зависание малинки» из-за кратковременных электрических неприятностей.