Записки программиста
Превращаем Raspberry Pi в беспроводной роутер, и заодно заворачиваем весь трафик в VPN
Беспроводные роутеры имеют несколько неприятных особенностей. Во-первых, они небезопасны, если только не разобраться с установкой OpenWrt. Во-вторых, со временем они перестают выпускаться, а значит, если ваш роутер сломается, вам придется разбираться с установкой OpenWrt на совершенно другой роутер. В-третьих, как правило, они довольно ограничены в ресурсах, а значит возложить на роутер какие-то дополнительные функции может быть проблематично. Между тем, абсолютно любой компьютер под управлением Linux может быть настроен в качестве полноценного Wi-Fi роутера, что решает проблемы безопасности, повторяемости и производительности. Для примера, рассмотрим создание беспроводного роутера на базе одноплатного компьютера Raspberry Pi.
Подготовительные работы
Я использовал уже не новую Raspberry Pi 2 Model B под управлением Raspbian Linux 9 (Stretch). В последних версиях этого дистрибутива SSH по умолчанию выключен. Чтобы его включить, вам понадобится USB-клавиатура и монитор с HDMI. Логинимся под пользователем pi с паролем raspberry, меняем пароль, включаем SSH:
Из сетевых интерфейсов данный одноплатник имеет только один Ethernet-разъем. Чтобы у устройства появился второй разъем, я использовал сетевую карту от компании Olimex на базе чипа AX88772B. Вы можете помнить это устройство по заметке Снифинг Ethernet-трафика с платой Throwing Star. Чтобы малина также умела и Wi-Fi, был использован донгл Panda Wireless PAU07 (a.k.a Panda N600) на базе чипа Ralink RT5572. Вообще, это довольно неплохой и популярный чип. На eBay вы найдете много других устройств на его базе. Примите во внимание, что не всякий донгл работает с Linux, а из тех, что работают, не всякий поддерживает работу в качестве точки доступа. Поэтому перед покупкой устройства будет не лишним загуглить, подходит ли оно для задачи.
Внешний вид роутера у меня получился следующим:
С точки зрения ОС картина такая:
- eth0 — встроенный Ethernet, здесь у нас будет WAN;
- eth1 — сетевая карта на базе AX88772B будет использована для LAN;
- wlan0 — донгл Panda Wireless PAU07, здесь будет WLAN;
Само собой разумеется, все описанные далее шаги будут работать для любого компьютера под управлением Linux с подходящими сетевыми интерфейсами, не только Raspberry Pi. Это вполне может быть какой-то старый стационарный компьютер, нетбук, или другой одноплатник. Интересно, что существуют даже специальные одноплатники с Wi-Fi и двумя или более Ethernet-портами. Одним из таких одноплатников является Orange Pi R1. На AliExpress или eBay устройство можно купить где-то за 20$ с доставкой. Пользователь vova_ivanov из чата Hardware & Radio даже подсказал, что используемый в нем Realtek RTL8189 без проблем работает в роли точки доступа под Linux. А также предупредил, что Orange Pi R1 не умеет PoE и убивается им. В том же чате Xarlan подсказал, что больше подобных одноплатников можно найти на сайте board-db.org. В частности, довольно интересно выглядят Banana Pi BPI-R1, Banana Pi BPI-R2 и Banana Pi BPI-R64. Впрочем, эти устройства относятся уже к другому ценовому диапазону, а BPI-R64 на момент написания этих строк еще нигде не продавался.
Первоначальная настройка NAT
Открываем /etc/network/interfaces и пишем туда следующее:
auto lo
iface lo inet loopback
# Вариант А, без смены MAC:
# iface eth0 inet dhcp
# Вариант Б, со сменой MAC:
iface eth0 inet dhcp
hwaddress ether 11:22:33:44:55:66
auto eth1
iface eth1 inet static
address 10.128.10.1
network 10.128.10.0
netmask 255.255.255.0
broadcast 10.128.10.255
auto wlan0
iface wlan0 inet static
address 10.128.11.1
network 10.128.11.0
netmask 255.255.255.0
broadcast 10.128.11.255
Вариант со сменой MAC нужен исключительно в случае, если ваш интернет-провайдер ограничивает доступ по MAC-адресам, как это зачем-то делает мой. Если ваш ISP не страдает такой фигней, смело используйте вариант А.
Поскольку мы подправили /etc/network/interfaces, демон dhcpcd теперь будет отказываться стартовать. Для порядку отключим его, чтобы система при загрузке не ругалась ошибками:
Следующим шагом ставим dnsmasq, который будет играть роль DHCP-сервера и кэширующего DNS-сервера. Если нужно, в нем также есть функция TFTP-сервера. Такой сервер, к примеру, бывает нужен для установки OpenWrt на некоторые роутеры.
# Можно явно указать апстрим DNS-сервера
# Это может быть особенно полезно, если вы
# хотите заворачивать весь трафик в VPN
server=8.8.8.8
server=8.8.4.4
# Listen only given interfaces
interface=lo
interface=eth1
interface=wlan0
bind-interfaces
# DNS cache size
cache-size=15000
# IP ranges
dhcp-range=eth1,10.128.10.50,10.128.10.250
dhcp-range=wlan0,10.128.11.50,10.128.11.250
# Default gateways
dhcp-option=eth1,3,10.128.10.1
dhcp-option=wlan0,3,10.128.11.1
# DNS servers
dhcp-option=eth1,6,10.128.10.1
dhcp-option=wlan0,6,10.128.11.1
Проверяем работу DNS-сервера:
DHCP и DNS настроены, осталось настроить NAT. Делается это при помощи iptables:
# enable IP-forwarding
sudo sh -c ‘echo 1 > /proc/sys/net/ipv4/ip_forward’
# for LAN
sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o eth1 -m conntrack \
—ctstate ESTABLISHED,RELATED -j ACCEPT
# for WLAN
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -m conntrack \
—ctstate ESTABLISHED,RELATED -j ACCEPT
# allow traffic between LAN and WLAN
sudo iptables -A FORWARD -i wlan0 -o eth1 -j ACCEPT
sudo iptables -A FORWARD -i eth1 -o wlan0 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Подключаем ноутбук ко второму Ethernet-порту малины. Проверяем, что нам выдали IP-адрес, и что имеется доступ в интернет. Если все работает, сохраняем сделанные изменения, чтобы они не потерялись после перезагрузки.
Fun fact! Нравится статья? Поддержи автора, чтобы он мог писать больше полезных статей!
Raspberry Pi + CentOS = 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).
(микс изображений из свободного доступа)
Отметим сразу, что каких-то космических скоростей не получится. Я выжимаю из своей «малинки» по воздуху максимум 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:
Перед началом использования образа удалим из него раздел SWAP, расширим корень на весь доступный объем и избавимся от SELinux. Алгоритм — простой: делаем копию корня на Linux, удаляем с microSD все разделы кроме первого (/boot), создаем новый корневой и возвращаем его содержимое из копии.
После распаковки содержимого корневого раздела самое время внести в него некоторые изменения.
Отключаем SELinux в /mnt/etc/selinux/config:
Редактируем /mnt/etc/fstab, оставляя в нем только две записи о разделах: загрузочный (/boot, без изменений) и корневой (изменяем значение UUID, которое можно узнать, изучив вывод команды blkid на Linux-е):
Наконец, изменяем параметры загрузки ядра: указываем новое расположение корневого раздела, отключаем вывод отладочной информации и (опционально) запрещаем ядру назначать IPv6 адреса на сетевых интерфейсах:
Приводим содержимое /mnt/cmdline.txt к следующему виду (одна строка без переносов):
Переставляем microSD в «малинку», запускаем и получаем к ней сетевой доступ по ssh (root/centos).
2. Настройка 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-серверы на ближайшие.
Для установки часового пояса будем использовать трюк. Так как наша цель — создание Wi-Fi роутера, работающего на 5GHz частотах, то заранее подготовимся к сюрпризам регулятора:
# yum info crda
Summary: Regulatory compliance daemon for 802.11 wireless networking
Эта злобная конструкция, ориентируясь в том числе на часовой пояс, «запрещает» использование (в России) 5GHz частот и каналов с «большими» номерами. Трюк заключается в установке тайм зоны без использования названий материков/городов, то есть вместо:
И финальные штрихи в прическе системы:
3. Дополнения CentOS
Все, о чем было сказано выше, можно считать законченной инструкцией по установке «ванильного» CentOS на Raspberry Pi. У вас должен получиться ПК, который (пере)загружается менее чем за 10 секунд, использует менее 15 Мегабайт оперативной памяти и 1.5 Гигабайта microSD (на самом деле менее 1 Гигабайта из-за неполного /boot, но будем честными до конца):
Для установки ПО 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 в режиме точки доступа.
Выясняем модель устройства и текущую версию прошивки:
Видим, что прошивка версии 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.
Ну и конечно же EPEL:
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-шников. К счастью, привести в порядок этот «параллельный хаос» оказывается простым, правда не всегда очевидным делом.
Создаем два виртуальных интерфейса-моста (bridge) с постоянными именами: lan и wan. К первому «подключим» Wi-Fi адаптер(ы), ко второму — eth0 «малинки».
IPForward=yes избавляет от необходимости через sysctl намекать ядру о включении маршрутизации.
MACAddress= раскомментируем и изменим при необходимости.
Сначала «подключаем» eth0. Помним о «проблеме единообразия» и используем только MAC адрес этого интерфейса, узнать который можно, например, так:
Удаляем предыдущий файл конфигурации eth0, перезагружаем «малинку» и получаем к ней сетевой доступ (IP адрес скорее всего изменится):
5. DNSMASQ
Для изготовления точек доступа Wi-Fi ничего лучше сладкой парочки из dnsmasq + hostapd еще не придумали. По моему мнению.
hostapd — это штука, которая управляет Wi-Fi адаптерами (в частности, возьмет на себя труд по их подключению к виртуальному lan «малинки»), авторизует и регистрирует беспроводных клиентов.
dnsmasq — настраивает сетевой стек клиентов: выдает IP-адреса, DNS-серверы, шлюз по умолчанию и тому подобные прелести.
Начинаем с dnsmasq:
редактируем его по своему вкусу.
«Магия» здесь заключается в параметре bind-dynamic, который указывает демону dnsmasq дожидаться появления в системе interface=lan, а не падать в обморок от приступа гордого одиночества после старта.
6. HOSTAPD
И наконец, волшебные конфигурации hostapd. Не сомневаюсь, что кто-то читает эту статью в поиске именно этих заветных строчек.
Перед установкой hostapd нужно побороться с «проблемой единообразия». Встроенный Wi-Fi адаптер wlan0 может легко изменить свое имя на wlan1 при подключении дополнительного USB Wi-Fi оборудования. Поэтому зафиксируем имена интерфейсов следующим способом: придумаем (беспроводным) адаптерам уникальные названия и привяжем их к MAC адресам.
Для встроенного Wi-Fi адаптера, который пока еще wlan0:
Теперь мы будем уверены, что 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 адаптера.
7. IPTABLES
«Шта. » © Да-да! Никакого systemd. Никаких новомодных комбайнов (в виде firewalld), которые в итоге делают одно и тоже.
Используем старый добрый iptables, службы которого после своего старта загрузят в ядро сетевые правила и спокойно завершат работу, не оставаясь резидентно и не потребляя ресурсов. У systemd есть элегантный IPMasquerade=, но трансляцию адресов (NAT) и файервол поручим все-таки iptables.
Конфигурацию 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:
Управлять новым Wi-Fi интерфейсом поручим отдельному демону hostapd, который будет запускаться и останавливаться в зависимости от наличия в системе строго определенного «свистка»: wl1.
Конфигурационный файл /etc/hostapd/hostapd2.conf:
Содержимое этого файла напрямую зависит от модели USB Wi-Fi адаптера, поэтому банальный copy/paste может вас подвести.
Копируем дистрибутивный service-файл в /etc/systemd/system/hostapd2.service:
и приводим его содержимое к следующему виду:
Осталось включить новый экземпляр hostapd:
Вот и все! Подергайте «свисток» и саму «малинку», посмотрите на беспроводные сети вокруг.
И напоследок хочу предупредить о качестве USB Wi-Fi адаптера и электропитания Raspberry. Подключенный «на горячую свисток», иногда может вызвать «зависание малинки» из-за кратковременных электрических неприятностей.