Домашний мини сервер из роутера

Размещаем сайт на домашнем роутере

Время на прочтение
7 мин

Количество просмотров 59K

Мне давно хотелось «потрогать руками» интернет-сервисы, настроив веб-сервер с нуля и выпустив его в Интернет. В этой статье хочу поделиться полученным опытом превращения домашнего роутера из узкофункционального устройства в практически полноценный сервер.

Началось всё с того, что служивший верой и правдой роутер TP-Link TL-WR1043ND перестал удовлетворять потребности домашней сети, захотелось 5ГГц диапазона и быстрого доступа к файлам на накопителе, подключенном к роутеру. Просмотрев профильные форумы (4pda, ixbt), сайты с отзывами и посмотрев на ассортимент местных магазинов — решил приобрести Keenetic Ultra.

В пользу именно этого устройства сработали хорошие отзывы владельцев:

  • отсутствие проблем с перегревом (тут пришлось отказаться от продукции Asus);
  • надежность в работе (тут вычеркнул TP-Link);
  • простота в настройке (побоялся не справиться и вычеркнул MikroTik).

Пришлось примириться с минусами:

  • нет WiFi6, хотелось взять оборудование с запасом на будущее;
  • 4 LAN порта, хотелось больше, но это уже не домашняя категория.

В итоге получилась вот такая «серверная»:

  • слева оптический терминал Ростелекома;
  • справа наш подопытный роутер;
  • проводом к роутеру подсоединен завалявшийся m.2 SSD на 128 ГБ, помещенный в коробку USB3 с алиэкспресса, сейчас он аккуратно закреплен на стенке;
  • на переднем плане удлинитель с независимым отключением розеток, провод от него идет к недорогому UPS;
  • на заднем плане пучок витой пары — на этапе ремонта квартиры сразу запланировал RJ45 розетки в местах предполагаемого размещения техники, чтобы не зависеть от замусоренности WiFi.

Итак, у нас есть оборудование, необходимо его настроить:

  • первичная настройка роутера занимает около 2 минут, указываем параметры подключения к провайдеру (у меня оптический терминал переключен в режим бриджа, PPPoE соединение поднимает роутер), название WiFi сети и пароль — в принципе всё, роутер запускается и работает.

Ставим переадресацию внешних портов на порты самого роутера в разделе «Сетевые правила — Переадресация»:

Теперь можно перейти к «продвинутой» части, чего я хотел от роутера:

  1. функционал небольшого NAS для домашней сети;
  2. выполнение функций веб-сервера для нескольких частных страничек;
  3. функционал персонального облака для доступа к личным данным из любой точки мира.

Первое реализуется встроенными средствами, не требуя особых усилий:

  • берем предназначенный для этой роли накопитель (флешку, карту памяти в картридере, жесткий диск или SSD во внешнем боксе и форматируем в Ext4 с помощью MiniTool Partition Wizard Free Edition (у меня нет компьютера с linux под рукой, там можно встроенными средствами). Как я понимаю, при работе система пишет на флешку только логи, поэтому, если их ограничить после настройки системы — можно использовать и карты памяти, если планируете много и часто писать на накопитель — лучше SSD или HDD.

После этого подключаем накопитель к роутеру и наблюдаем его на экране системного монитора

Переходим щелчком по «USB-диски и принтеры» в раздел «Приложения» и настраиваем общий ресурс в разделе «Сеть Windows»:

И у нас имеется сетевой ресурс, который можно использовать с компьютеров под Windows, подключив при необходимости как диск: net use y: \\192.168.1.1\SSD /persistent:yes

Скорость такого импровизированного NAS вполне достаточна для домашнего применения, по проводу он использует весь гигабит, по WiFi скорость составляет около 400-500 мегабит.

Настройка хранилища — один из необходимых шагов для настройки сервера, далее нам нужно:
— приобрести домен и статический IP адрес (можно обойтись и без этого, используя Dynamic DNS, но статический IP у меня уже был, поэтому проще оказалось воспользоваться бесплатными сервисами Яндекса — делегировав туда домен, мы получаем DNS-хостинг и почту на своем домене);

— настроить DNS сервера и добавить A-записи, указывающие на ваш IP:

Вступление в силу настроек делегирования домена и DNS занимает несколько часов, поэтому параллельно занимаемся настройкой роутера.

Для начала необходимо установить репозиторий Entware, из которого мы сможем ставить на роутер необходимые пакеты. Я воспользовался этой инструкцией, только не заливал установочный пакет по FTP, а создал папку прямо на подключенном ранее сетевом диске и скопировал туда файл обычным способом.

Получив доступ по SSH, меняем пароль командой passwd и ставим командой opkg install [имена пакетов] все нужные пакеты:

В ходе настройки на роутере оказались установлены следующие пакеты (результат вывода команды opkg list-installed):

Список пакетов

bash — 5.0-3
busybox — 1.31.1-1
ca-bundle — 20190110-2
ca-certificates — 20190110-2
coreutils — 8.31-1
coreutils-mktemp — 8.31-1
cron — 4.1-3
curl — 7.69.0-1
diffutils — 3.7-2
dropbear — 2019.78-3
entware-release — 1.0-2
findutils — 4.7.0-1
glib2 — 2.58.3-5
grep — 3.4-1
ldconfig — 2.27-9
libattr — 2.4.48-2
libblkid — 2.35.1-1
libc — 2.27-9
libcurl — 7.69.0-1
libffi — 3.2.1-4
libgcc — 8.3.0-9
libiconv-full — 1.11.1-4
libintl-full — 0.19.8.1-2
liblua — 5.1.5-7
libmbedtls — 2.16.5-1
libmount — 2.35.1-1
libncurses — 6.2-1
libncursesw — 6.2-1
libndm — 1.1.10-1a
libopenssl — 1.1.1d-2
libopenssl-conf — 1.1.1d-2
libpcap — 1.9.1-2
libpcre — 8.43-2
libpcre2 — 10.34-1
libpthread — 2.27-9
libreadline — 8.0-1a
librt — 2.27-9
libslang2 — 2.3.2-4
libssh2 — 1.9.0-2
libssp — 8.3.0-9
libstdcpp — 8.3.0-9
libuuid — 2.35.1-1
libxml2 — 2.9.10-1
locales — 2.27-9
mc — 4.8.23-2
ndmq — 1.0.2-5a
nginx — 1.17.8-1
openssl-util — 1.1.1d-2
opkg — 2019-06-14-dcbc142e-2
opt-ndmsv2 — 1.0-12
php7 — 7.4.3-1
php7-mod-openssl — 7.4.3-1
poorbox — 1.31.1-2
terminfo — 6.2-1
zlib — 1.2.11-3
zoneinfo-asia — 2019c-1
zoneinfo-europe — 2019c-1

Возможно, тут что-то лишнее затесалось, но места на накопителе много, поэтому разбираться не стал.

После установки пакетов настраиваем nginx, я пробовал с двумя доменами — на втором настроен https, и пока висит заглушка. 81 и 433 внутренние порты вместо 80 и 443 используются, поскольку на нормальных портах висят админки роутера.

etc/nginx/nginx.conf

user  nobody;
worker_processes  1;
#error_log  /opt/var/log/nginx/error.log;
#error_log  /opt/var/log/nginx/error.log  notice;
#error_log  /opt/var/log/nginx/error.log  info;
#pid        /opt/var/run/nginx.pid;

events {
    worker_connections  64;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  /opt/var/log/nginx/access.log main;
    sendfile        on;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;
    #gzip  on;

server {
    listen 81;
    server_name milkov.su www.milkov.su;
    return 301 https://milkov.su$request_uri;
}

server {
        listen 433 ssl;
        server_name milkov.su;
        #SSL support
        include ssl.conf;
        location / {
            root   /opt/share/nginx/html;
            index  index.html index.htm;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
            }
        }
}

etc/nginx/ssl.conf

ssl_certificate /opt/etc/nginx/certs/milkov.su/fullchain.pem;
ssl_certificate_key /opt/etc/nginx/certs/milkov.su/privkey.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
ssl_dhparam /opt/etc/nginx/dhparams.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_stapling on;

Для того, чтобы сайт работал по https, воспользовался известным скриптом dehydrated, установив его по этой инструкции. Затруднений этот процесс не вызвал, запнулся только на том, что в тексте скрипта для работы на моем роутере надо закомментировать строчку в файле /opt/etc/ssl/openssl.cnf:

[openssl_conf]
#engines=engines

И отмечу, что генерация dhparams.pem командой «openssl dhparam -out dhparams.pem 2048» на моем роутере занимает больше 2 часов, если бы не индикатор прогресса — потерял бы терпение и перезагрузил.

После получения сертификатов перезапускаем nginx командой «/opt/etc/init.d/S80nginx restart». В принципе на этом настройка закончена, но сайта еще нет — если положим в каталог /share/nginx/html файл index.html, увидим заглушку.

<!DOCTYPE html>
<html>
<head>
<title>Тестовая страничка!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Тестовая страничка!</h1>
<p>Это простая статическая тестовая страничка, абсолютно ничего интересного.</p>
</body>
</html>

Чтобы разместить информацию красиво, непрофессионалу типа меня проще воспользоваться готовыми шаблонами, после долгого перебора различных каталогов нашел templatemo.com — там неплохой выбор бесплатных шаблонов, не требующих обязательного указания авторства (что редкость в интернете, большая часть шаблонов в лицензии требуют сохранить ссылку на ресурс, откуда они получены).

Выбираем подходящий шаблон — там есть на самые разные случаи, скачиваем архив, и раcпаковываем его в каталог /share/nginx/html, делать это можно уже со своего компьютера, затем редактируем шаблон (тут потребуются минимальные знания HTML, чтобы не нарушить структуру) и заменяем графику, как показано на рисунке ниже.

Резюме: роутер вполне пригоден для размещения на нем легкого сайта, в принципе — если не предполагается большой нагрузки, можно поставить и php, и экспериментировать с более сложными проектами (смотрю на nextcloud/owncloud, вроде есть успешные установки на такое железо). Возможность установки пакетов поднимает его полезность — например, когда надо было защитить RDP порт ПК в локальной сети, поставил knockd на роутер — и проброс порта к ПК открывался только после port knocking.

Почему именно роутер, а не обычный PC? Роутер — одна из немногих компьютерных железяк, круглосуточно работающих во многих квартирах, домашний роутер обычно абсолютно бесшумен и легкий сайт с числом посещений в сутки меньше сотни его совершенно не напряжет.

Делаем из роутера минисервер. Часть 1 — установка Optware.

Маршрутизатор D-Link DIR-320 является довольно универсальным устройством. При соответствующей настройке из него можно получить Web-сервер, NAS (сетевое хранилище), прокси-сервер, баннерорезку, медиасервер, можно возложить на него функции управления другой техникой и многое другое.

Итак, дано:

  • Роутер D-Link DIR-320 с прошивкой Tomato v1.27;
  • 3G-модем Huawei E173 (совсем недавно был Huawei E1550);
  • Принтер Samsung ML-1641;
  • Жёсткий диск Toshiba MK3265GSX 320Гб во внешнем боксе;
  • USB-хаб D-Link DUB-H7.

Установка Optware

Для установки Optware понадобится любой флэш-накопитель или внешний жесткий диск.

  1. Форматируем флэшку в файловую систему ext3. Это можно сделать любыми доступными вам средствами: из Linux, загрузившись с Linux LiveCD и т.д.
  2. После этого создадим в корне накопителя папку «Optware».
  3. В админке роутера перейдём в раздел «USB and NAS — USB Support» и поставим все галочки.
  4. Подключим флэшку к роутеру. После перезагрузки она должна автоматически примонтироваться к файловой системе роутера в /mnt/имя_раздела .
  5. Подключимся к роутеру через Telnet или по SSH (рекомендую для этого PuTTY).

Введём команду «mount». Ищем подобную строчку:

/dev/discs/disc0/part1 on /tmp/mnt/system type ext3 (rw,noatime,nodev)

В данном случае system — это имя раздела накопителя.

  • Добавляем в админке роутера в поле «Run after mount» следующую команду (system заменить на ваше имя раздела):
mount -o noatime -t ext3 -obind /mnt/system/Optware /opt

Теперь раздел автоматически будет монтироваться в директорию /opt , которая необходима для Optware.

  • Перезагружаемся и проверяем, так ли это. Если нет, то смотрим где мы допустили ошибку.

В качестве накопителя можно использовать microSD карточку, вставленную в картридер 3G-модема.

Для монтирования флэшки, в данном случае, в поле «Script hotplug» (USB and NAS — USB Support) необходимо вписать следующий скрипт:

mkdir -p /tmp/mnt/sd
mount -o noatime /dev/discs/disc0/part1 /tmp/mnt/sd
if [ -d /mnt/sd ]; then
mount -o noatime -t ext3 -obind /mnt/sd/Optware /opt
fi

Если всё правильно, то настало время установить Optware. Для этого в консоли даём следующие команды:

wget http://wd.mirmana.com/optware-install-ddwrt2.sh -O - | tr -d '\r' > /tmp/optware-install.sh
sh /tmp/optware-install.sh

Теперь Optware установлено. Для управления пакетами программ служит утилита ipkg-opt.

Команды ipkg-opt

Обновление списка доступных программ:

# ipkg-opt update

Обновление всех установленных пакетов до актуальной версии:

# ipkg-opt upgrade

img

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

Просмотреть список всех пакетов:

# ipkg-opt list | more

Просмотреть список всех установленных пакетов:

# ipkg-opt list_installed | more

Установка пакетов:

# ipkg-opt install название_пакета

Удаление пакетов:

# ipkg-opt remove название_пакета

Скачать пакет (файл ipk):

# ipkg-opt download название_пакета

Установить ранее скачанный пакет (ipk):

# ipkg-opt install имя_файла.ipk

Получить информацию о пакете:

# ipkg-opt info название_пакета

img

Рекомендуемые для обязательной установки пакеты

  • coreutils — набор основных unix утилит
  • diffutils — набор unix утилит для работ по сравнению строк, текстов и т.д. (пригодится при написании скриптов)
  • man — для чтения мануалов по командам
  • mc — файловый менеджер Midnight Commander
  • nano — текстовый редактор
  • thttpd — web-сервер
  • transmission — торрент-клиент

Например, установим файловый менеджер Midnight Commander:

# ipkg-opt install mc

После этого необходимо задать переменные окружения. Для этого создадим (или отредактируем если он существует) файл /opt/etc/profile

#
# Bash initialization script
#

#PS1="[\u@\h \W]$ "
export PATH=/opt/sbin:/opt/bin:/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=/opt/lib:${LD_LIBRARY_PATH}
export HOSTNAME=`cat /proc/sys/kernel/hostname`

export SHELL="/opt/bin/bash"
export TERMINFO="/opt/share/terminfo"
export TERM="xterm"

# Раскоментируйте следующие строки чтобы включить русское меню в MC.
# У меня русский язык нормально работал только при подключении через Telnet под убунтой.

#export LC_ALL="ru_RU.KOI8-R"
#export LANG="ru_RU.KOI8-R"
#export LANGUAGE="ru_RU.KOI8-R"
#export LC_CTYPE="ru_RU.KOI8-R"
#export LC_NUMERIC="ru_RU.KOI8-R"
#export LC_TIME="ru_RU.KOI8-R"
#export LC_COLLATE="ru_RU.KOI8-R"
#export LC_MONETARY="ru_RU.KOI8-R"
#export LC_MESSAGES="ru_RU.KOI8-R"

После этого разорвём Telnet/SSH соединение и зайдём снова. Попробуем запустить Midnight Commander:

# mc

Во второй части статьи будет подробнее рассказано про скрипты.
Часть вторая

В прошлой статье было рассказано об аппаратной части самодельного сервера (роутера) и его конструкции. В этой статье я расскажу как установить и настроить операционную систему Raspberry Pi OS (GNU/Linux), подготовить программы для работы с сетью: ssh, iw, iptables, hostapd, isc-dhcp, wvdial, minicom.

Также, приведу простые скрипты на языке Python для вывода информации на дисплей SSD1306, воспроизведения звуковых сигналов, считывания информации с кнопок и другую полезную информацию.

Содержание:

  1. Структура сети и ее работа
  2. Подготовка Micro-SD карты с Raspbian
  3. Первое включение и базовая настройка Raspbian
  4. Подключение к сети и обновление ПО
  5. Установка необходимого программного обеспечения
  6. Оптимизация файловых систем
  7. Сетевые настройки и SSH
  8. Мощность передатчика Wi-Fi карты, регуляторный домен
  9. Настройка брандмауэра IPTables, роутинг и защита
  10. Беспроводная точка доступа (Access Point) на основе HOSTAPD
  11. Настройка демона ISC-DHCP-Server
  12. Решение проблемы старта isc-dhcpd и активации сетевых интерфейсов
  13. Настройка статического списка DNS-серверов
  14. Подготовка 3G-модема, узнаем его состояние используя minicom
  15. 3G-модем и консольная звонилка WVDIAL
  16. Режимы управления частотой CPU в Raspberry Pi и его температура
  17. Настройка часов реального времени (RTC)
  18. Считываем показания термодатчика DS18B20
  19. Генерация звуковых сигналов через пьезо-зуммер
  20. Управление RGB-светодиодом и реагирование на нажатия кнопок
  21. Вывод данных на OLED-дисплей
  22. Набор скриптов для управления
  23. Другие полезности
  24. Доработки, установка других сетевых служб, усложнение сети
  25. Устранение неполадок
  26. В завершение

Структура сети и ее работа

Поскольку наш самодельный мини-сервер будет выполнять роль сетевого маршрутизатора (роутер, router), то целесообразно предварительно спланировать структуру сети с использованием данного устройства.

Структура сети, управляемой самодельным маршрутизатором (роутером) построенном на основе Raspberry PI

Рис. 1. Структура сети, управляемой самодельным маршрутизатором (роутером) построенном на основе Raspberry PI.

Маршрутизатор может быть подключен к интернету используя один из каналов:

  1. Проводной, через USB-ethernet адаптер (интерфейс eth1);
  2. Беспроводный, через USB 3G адаптер (интерфейс ppp0).

Сетевые устройства могут быть подключены к маршрутизатору через следующие каналы:

  1. Проводной (eth0) — через сетевой свич (Ethernet switch): сервер, рабочая станция, ноутбук и т.п.
  2. Беспроводной (wlan0) — Wi-Fi: смартфон, планшет, ноутбук и другие беспроводные устройства.

USB-3G модем используется как резервный вариант в случае пропадания проводного канала, также возможно использовать его как основной канал.

Пропускная способность проводной сети составит 100Мбит/c. Она ограничена скоростью встроенного Ethernet-порта Raspberry Pi, USB-Ethernet адаптера, а также скоростью сетевого коммутатора.

Пропускная способность беспроводной сети может колебаться в значительных пределах и зависит от качества Wi-Fi сигнала между соединенными устройствами. Скорость интернета в варианте с 3G-модемом зависит от выбранного тарифа, уровня сигнала и возможностей самого модема.

В данном случае, внешние сетевые интерфейсы — это eth1 и ppp0, а внутренние — eth0 и wlan0.

Адреса для интерфейсов:

  • eth0 — 192.168.1.1 /24
  • wlan0 — 192.168.2.1 /24
  • eth1 — DHCP (получаем адрес от интернет-провайдера)
  • ppp0 — PPP (получаем адрес от интернет-провайдера)

Пулы адресов, зарезервированные для DHCP-сервера, который будет обслуживать внутренние LAN и WLAN сети:

  • eth0: 192.168.1.10 — 192.168.1.100
  • wlan0: 192.168.2.10 — 192.168.2.100

Остальные доступные адреса можно использовать для устройств со статическими сетевыми настройками или же чтобы обозначить какое-то конкретное устройство.

Например, можно выделить тестовому серверу легко запоминающийся адрес 192.168.1.111 (подключение по кабелю), а рабочему ноутбуку — 192.168.2.2 (подключение по Wi-Fi).

Все устройства из подсети 192.168.1.1/24 будут доступны для связи устройствам из подсети 192.168.2.1/24 и наоборот. Таким образом можно будет осуществлять коммуникацию между сетевыми устройствами, которые подключены к проводному и беспроводному (Wi-Fi) интерфейсам роутера.

Сетевые пакеты, проходящие через любой из интерфейсов ppp0 или eth1 (интернет-трафик), будут транслироваться с изменением их адресов (masquarade, NAT) для использования во внутренней сети.

Также, на этих интерфейсах выполним фильтрацию входящих пакетов и защиту от вторжений используя мощь iptables.

Есть еще важный нюанс: если у вас уже установлен интернет-маршрутизатор с IP-адресом в подсети 192.168.1.x то при подключении к нему малинового роутера для интерфейсов нужно будет выбрать и настроить подсети с другими номерами, например: для eth0 — 192.168.10.x., а для wlan0 — 192.168.20.x.

В интернет-маршрутизаторе уже могут быть задействованы подсети 192.168.1.x (для проводных подключений) и 192.168.2.x (для беспроводных, Wi-Fi), таким образом, выбрав другие номера подсетей для малинового роутера мы предотвратим конфликты в маршрутизации.

Ниже привожу рисунок со схемой, иллюстрирующей два варианта подключения самодельного роутера на основе Raspberry Pi к интернету:

  1. Напрямую к каналу интернет провайдера;
  2. Через домашний маршрутизатор.

Схемы подключения самодельного маршрутизатора к интернету - напрямую и через промежуточный роутер

Рис. 2. Схемы подключения самодельного маршрутизатора к интернету — напрямую и через промежуточный роутер.

Поскольку на малинке для сетевого интерфейса eth1 у нас будет настроен NAT (Network Adresses Translation, служба маскировки сетевых адресов), то (смотри рисунок 2):

  1. При прямом подключению к провайдеру, все узлы из его сети с IP-адресами вида 10.x.x.x не будут иметь доступа к устройствам вашей внутренней подсети;
  2. При подключении через домашний роутер «Home Router», все подключенные к нему устройства не смогут увидеть устройства, что подключены к интерфейсам малинки. Сети предоставляемые малинкой будут защищены от доступа со стороны устройств, что подключены к «Home Router». У вас получится такая себе «персональная подсеть», изолированная от основной домашней сети.

Как видите, структура сети совсем не сложная и достаточно универсальная. Вы можете выбрать удобные вам номера подсетей и настраивать конфигурацию всех служб как описано в статье но уже с учетом этих номеров.

Можем приступать к реализации схемы.

Подготовка Micro-SD карты с Raspbian

Раньше, в одной из статей, я уже подробно описывал процесс установки Raspbian на Micro-SD карту в операционных системах (ОС) Microsoft Windows и GNU/Linux, также там описаны нюансы подбора флешь-карточки и другиая полезная информация. Поэтому, здесь я лишь кратко распишу как установить Raspberry Pi OS (Raspbian).

Ищем подходящий нам архив с образом операционной системы на официальном сайте Raspberry Pi OS — https://www.raspberrypi.org/software/operating-systems/.

Там может быть несколько версий Raspberry Pi OS:

  • облегченная версия с минимумом необходимого ПО (Lite);
  • версия с ПО для графического рабочего стола (with desktop);
  • версия с графическим рабочим столом + дополнительное ПО;
  • и другие.

В данном случае, мною был скачан архив с максимально полным набором ПО — «2020-05-27-raspios-buster-full-armhf.zip» (2,5Гб), в котором запакован файл «2020-05-27-raspios-buster-full-armhf.img» (6,9Гб) — образ операционной системы Raspberry Pi OS (Debian 10 с кодовым названием Buster).

Выбрал я эту версию в целях эксперимента, для оценки набора предустановленных программ и возможностей, так как самодельный «роутер» иногда будет использоваться для подключения к монитору и для разных экспериментов. Для записи этого образа понадобится карта памяти с размером не менее чем на 16 ГБ (на 8 ГБ карту поместится, но свободного места останется мало).

Вы же можете использовать более малый по размеру образ с рабочим столом или же и вовсе облегченную версию.

Скачанный образ я сохранил его в папку «/home/master/Downloads» на своем рабочем Linux-ПК.

Установим на компьютере архиватор 7-Zip (для распаковки архива) и программу «pv» (для мониторинга за потоком данных):

sudo apt-get install p7zip-full pv

Распакуем архив:

cd /home/master/Downloads
7z x 2020-05-27-raspios-buster-full-armhf.zip

Установим Micro-SD карту в карт-ридер и узнаем название ее блочного устройства:

lsblk
sdX             8:32   1  14.5G  0 disk 
├─sdX1          8:33   1    56M  0 part 
└─sdX2          8:34   1  14.4G  0 part

Вместо «X» подставьте букву для своего полученного устройства и можно приступать к процессу записи образа ОС на карту памяти:

sudo pv 2020-05-27-raspios-buster-full-armhf.img | sudo dd of=/dev/sdX bs=4M

Запустим команду для сброса буферов записи и дождемся завершения ее работы:

sync

Теперь можно смело извлечь Micro-SD карту из карт-ридера и установить ее в компьютер Raspberry Pi.

Первое включение и базовая настройка Raspbian

Подключаем к нашему самодельному мини-серверу USB-клавиатуру и мышь (удобно использовать беспроводный комплект), к HDMI-выходу подключаем монитор. Включаем питание.

Дожидаемся загрузки графического интерфейса. При первом запуске будет предложено выбрать язык, временную зону и другие настройки — внимательно ознакомьтесь, в принципе все можно оставить пока что по умолчанию. На запрос обновления программного обеспечения отвечаем — Skip (пропустить).

Теперь запускаем программу «Терминал» (Консоль). В терминале запускаем конфигуратор малинки:

sudo raspi-config

Настройки по пунктам:

Change User Password — устанавливаем пароль доступа, желательно длиной от 8 и более символов с цифрами и буквами разного регистра.

Network options -> Hostname — меняем название системы, например на «myserver».

Boot options:

  • Desktop / CLI -> Text console, requiring user to login — отключаем запуск графической оболочки при старте системы, будет загружена консоль с запросом авторизации. В будущем для запуска графической среды достаточно будет выполнить команду «startx» из консоли.
  • Wait for Network at Boot -> Yes — ожидать завершения инициализации сетевой подсистемы при старте.
  • Splash Screen -> Would you like to show the splash screen at boot? -> No — не отображать заставку при старте.

Localisation Options -> Change Locale:

  • en_US.UTF-8,  ru_RU.CP1251, ru_RU.KOI8-R, ru_RU.UTF-8,  uk_UA.UTF-8, uk_UA.KOI8-R;
  • Default locale for the system environment -> en_US.UTF-8 — выбор системной локали по умолчанию, если желаете то можете выбрать украинскую или русскую.

Localisation Options -> Change Timezone — установка временной зоны, например Europe -> Kiev.

Localisation Options -> Change Keyboard Layout:

  • Generic 105-key (Intl) PC
  • English US
  • Key to function as AltGr -> The default for the keyboard
  • Compose key -> No compose key
  • Use Control+Alt+Backspace to terminate teh X server? -> No

Localisation Options -> Change Wi-fi Country — выбор страны для Wi-Fi, например «UA Ukraine». Очень важная настройка!

Interfacing options:

  • SSH -> Would you like the SSh server to be enabled? -> Yes — включаем SSH-службу для удаленного доступа к консоли по сети;
  • I2C -> Would you like the ARM I2C interface to be enabled?Yes — включаем I2C-шину для доступа к дисплею SSD1306 и часам реального времени DS1307;
  • 1-Wire -> Would you like the one-wire interface to be enabled?Yes — включаем 1-Wire шину для доступа к датчику температуры DS18B20.

Advanced options:

  • Expand filesystem — расширяем файловую систему ОС для использования всего доступного на Micro-SD карте пространства;
  • Memory Split -> 64 — выбираем количество оперативной памяти, выделяемое под графический адаптер. Значение 64МБ — оптимальное если планируется использовать графическую оболочку, в противном случае можно установить 32МБ или 16МБ.

Подключение к сети и обновление ПО

Для возможности удаленного доступа к малинке через SSH выполним первичную настройку проводной сети. Это позволит удобно выполнять настройки, копировать файлы и редактировать скрипты.

Подключим малинку к ноутбуку или рабочему ПК используя сетевой кабель и сетевой коммутатор. Можно также непосредственно подключить два устройства без сетевого коммутатора, в таком случае понадобится сетевой кабель RJ-45 c перевернутой разводкой проводов (сетевой кросс-кабель).

Вариант 1: [notebook |RJ-45>----кабель1----<RJ-45| Ethernet switch |RJ-45>----кабель2----<RJ-45| Raspberry Pi]
Вариант 2: [notebook |RJ-45>----кабель_кросс----<RJ-45| Raspberry Pi]

На ноутбуке (или ПК) установим статический IP-адрес — 192.168.1.2.

Начиная с Raspbian Stretch (Debian 9) статические настройки для сетевых интерфейсов прописываются в конфигурационном файле для DHCP клиента (DHCP Client Daemon) — «/etc/dhcpcd.conf». В более старых версиях ОС, например Raspbian Jessie (Debian 8) — это делалось с помощью файла «/etc/network/interfaces».

Теперь, присвоим интерфейсу eth0 на малинке сетевой адрес 192.168.1.1.  Для добавления настроек статической адресации откроем файл «dhcpcd.conf»:

sudo nano /etc/dhcpcd.conf

Добавляем в самый низ файла следующие строчки:

interface eth0
static ip_address=192.168.1.1/24

Выходим из редактора (CTRL+X), подтверждаем сохранение содержимого файла (Y + ENTER).

Выполним перезагрузку Raspbian:

sudo reboot

Проверяем есть ли связь на ноутбуке (ПК) с сетевым адресом 192.168.1.1, пробуем подключиться к Raspberry PI используя этот же адрес:

ping 192.168.1.1
ssh pi@192.168.1.1

Будет запрошен пароль для авторизации по SSH — мы установили его на этапе начальной конфигурации.

Теперь, подключившись к Raspberry Pi удаленно по SSH, можно отключить клавиатуру и мышь от мини-компьютера. Но прятать далеко их не стоит, они еще могут понадобиться в случае если не удастся выполнить подключение к малинке по SSH и для решения других возможных проблем в процессе настройки.

Подключаем USB-Ethernet адаптер к одному из свободных USB-портов самодельного роутера, также подключаем к этому же адаптеру сетевой кабель с интернетом от провайдера или модема/роутера.

USB-Ethernet адаптер должен автоматически определиться малинкой, а его интерфейс получит IP-адрес, сетевой шлюз (Gateway) и список DNS-серверов от провайдера интернета или домашнего роутера.

Смотрим список доступных сетевых интерфейсов и их конфигурацию, список активных сетевых маршрутов, а также список DNS-серверов, полученных по DHCP:

ip -c a
ip route
cat /etc/resolv.conf

 На малинке должен появиться интернет. Проверим доступен ли DNS-сервер Google:

ping 8.8.8.8

Осматриваем источники репозиториев, файлы и папки на наличие нежелательных:

ls -la /etc/apt/sources.list.d/
ls -la /etc/apt/trusted.gpg.d/
cat /etc/apt/sources.list

# Например, удяляем навязанный Microsoft репозиторий
# для VSCode и их ключ, которые пробовали "пропихнуть"
# в Raspberry Pi Foundation:
# https://old.reddit.com/r/linux/comments/lbu0t1/microsoft_repo_installed_on_all_raspberry_pis/
sudo rm /etc/apt/sources.list.d/vscode.list
sudo rm /etc/apt/trusted.gpg.d/microsoft.gpg
# Заблокируем хост с репозиторием от MS:
sudo echo "# Protecting from MS" >> /etc/hosts
sudo echo "127.0.0.1       packages.microsoft.com" >> /etc/hosts

Теперь можно выполнить обновление списков пакетов и обновить уже установленное программного обеспечение:

sudo apt-get update
sudo apt-get upgrade

Настроим автоматическую установку критических обновлений безопасности:

sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

На запрос последней команды отвечаем утвердительно — Yes.

Выполним принудительный запуск unattended-upgrades для проверки работоспособности:

sudo unattended-upgrades -d

На этом этапе желательно перезагрузить Raspberry Pi и повторно проверить работоспособность сети и интернета.

Установка необходимого программного обеспечения

Выполним установку необходимого для работы и функционирования программного обеспечения. Базовый набор инструментов:

sudo apt-get install mc htop p7zip-full lynx tmux
  • mc — Midnight Commander, консольный двухпанельный файловый менеджер;
  • htop — мониторинг производительности и ресурсов системы;
  • p7zip-full — мощный архиватор 7Zip;
  • tmux — Terminal Multiplexor, удобный мультифункциональный эмулятор терминалов.

Полезности для работы с USB-модемом:

sudo apt-get install usb-modeswitch usb-modeswitch-data wvdial ppp minicom
  • usb-modeswitch — набор скриптов для автоматического переключения режима работы модемов;
  • wvdial — программа дозвона для модема;
  • ppp — служба для поддержки протокола Point-to-Point;
  • minicom — терминал с возможностью подключения к последовательным портам.

Сетевые программы:

sudo apt-get install tcpdump nmap netdiag hostapd isc-dhcp-server
  • tcpdump — сниффер сетевых пакетов;
  • nmap — мощный сетевой сканер, легендарная программа;
  • netdiag — пакет, содержащий несколько полезных утилит, в особенности «trafshow» для мониторинга подключений;
  • hostapd — служба для создания беспроводной точки доступа IEEE 802.11 AP  и IEEE 802.1X/WPA/WPA2/EAP авторизатор ;
  • isc-dhcp-server — популярный DHCP сервер.

Мониторинг дисковых операций:

sudo apt-get install iotop sysstat
  • iotop — мониторинг операций ввода-вывода (I/O);
  • sysstat — набор утилит для мониторинга производительности в GNU/Linux.

Оптимизация файловых систем

Для работы малинки в качестве роутера можно провести ряд оптимизаций, которые снизят количество операций записи на карту. Можно отключить логирование для некоторых программ и демонов, отключить отслеживание времени последнего доступа к файлам, а также перенести некоторые разделы на TMPFS (файловая система в оперативной памяти).

Для того чтобы узнать какие программы выполняют интенсивный обмен данными с накопителем данных (картой памяти), можно использовать утилиту iotop:

sudo iotop -bktoqqq

Пояснение ключей запуска:

  • b — batch, включить не интерактивный режим;
  • k — отображать значения в Килобайтах;
  • t — показать временную метку для каждой строчки;
  • o — отобразить только активные процессы ввода-вывода;
  • qqq — не выводить суммарную информацию.

Увидим примерно следующую картину (фрагмент):

08:06:44    94 be/3 root        0.00 K/s   46.61 K/s  0.00 % 20.63 % [jbd2/mmcblk0p2-]
08:06:46   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.05 % [kworker/3:2]
08:06:48   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.05 % [kworker/3:2]
08:06:50   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.05 % [kworker/3:2]
08:06:52   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.05 % [kworker/3:2]
08:06:54   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.06 % [kworker/3:2]
08:06:55   537 be/4 root        0.00 K/s   11.13 K/s  0.00 %  0.00 % rsyslogd -n [rs:main Q:Reg]
08:06:56   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.06 % [kworker/3:2]
08:06:59   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.05 % [kworker/3:2]
08:07:01    94 be/3 root        0.00 K/s    7.41 K/s  0.00 %  1.88 % [jbd2/mmcblk0p2-]
08:07:01   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.06 % [kworker/3:2]
08:07:03   139 be/4 root        0.00 K/s    0.00 K/s  0.00 %  0.06 % [kworker/3:2]
08:07:03   537 be/4 root        0.00 K/s   14.83 K/s  0.00 %  0.00 % rsyslogd -n [rs:main Q:Reg]
08:07:03  1412 be/4 root        0.00 K/s    7.42 K/s  0.00 %  0.00 % sshd: pi [priv]

Также можно понаблюдать за суммарной статистикой ввода-вывода для накопителей данных, используя утилиту iostat:

iostat -dzp 5

Ключи запуска:

  • d — отобразить отчет об использовании устройств;
  • z — не выводить данные для неактивных устройств;
  • p — отображать все блочные устройства и их разделы;
  • 5 — интервал обновления.

Вывод программы будет иметь следующий вид:

Linux 4.9.35-v7+ (myserver)    24.08.17        _armv7l_        (4 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
mmcblk0           4,11       116,12        43,40     208752      78024
mmcblk0p1         0,05         1,12         0,00       2015          0
mmcblk0p2         4,04       114,78        43,40     206337      78024

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
mmcblk0           0,40         0,00         3,20          0         16
mmcblk0p2         0,40         0,00         3,20          0         16

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn

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

Перейдем непосредственно к оптимизациям, вот в чем они заключаются:

  • Отключаем операции записи временных меток доступа к папкам и файлам (noatime, nodiratime);
  • Переносим директории «/tmp», «/var/log», «/var/spool/mqueue» и «/var/tmp» в оперативную память (tmpfs);
  • Отключаем файл подкачки (swap).

Все эти меры помогут минимизировать количество операций записи на карту памяти.

Редактируем файл «fstab» с описанием всех монтируемых файловых систем:

sudo nano /etc/fstab

Для раздела с точкой монтирования «/» добавляем флаги «noatime,nodiratime», также добавляем строчки для монтирования директорий в файловую систему «tmpfs». Примерный вид файла «fstab»:

proc            /proc           proc    defaults          0       0
PARTUUID=afb93022-01  /boot           vfat    defaults  0       2
PARTUUID=afb93022-02  /               ext4    defaults,noatime,nodiratime  0       1
tmpfs    /tmp               tmpfs   nodev,nosuid,nodiratime,size=256M              0    0
tmpfs    /var/log           tmpfs   defaults,noatime,nosuid,mode=0755,size=50M     0    0
#tmpfs    /var/spool/mqueue  tmpfs   defaults,noatime,nosuid,mode=0700,size=20M     0    0
tmpfs    /var/tmp           tmpfs   defaults,noatime,nosuid,size=256M              0    0
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

С такой конфигурацией все системные логи, письма в очереди на отправку и временные файлы будут записываться в файловой системе, выделяемой из оперативной памяти, после выключения питания малинки вся эта информация будет безвозвратно утеряна.

Если нужно сохранять логи, или же временно включить их сохранение, то достаточно закомментировать строчку «tmpfs    /var/log…». Сейчас например закомментирована точка монтирования tmpfs для  директории /var/spool/mqueue.

Подобным образом можно поступить и с другими точками монтирования, а также если нужно добавить свои.

Еще один из вариантов хранения логов и другой статической информации — подключить и подмонтировать миниатюрный USB-флешь накопитель с размером памяти 2-8G.

Максимальные значения оперативной памяти, которые могут быть выделены для точек монтирования в приведенном случае:

  • /tmp  — 256M;
  • /var/log  — 50M;
  • /var/spool/mqueue  — 20M;
  • /var/tmp  — 256M.

В суме: 256 + 50 + 20 + 256 = 582(М).

Оперативная память в файловой системе tmpfs используется по мере необходимости, это значит что если в /tmp записать файл размером 10М, то при максимально допустимом размере файловой системы 256M реальной памяти будет использовано примерно 10М.

В Raspberry Pi 3 B установлено 1G оперативной памяти, поэтому если будут заполнены все файловые системы «tmpfs» (что маловероятно) то на все остальное останется примерно 400М.

В некоторых случаях (просмотр содержания больших архивов через mc, установка определенного ПО которое использует много места во временной файловой системе и т.п.) выделенной памяти в 256М для раздела /tmp может быть маловато.

Чтобы выйти из этой ситуации можно временно закомментировать строчку отвечающую за монтирвоание «tmpfs» для «/tmp», перезагрузить малинку и выполнить все нужные операции, а потом вернуть все как прежде. Также можно попробовать увеличить размер файловой системы с 256М до 512М.

Идем дальше. Осталось отключить и удалить файл подкачки:

sudo dphys-swapfile swapoff
sudo systemctl disable dphys-swapfile
sudo rm /var/swap

В случае неполадок или ошибок после редактирования файла «fstab» операционная система может быть загружена в однопользовательском режиме, нормальный режим загрузки станет недоступным.

Чтобы исправить записи в файле «fstab» нужно перемонтировать корневую файловую систему в режиме записи и отредактировать файл fstab:

mount -o,remount /
nano /etc/fstab

После внесения изменений перезагружаем малинку.

Сетевые настройки и SSH

Разрешим пересылку IPv4 пакетов между сетевыми интерфейсами, а также отключим сетевой протокол IPv6. Для домашней сети IPv6 избыточен, поэтому мы его использовать не будем.

Открываем для редактирования файл «/etc/sysctl.conf»:

sudo nano /etc/sysctl.conf

 Добавляем в самый низ его содержимого следующие строки:

# Network packets forwarding for IPv4
net.ipv4.ip_forward=1

# Disable IPv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Также включим защиту от некоторых сетевых атак с подменой данных (Spoofing attacks), для этого нужно раскомментировать две строчки в этом же файле:

# Spoofing attacks protection
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1

Добавим в файл «/etc/network/interfaces» настройки для поддержки «горячего» извлечения сетевых устройств, относящихся к интерфейсам wlan0(может быть USB-адаптер, например в малинке 2-й версии) и eth1(USB-адаптер). Также укажем что эти интерфейсы настраиваются вручную (их настройками будет управлять сконфигурированный нами сетевой демон DHCPCD).

sudo nano /etc/network/interfaces

Добавляем описания для интерфейсов:

allow-hotplug eth1
iface eth1 inet manual

allow-hotplug wlan0
iface wlan0 inet manual

Раньше нами уже был прописан статический IPv4-адрес для интерфейса eth0, осталось задать статический адрес для интерфейса беспроводной сети wlan0. Также нам нужно запретить использование механизма WPA-авторизации, что позже позволит использовать этот сетевой интерфейс для создания на его основе беспроводной точки доступа (Wireless Access Point).

sudo nano /etc/dhcpcd.conf

Заменяем ранее добавленные строчки для интерфейса eth0 следующим содержимым:

nohook wpa_supplicant

interface eth0
static ip_address=192.168.1.1/24

interface wlan0
static ip_address=192.168.2.1/24

Вы можете ознакомиться с назначением директив в файле «dhcpcd.conf» используя встроенную справочную систему:

man dhcpcd.conf

Перезагружаем малинку и смотрим статус службы dhcpcd:

sudo reboot
sudo systemctl status dhcpcd.service

Смотрим присвоены ли нужные нам статические IP-адреса для интерфейсов eth0 и wlan0:

ip -c a | grep  eth0 && ip -c a | grep  wlan0

Вы можете заметить что интерфейсу wlan0 не присвоен установленный нами IP-адрес, в действительности здесь все нормально — он появится позже, когда интерфейс будет инициализирован после настройки беспроводной точки доступа.

Фикс уязвимостей CVE-2016-0777 и CVE-2016-0778 для безопасности SSH-клиента:

sudo nano /etc/ssh/ssh_config

Добавить вниз файла строку:

UseRoaming no

В SSH-демоне по умолчанию включено выполнение DNS-запросов для получения имени удаленного хоста (который питается подключиться), эта возможность используется для того чтобы убедиться что обратное преобразование имени вернет идентичный IP-адрес, служит в целях безопасности. Следующий фикс ускорит SSH-подключения к нашему самодельному серверу из машин в локальной сети.

sudo nano /etc/ssh/sshd_config

Нужно найти (CTRL+W) и раскомментировать строку:

UseDNS no

Мощность передатчика Wi-Fi карты, регуляторный домен

В Raspberry Pi 3 (model B) встроен достаточно мощный модуль Wi-Fi. Мне нигде не удалось найти точных данных о выходной мощности беспроводного модуля для малинки, поэтому определил ее примерное значение экспериментально.

Значения мощности часто указывают по логарифмической децибельной шкале — в Децибелах (дБ, Decibel, dB). Если измерение выполняется относительно единицы мощности милливатт (мВт), то в децибеллах (дБ) это значение обозначается как «дБм» или «dBm» (0 dBm = 1mW).

Выходная мощность излучения беспроводного адаптера часто указывается и задается именно в dBm. Для простого перевода значений dBm в милиВатты можно воспользоваться следующей табличкой:

Значение, дБм Значение, мВт      Значение, дБм Значение, мВт
-1 0,8   21 125
0 1   22 160
1 1,259   23 200
2 1,6   24 250
3 1,995   25 320
4 2,5   26 400
5 3,2   27 500
6 3,981   28 640
7 5   29 800
8 6,4   30 1000
9 8   31 1250
10 10   32 1600
11 12,5   33 2000
12 16   34 2500
13 20   35 3200
14 25   36 4000
15 32   37 5000
16 40   38 6400
17 50   39 8000
18 64   40 10 000
19 80   50 100 000
20 100   60 1000 000

Увеличение мощности передатчика на 1dBm равносильно ее увеличению в 100,1 раза или примерно в 1,259 раза. Каждое прибавление 3 дБ к мощности увеличивает ее в два раза, например: 10дБ (10мВт) + 3дБ = 13дБ (20мВт) или 30дБ (1Вт) + 3дБ = 33дБ (2Вт) и т.д.

Текущую мощность передатчика (txpower, Transmit Power) для беспроводного модуля с сетевым интерфейсом wlan0 можно узнать используя команду:

iw wlan0 info

 Получим примерно следующую информацию:

Interface wlan0
        ifindex 3
        wdev 0x1
        addr b8:27:eb:6a:XX:XX
        ssid Raspberry-Pi
        type AP
        wiphy 0
        channel 6 (2437 MHz), width: 20 MHz, center1: 2437 MHz
        txpower 15.00 dBm

Здесь мы видим, что текущая выходная мощность передатчика (txpower) — 15 дБм, что равно 32мВт или 0,032Вт.

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

iw list

На экран будет выведено много разной информации: поддерживаемые алгоритмы шифрования и режимы интерфейса, список возможных скоростей для передачи данных, каналов с указанием частот, поддерживаемые команды и многое другое.

Сейчас нас наиболее интересует раздел «Frequencies»:

iw list | grep -A 15 Frequencies:

 В моем случае его вывод команды имеет следующий вид:

Frequencies:
  * 2412 MHz [1] (20.0 dBm)
  * 2417 MHz [2] (20.0 dBm)
  * 2422 MHz [3] (20.0 dBm)
  * 2427 MHz [4] (20.0 dBm)
  * 2432 MHz [5] (20.0 dBm)
  * 2437 MHz [6] (20.0 dBm)
  * 2442 MHz [7] (20.0 dBm)
  * 2447 MHz [8] (20.0 dBm)
  * 2452 MHz [9] (20.0 dBm)
  * 2457 MHz [10] (20.0 dBm)
  * 2462 MHz [11] (20.0 dBm)
  * 2467 MHz [12] (20.0 dBm)
  * 2472 MHz [13] (20.0 dBm)
  * 2484 MHz [14] (disabled)
Supported commands:

Здесь указаны 14 частот для 14-ти каналов, доступны из которых только 13 (14-й канал заблокирован, disabled). Выходная мощность для передатчика ограничена значением в 20 dBm (100 mW).

Выполняя базовую настройку Raspbian в разделе «Localisation Options -> Change Wi-fi Country» мы раньше установили страну для Wi-Fi — UA (Украина).

В каждой стане действуют свои правила и ограничения по использованию частот и беспроводного сетевого оборудования. Для большинства стран мира доступны каналы 1-13, а 14-й канал недоступен к использованию, исключением здесь является Япония, где в некоторых режимах работа на 13-м канале все же возможна. Для соединенных штатов доступны каналы 1-11.

Для реализации правил использования частот при работе с сетевым оборудованием в разных странах используются регуляторные домены.

Регуляторный домен (Regulatory Domain, regdomain) — это специальный набор правил, специфичный для каждой страны, который регулирует использование частот, может ограничивать мощность радиопередатчика, не допускать использование некоторых технологий и возможностей при передаче данных в беспроводных сетях.

При работе с регуляторными доменами в GNU/Linux используется CRDA (Central Regulatory Domain Agent). Чтобы узнать правила и ограничения регуляторного домена для вашей страны можно воспользоваться публичной базой данных — 

https://www.kernel.org/pub/software/network/wireless-regdb/

Скачиваем самый свежий архив, открываем файл «db.txt» и ищем там индекс своей страны. Пример для Украины:

country UA: DFS-ETSI
	(2400 - 2483.5 @ 40), (20), NO-OUTDOOR
	(5150 - 5250 @ 80), (20), NO-OUTDOOR, AUTO-BW
	(5250 - 5350 @ 80), (20), DFS, NO-OUTDOOR, AUTO-BW
	(5490 - 5670 @ 160), (20), DFS
	(5735 - 5835 @ 80), (20)
	# 60 GHz band channels 1-4, ref: Etsi En 302 567
	(57000 - 66000 @ 2160), (40)

Там же найдете ссылки на регуляторные документы своей страны и другую полезную информацию.

Чтобы узнать какой регуляторный домен используется в текущий момент на малинке, достаточно выполнить следующую команду:

iw reg get

В моем случаем вывод команды будет почти идентичным (за исключением комментария), как и в примере из файла «db.txt» для Украины. Здесь видно что для диапазона частот 2400 — 2483(МГц) выходная мощность передатчика ограничивается значением 20dBm (100 мВт).

В данном случае, попытка установить мощность передатчика выше 20dBm, скорее всего, не даст практического результата — мощность будет ограничиваться текущим регуляторным доменом (ядром ОС, использующим этот набор правил).

Для установки или смены регуляторного домена в GNU/Linux применяется следующая команда:

sudo iw reg set UA

Здесь вместо «UA» может быть «US», «VE» или другой код страны. Сменив регуляторный домен, мы сменим правила, по которым ядро ОС применяет ограничения при использовании беспроводных сетевых устройств.

Есть регуляторные домены, в которых для некоторых частот запрещено использовать режим точки доступа (AP, Access Point), поэтому нужно с ответственностью и пониманием отнестись к установке этой опции.

Чтобы обойти ограничение на 20dBm, в моем случае можно выбрать регуляторный домен «VE» и изменить мощность передатчика в большую сторону — 30dBm, но это уже будет нарушением правил по использованию частот для моей страны. К тому же, мне не нужна такая большая мощность, даже наоборот — мы будем ее снижать, зачем нам лишнее излучение вокруг нас.

Установить мощность Wi-Fi передатчика для интерфейса wlan0 можно следующей командой:

sudo iwconfig wlan0 txpower 10

В данном случае «10» — это значение мощности в дБм (dBm), которое равно 10мВт. Такой мощности может вполне хватить чтобы покрыть беспроводной сетью небольшую комнату, в которой расположен роутер.

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

Мы же заставим эту команду выполняться при готовности сетевого интерфейса, в файле «/etc/network/interfaces». Там же можно и добавить команду установки регуляторного домена, если нужно. Откроем этот файл в редакторе:

sudo nano /etc/network/interfaces

Добавим секцию из двух строчек для интерфейса wlan0, настройки получат следующий вид:

allow-hotplug wlan0
iface wlan0 inet manual
    up iw reg set UA
    up iwconfig wlan0 txpower 10

Статический IP-адрес для этого интерфейса мы уже раньше указали в файле «/etc/dhcpcd.conf», поэтому здесь ничего больше добавлять не нужно.

Перезагружаем малинку и смотрим установилась ли нужная мощность передатчика и нужный регуляторный домен:

sudo reboot
iw wlan0 info
iw reg get

Настройка брандмауэра IPTables, роутинг и защита

С помощью IPTables мы будем выполнять следующие задачи:

  • Разрешим пересылку сетевых пакетов между внутренними подсетями (интерфейсы eth0, wlan0);
  • Выполним трансляцию сетевых пакетов (NAT, masquarade) через интерфейсы, которые выходят в интернет (ppp0, eth1);
  • Разрешим подключение к роутеру через внутренние интерфейсы eth0, wlan0 используя порт 22 (SSH);
  • Разрешим все входящие пакеты, относящиеся к уже установленным подключениям (для цепочек INPUT и FORWARD);
  • Запретим все остальные входящие соединения на любом из сетевых интерфейсов;
  • Ограничим возможность сканирования роутера с использованием TCP-пакетов со специальными флагами.

Это достаточно жесткая политика, тем не менее, она позволит неплохо защитить ваш роутер. Вы сможете устанавливать исходящие соединения и принимать входящие, которые относятся к уже установленным исходящим, использовать интернет, свободно работать с сетевыми устройствами во внутренней сети.

На роутере будет открыт для подключения только порт 22 (SSH, для администрирования), все остальные попытки «достукаться» до роутера со стороны провайдера или другого промежуточного маршрутизатора (через интерфейсы eth1, ppp0) будут бесполезны. Ваш роутер не смогут даже «пропинговать» (командой ping) снаружи, поскольку будут отсекаться все ICMP-пакеты.

Если же вам не нужна такая жесткая политика, то вы можете настроить брандмауэр на свое усмотрение, исправив, добавив или удалив какие-то из правил.

Для построения набора правил IPTables в Raspbian можно использовать пакет «iptables-persistent», который при каждом старте ОС будет выполнять загрузку правил брандмауэра с ранее сохраненной конфигурацией.

Я же предлагаю использовать отдельный скрипт, который будет загружаться системой через systemd. В одной из статей я приводил скрипт IPTables для ipv4 и ipv6 с автозагрузкой в Linux, здесь будет использована немного упрощенная (без IPv6) и модифицированная версия этого скрипта.

Создаем файл скрипта с будущими правилами, откроем его для редактирования:

sudo nano /usr/local/sbin/systemd-iptables.sh

Вставляем в окно редактора следующий код:

#!/bin/sh
# IPTables init script for systemd
# Project: Raspberry Pi Router
# by ph0en1x - https://ph0en1x.net

IPT=/sbin/iptables

ETH=eth0
WLAN=wlan0
PPP=ppp0
ETH_EXT=eth1

# Flush active rules, flush custom tables, and set default policy
Flush_Rules () {
	$IPT --flush
	$IPT -t nat --flush
	$IPT -t mangle --flush
	$IPT --delete-chain
	$IPT -t nat --delete-chain
	$IPT -t mangle --delete-chain
	# Set default policies to ACCEPT
	$IPT -P INPUT ACCEPT
	$IPT -P FORWARD ACCEPT
	$IPT -P OUTPUT ACCEPT
}

# Loading rules
Load_Rules () {
        # Flush
        Flush_Rules
        # DEFAULT POLICIES
        $IPT -P INPUT DROP
        $IPT -P FORWARD DROP
        $IPT -P OUTPUT ACCEPT

        # PASS localhost traffic
        $IPT -A INPUT  -i lo -j ACCEPT
        $IPT -A OUTPUT -o lo -j ACCEPT

        # ALLOW traffic from already established connections
        $IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
        # ALLOW local connections to router via SSH
        $IPT -A INPUT -p tcp --dport 22 -i $ETH -j ACCEPT
        $IPT -A INPUT -p tcp --dport 22 -i $WLAN -j ACCEPT
        # DROP all other incoming connections
        $IPT -A INPUT -j DROP

        # ALLOW packets forwarding between internal networks
        $IPT -A FORWARD -i $ETH -o $WLAN -j ACCEPT
        $IPT -A FORWARD -i $WLAN -o $ETH -j ACCEPT
        # ALLOW packets forwarding between local net and internet
        $IPT -A FORWARD -i $PPP -o $ETH -m state --state RELATED,ESTABLISHED -j ACCEPT
        $IPT -A FORWARD -i $ETH -o $PPP -j ACCEPT
        $IPT -A FORWARD -i $PPP -o $WLAN -m state --state RELATED,ESTABLISHED -j ACCEPT
        $IPT -A FORWARD -i $WLAN -o $PPP -j ACCEPT
        
        $IPT -A FORWARD -i $ETH_EXT -o $ETH -m state --state RELATED,ESTABLISHED -j ACCEPT
        $IPT -A FORWARD -i $ETH -o $ETH_EXT -j ACCEPT
        $IPT -A FORWARD -i $ETH_EXT -o $WLAN -m state --state RELATED,ESTABLISHED -j ACCEPT
        $IPT -A FORWARD -i $WLAN -o $ETH_EXT -j ACCEPT

        # DROP all other forwarding traffic
        $IPT -A FORWARD -j DROP 

        # DROP ports scanning traffic
        $IPT -N PORT-SCAN
        $IPT -A PORT-SCAN -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j RETURN
        $IPT -A PORT-SCAN -j DROP

        # NAT for external interface
        $IPT -t nat -A POSTROUTING -o $PPP -j MASQUERADE
        $IPT -t nat -A POSTROUTING -o $ETH_EXT -j MASQUERADE
}


case $1 in
	start)
		Load_Rules
		echo "IPTables rules loaded."
		;;
	stop)
		Flush_Rules
		echo "IPTables rules flushed."
		;;
	restart)
		Flush_Rules
		Load_Rules
		echo "IPTables rules reloaded."
		;;
	*)
		echo "Usage: systemctl {start|stop|restart} iptables.service"
		exit 1
esac

exit 0

В начале скрипта указаны названия задействованных интерфейсов:

  • ETH — проводной сетевой интерфейс (внутренняя сеть)
  • WLAN — беспроводной (Wi-Fi) сетевой интерфейс (внутренняя сеть)
  • PPP — беспроводной (USB-3G) сетевой интерфейс (Internet)
  • ETH_EXT — проводной сетевой интерфейс (Internet)

В самом начале статьи была приведена схема сети с использованием будущего роутера на основе малинки, не ленитесь еще раз на нее взглянуть чтобы более четко понять структуру сети и работу скрипта с правилами IPTables.

В процедуре «Flush_Rules» выполняется очистка правил для всех цепочек брандмауэра, установка разрешающей (ACCEPT) сетевой политики для всех цепочек. Процедура «Load_Rules» выполняет загрузку прописанных нами правил с указанием различных опций и цепочек фильтрации.

В конце, с помощью конструкции «case $1 in», выполняется анализ и применение переданной скрипту команды (start, stop, restart), запускаются выше указанные процедуры «Flush_Rules» и «Load_Rules в нужном порядке.

Чтобы скрипт можно было запускать на исполнение, его файлу нужно дать соответствующие права:

sudo chmod +x /usr/local/sbin/systemd-iptables.sh

Теперь вы можете вручную запустить, остановить, перезапустить скрипт и оттестировать функционал его правил:

sudo /usr/local/sbin/systemd-iptables.sh start
sudo /usr/local/sbin/systemd-iptables.sh stop
sudo /usr/local/sbin/systemd-iptables.sh restart

Когда скрипт готов, можно приступать к созданию специального юнита для systemd, который будет выполнять автозапуск скрипта при старте ОС.

sudo nano /etc/systemd/system/iptables.service

Содержимое файла будет таким:

[Unit]
Description=IPTables rules
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/systemd-iptables.sh start
ExecStop=/usr/local/sbin/systemd-iptables.sh stop
ExecReload=/usr/local/sbin/systemd-iptables.sh restart
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Разрешим использование новосозданного юнита демоном systemd:

sudo systemctl enable iptables.service

Дадим юниту команду на старт, проверим состояние таблиц IPTables:

sudo systemctl start iptables.service
sudo systemctl status iptables.service
sudo iptables -nvL

Также можно вывести список уже загруженных в IPTables правил в более удобном виде, с нумерацией строк:

sudo iptables -t filter --list --line-numbers
sudo iptables -t nat --list --line-numbers

Беспроводная точка доступа (Access Point) на основе HOSTAPD

Поскольку наш роутер будет предоставлять возможность подключения к нему по Wi-Fi, давайте выполним настройку отвечающей за это службы  hostapd.

Hostapd (Host Access Point Daemon) — это демон, работающий в фоновом режиме и отвечающий за организацию беспроводной сетевой точки доступа стандарта IEEE 802.11 на основе имеющегося Wi-Fi адаптера с поддержкой этого режима. Также это демон берет на себя функции авторизации клиентов и выполняет другую связанную работу.

  • https://w1.fi/hostapd/ — страничка программы на официальном сайте
  • https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf — описание опций конфигурационного файла (набор впечатляет).

Чтобы убедиться что сетевой Wi-Fi адаптер малинки поддерживает режим точки доступа (Access Point, AP), выведем еще раз, как в разделе о настройке мощности передатчика, информацию о беспроводных интерфейсах:

iw list

Смотрим секцию «Supported interface modes», в моем случае ее содержимое выглядит вот так:

Supported interface modes:
  * IBSS
  * managed
  * AP
  * P2P-client
  * P2P-GO
  * P2P-device

Как видим, режим «AP» присутствует, значит можно продолжать.

Пакет «hostapd» уже был ранее нами установлен, на этапе установки необходимого программного обеспечения. Приступаем к настройке. Открываем для редактирования конфигурационный файл демона hostapd: 

sudo nano /etc/hostapd/hostapd.conf

Приводим его содержимое к такому виду:

interface=wlan0

driver=nl80211

ssid=JohnX-Pi

# Use the 2.4GHz band
hw_mode=g

channel=6

# Enable 802.11n
ieee80211n=1

wmm_enabled=1

# Enable 40MHz channels with 20ns guard interval
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]

# Accept all MAC addresses
macaddr_acl=0

# Use WPA authentication
auth_algs=1

# Require clients to know the network name
ignore_broadcast_ssid=0

wpa=2

wpa_key_mgmt=WPA-PSK

wpa_passphrase=SUP3R_PASSW00RD*#12

# Use AES, instead of TKIP
rsn_pairwise=CCMP

# 0 - disabled
wps_state=0

Это минимальный набор опций для организации беспроводной точки доступа. Опции которые вам следует изменить на свое усмотрение:

  • «ssid=JohnX-Pi» — здесь указано название будущей точки доступа, вместо «JohnX-Pi» укажите свое название, используйте по возможности символы A-Z0-9 и дефис. В названии допустимо использование всего арсенала символов из кодировки UTF-8 если добавить в конфигурационный файл опцию «utf8_ssid=1», правда отображаться на некоторых устройствах такие имена могут не корректно;
  • «channel=6» — номер канала, на котором будет осуществляться обслуживание беспроводной сети, выберите наименее загруженный в своей местности или здании;
  • «wpa_passphrase=SUP3R_PASSW00RD*#12» — пароль для доступа к беспроводной сети. Установите сложный и надежный пароль, с использованием 10-20 символов, включая буквы, цифры и специальные знаки.

 Укажем путь к используемому конфигурационному файлу для демона hostapd:

sudo nano /etc/default/hostapd

Нужно расскомментировать строчку «DAEMON_CONF=» и указать в ней путь к файлу hostapd.conf:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

Перезапускаем службу hostapd и смотрим ее статус после запуска:

sudo systemctl restart hostapd
sudo systemctl status hostapd

В новых версиях Raspbian эта служба по умолчанию скрыта (masked). Поэтому после попытки запустить hostapd вы можете получить сообщение об ошибке:

Failed to start hostapd.service: Unit hostapd.service is masked.

В данном случае нужно разблокировать службу и запустить ее, делается это следующими командами:

sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd
sudo systemctl status hostapd

Теперь можно попробовать подключиться к точке доступа, используя ноутбук или смартфон, правда ни одно из устройств не получит сетевых настроек, потому что нужно еще настроить сервер DHCP.

Настройка демона ISC-DHCP-Server

Раньше мы уже выполнили установку пакета «isc-dhcp-server».

ISC DHCP Server (Internet Systems Consortium Dynamic Host Configuration Server) — это программа, работающая в фоновом режиме (служба, демон), которая отвечает за автоматическую выдачу сетевых настроек для разных устройств.

  • https://www.isc.org/ — официальный сайт Internet Systems Consortium

Документация по ISC DHCP Server доступна во встроенной справочной системе GNU/Linux, используем команды «man»:

man dhcpd
man dhcpd.conf

Планируя структуру сети в начале статьи мы уже определились с пулами адресов для сетевых интерфейсов, которыми будет орудовать DHCPD:

  • eth0: 192.168.1.10 — 192.168.1.100
  • wlan0: 192.168.2.10 — 192.168.2.100

Открываем для редактирования конфигурационный файл DHCP сервера — dhcpd.conf (не путать с dhcpcd.conf для DHCP клиента):

sudo nano /etc/dhcp/dhcpd.conf

Укажем что этот DHCP-сервер будет официальным в сети, для этого ищем строчку «#authoritative;» и раскомментируем ее, убрав значек решотки:

authoritative;

Добавляем в самый низ файла две секции с описанием параметров выдачи адресов и настроек для подсетей:

subnet 192.168.1.0 netmask 255.255.255.0 {
 range 192.168.1.10 192.168.1.100;
 option broadcast-address 192.168.1.255;
 option routers 192.168.1.1;
 default-lease-time 600;
 max-lease-time 7200;
 option domain-name "local-network";
 # OpenDNS
 option domain-name-servers 208.67.222.222, 208.67.220.220;
}
 
subnet 192.168.2.0 netmask 255.255.255.0 {
 range 192.168.2.10 192.168.2.100;
 option broadcast-address 192.168.2.255;
 option routers 192.168.2.1;
 default-lease-time 600; 
 max-lease-time 7200;
 option domain-name "local-network";
 # OpenDNS
 option domain-name-servers 208.67.222.222, 208.67.220.220;
}

Также, по желанию, можно привязать какой-либо фиксированный IP-адрес к какому-то устройству по его MAC-адресу. Например, сделаем так, чтобы тестовый лептоп с мак-адресом сетевой карты «00:0c:12:b6:f2:c8» всегда получал IP-адрес «192.168.1.55», для этого добавим в конец файла «dhcpd.conf» еще одну секцию:

host TEST-LAPTOP {
  hardware ethernet 00:0c:12:b6:f2:c8;
  fixed-address 192.168.1.55;
}

По завершению редактирования конфигурационного файла DHCPD выполним проверку его синтаксиса:

sudo dhcpd -t

Если нет никаких предупреждений и указаний о наличии ошибок — значит все отлично!

По умолчанию DHCPD будет пробовать работать на всех доступных сетевых интерфейсах — нам это не нужно, поскольку eth1 у нас подключен к интернету и с ним уже работает служба DHCP клиента — dhcpcd.

Поэтому укажем DHCP серверу работать только с интерфейсами eth0 и wlan0:

sudo nano /etc/default/isc-dhcp-server

Прописываем названия интерфейсов для IPv4 через пробел:

INTERFACESv4="eth0 wlan0"
INTERFACESv6=""

Запускаем службу и смотрим ее состояние:

sudo systemctl start isc-dhcp-server
sudo systemctl status isc-dhcp-server

Наблюдать за всеми событиями служб DHCP сервера и клиента можно с помощью следующей команды:

cat /var/log/daemon.log | grep dhcp

DHCP сервер от ISC сохраняет внутреннюю базу данных о выданных когда-либо адресах и параметрах подключаемых устройств, эту информацию удобно использовать как для отладки, так и в других целях. Посмотреть файл базы данных можно командой:

less /var/lib/dhcp/dhcpd.leases

Содержимое и структура этого файла хорошо описаны во встроенной справочной системе:

man dhcpd.leases

Теперь можно попробовать подключить к роутеру другие сетевые устройства и убедиться что они получают корректные сетевые настройки.  Подключенному устройству будут назначены следующие адреса:

  • IP-адрес с подсетью 192.168.1.ххх для проводного подключения и с подсетью 192.168.2.ххх для беспроводного;
  • Шлюз (Gateway) 192.168.1.1 для проводного подключения и 192.168.2.1 для беспроводного;
  • Публичные DNS-сервера от OpenDNS (208.67.222.222, 208.67.220.220).

Подключив к USB-разъему малинки USB-Ethernet адаптер, который в свою очередь подключен сетевым кабелем к другому маршрутизатору с DHCP-сервером на борту или же интернет-провайдеру, мы получим работающий интернет как на малинке, так и на подключенных к ней сетевых устройствах.

Маршрутизатор на основе Raspberry Pi должен уже работать.

Решение проблемы старта isc-dhcpd и активации сетевых интерфейсов

После нескольких перезапусков роутера на основе малинки вы можете столкнуться с проблемой, когда подключаемые к нему сетевые устройства не могут получить сетевых настроек (IP, Gateway, DNS) по протоколу DHCP.

Причина этому — запуск демона DHCPD, прежде чем сетевые интерфейсы станут активными и получат указанные нами в настройках DHCPCD статические IP-адреса.

Смотрим логи системы с момента ее запуска:

journalctl -b

Там можно встретить следующие предупреждения для сетевых интерфейсов (пример для eth0):

No subnet declaration for eth0 (no IPv4 addresses).
** Ignoring requests on eth0.  If this is not what
    you want, please write a subnet declaration
    in your dhcpd.conf file for the network segment
    to which interface eth0 is attached. **
 
Not configured to listen on any interfaces!

If you think you have received this message due to a bug rather
than a configuration issue please read the section on submitting
bugs on either our web page at www.isc.org or in the README file
before submitting a bug.  These pages explain the proper
process and the information we find helpful for debugging..

exiting.

Это означает, что в конфигурационном файле «dhcpd.conf» нет описания подходящей зоны для сетевого интерфейса eth0 с IP-адресом и подсетью которые ему назначены на данный момент. Поэтому обслуживание этого интерфейса будет игнорироваться.

По сути, интерфейс eth0 еще не успел получить статический IP-адрес и подсеть, указанный в настройках DHCPCD. Такое же предупреждение появится и для второго интерфейса — wlan0.

Для решения проблемы можно попробовать переназначить приоритеты для запуска служб, то есть запускать DHCPD на более позднем этапе загрузки, после инициализации DHCPCD и сетевой подсистемы в целом.

На форуме raspberrypi.org нашел описание решения подобной проблемы, заключается оно в создании копии юнит-файла «isc-dhcp-server.service» для systemd, с указанием дополнительных опций «Restart=on-failure» и «RestartSec=5», что позволило бы при неудачном старте или сбое (failure) демона «isc-dhcp-server» выполнить его автоматический перезапуск через 5 секунд.

Подобное решение мне показалось интересным, но оно не заработало, и вот почему… Предупреждение в логах системы гласит что в файле «dhcpd.conf» отсутствует описание зоны для закрепленной за интерфейсом подсети. Интерфейс еще не успел получить настройки от DHCPCD, поэтому он просто игнорируется службой DHCPD.

Сама же служба DHCPD при этом не «падает» (failure) и продолжает работать, выводя в системный лог предупреждение (warning). Таким образом, опция «Restart=on-failure» в юнит-файле проблему не решит.

К тому же, подобное копирование и изменение системного юнит-файла «isc-dhcp-server.service» может привести в будущем к проблемам при получении обновлений для пакета isc-dhcp-server.

Решил разобраться с этой проблемой по своему — создать сторожевого песика (Watchdog), являющего из себя скрипт, который будет запущен при старте системы и проследит за получением сетевых адресов на указанных интерфейсах, после этого выполнит перезапуск службы «isc-dhcp-server».

Открываем для редактирования новый файл:

sudo nano /usr/local/sbin/systemd-isc-watchdog.sh

Вставляем в него следующий код:

#!/bin/bash
# Waiting for interfaces assigning IP, than restarting isc-dhcp-server.
# https://ph0en1x.net

declare -A INTERFACES
INTERFACES=(
  [eth0]="192.168.1.1"
  [wlan0]="192.168.2.1"
)

for i in "${!INTERFACES[@]}"
do
  # wait until interface accepts IP
  for ((n=0; n < 60; n++))
  do
    has_ip=`ip a show "$i" | grep "inet ${INTERFACES[$i]}"`
    if [ ! -z "$has_ip" ]; then
      echo "ISC_Watchdog: interface $i ready."
      break
    fi
    sleep 1
  done
done
sleep 15
echo "ISC_Watchdog: restarting isc-dhcp-server..."
systemctl restart isc-dhcp-server
exit 0

Скрипт работает следующим образом:

  • запускается при старте ОС отдельно созданным для systemd юнит-файлом;
  • проходит в цикле через каждую пару [название_интерфейса]=IP из массива INTERFACES;
  • для каждого интерфейса делается 60 проверок наличия нужного IP-адреса с таймаутом 1 секунда;
  • после завершения проверок ждет 15 секунд и перезапускает isc-dhcp-server;

Таким образом, проверка с ожиданием может длиться максимум 60+60 секунд, после этого в любом случае через 15 секунд DHCPD будет перезапущен.

Здесь важно указать верные IP-адреса для сетевых интерфейсов eth0 и wlan0. Если планируется использовать еще какой-то сетевой интерфейс для внутренней сети (например eth2), обслуживаемый DHCPD и получивший IP-адрес (например 192.168.10.1) через DHCPCD, то его также можно добавить в массив строчкой «[eth2]=»192.168.10.1».

Дадим файлу скрипта право на запуск и откроем для редактирования новый файл с юнитом для systemd:

sudo chmod +x /usr/local/sbin/systemd-isc-watchdog.sh
sudo nano /etc/systemd/system/isc-watchdog.service

Поместим в него следующее содержимое:

[Unit]
Description=Watchdog for isc-dhcp-server.
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/systemd-isc-watchdog.sh
RemainAfterExit=no

[Install]
WantedBy=multi-user.target

Разрешим обработку юнита при старте ОС:

sudo systemctl enable isc-watchdog.service

На всякий случай, можно еще добавить периодический перезапуск демона через crontab, откроем файл системного планировщика заданий для редактирования:

sudo nano /etc/crontab

Добавим строчку с новым заданием:

# Restart ISC DHCP-server
1  *    * * *   root    /bin/systemctl restart isc-dhcp-server

Таким образом мы настроили перезапуск демона isc-dhcp-server в начале каждого часа (период 60 минут).

Настройка статического списка DNS-серверов

Список DNS-серверов, используемых системой, как правило содержится в файле «/etc/resolv.conf». По умолчанию, содержимое этого файла в Raspbian автоматически генерируется при запуске системы и может быть изменено различными службами (например DHCPCD, PPP и другими).

При подключении сетевого кабеля от провайдера интернета к USB-Ethernet адаптеру с интерфейсом eth1, этому интерфейсу будет присвоен IP-адрес от провайдера, в системе будет установлен маршрут по умолчанию (Default Route) с указанием шлюза провайдера, а также в файл «/etc/resolv.conf» будет помещен список DNS-серверов. Все эти действия выполняет сетевой демон DHCPCD (DHCP-клиент).

Мы можем сами указать список предпочитаемых DNS-серверов, поместив их в файл «/etc/resolv.conf», но после презагрузки системы или же после переподключения USB-Ethernet адаптера, все внесенные в файл изменения будут перезаписаны демоном DHCPCD.

Если вы действительно хотите использовать свой список DNS-серверов (например от Гугла), то нужно указать службе DHCPCD не выполнять «хук» (не «подцеплять») список NS-серверов, полученный от другого маршрутизатора по DHCP.

Добавим IP-адреса публичных серверов от OpenDNS:

sudo nano /etc/resolv.conf

Заменим содержимое файла строчками:

nameserver 208.67.222.222
nameserver 208.67.220.220

Теперь нужно отредактировать файл «/etc/dhcpcd.conf»:

sudo nano /etc/dhcpcd.conf

Добавляем в нем строчку «nohook resolv.conf», вот пример из текущей конфигурации:

nohook wpa_supplicant
nohook resolv.conf

interface wlan0
static ip_address=192.168.2.1/24

Данное ограничение на действия с файлом «/etc/resolv.conf» будет справедливо только для службы DHCPCD, другие программы и далее смогут вносить изменения в этот файл.

Чтобы полностью запретить изменение прописанных вручную DNS-серверов в файле «/etc/resolv.conf», его нужно защитить от перезаписи, важно заметить что манипуляции с командой «chmod -w» здесь не помогут. Для этой цели воспользуемся командой «chattr», которая служит для изменения атрибутов файлов.

Установим файлу «/etc/resolv.conf» атрибут «immutable» (не модифицируемый), который запретит переименование файла, создание символьных ссылок для него, не позволит записывать в него данные и запускать. Снять этот атрибут из файла может только суперпользователь — root.

sudo chattr +i /etc/resolv.conf

Если нужно будет отредактировать файл, то с помощью следующей команды можно снять атрибут «immutable»:

sudo chattr -i /etc/resolv.conf

Важно понимать, что получаемый от интернет-провайдера список DNS-серверов может использоваться для сопоставления доменных имен и IP-адресов ресурсов, которые работают внутри сети провайдера (не в интернете).

В случае замены DNS-серверов, полученных от интернет-провайдера по DHCP, на любые другие, его внутренние сайты и ресурсы могут оказаться недоступными. Исправить это можно временной установкой DNS-серверов провайдера или же прописыванием статических записей с соответствием «хост-IP» часто используемых ресурсов из сети провайдера в файл hosts.

Важная заметка в плане информационной безопасности публичных DNS: делая запросы к разным сайтам и хостам в интернете их имена будут преобразовываться в IP-адреса используя для этого указанные вами публичные DNS-сервера, соответственно компании что предоставляют такие услуги смогут видеть что с вашего IP выполняются DNS-запросы для получения адресов сопоставимых именам тех или иных сайтов.

Будут ли эти данные собраны и потом как-то использованы — можно лишь догадываться. Например в компании Гугл эта информация может быть использована в маркетинговых или других статистических целях.

По этим причинам рекомендую хорошо обдумать какому из публичных DNS-провайдеров отдавать предпочтение, и стоит ли это делать вообще если в вашем случае безопасность и приватность очень важна.

Таблица с публичными DNS-серверами от различных компаний по всему миру:

Компания IPv4 nameservers IPv6 nameservers Примечание
CloudFlare 1.1.1.1
1.0.0.1
   
Google INC 8.8.8.8
8.8.4.4
2001:4860:4860::8888
2001:4860:4860::8844
 
OpenNIC 185.121.177.177
185.121.177.53
2a05:dfc7:5::53
2a05:dfc7:5::5353
 
UncensoredDNS 91.239.100.100
89.233.43.71
2001:67c:28a4::
2a01:3a0:53:53::
anycast
unicast
Comodo 8.26.56.26
8.20.247.20
   
DNS.WATCH 84.200.69.80
84.200.70.40
2001:1608:10:25::1c04:b12f
2001:1608:10:25::9249:d69b
OpenDNS 208.67.222.222
208.67.220.220
2620:0:ccc::2
2620:0:ccd::2
 
Quad9 9.9.9.9
9.9.9.10
2620:fe::fe
2620:fe::10
С blocklist и DNSSEC
Без blocklist и DNSSEC

Подготовка 3G-модема, узнаем его состояние используя minicom

Многие 3G-модемы являются составными устройствами, которые могут эмулировать несколько различных устройств:

  • виртуальный накопитель CD-ROM (как правило на нем содержатся драйвера и программы);
  • картридер для Flash-карты (если в устройстве есть разьем под карточку);
  • модем.

В начале статьи нами был установлен пакет «usb-modeswitch», который представляет собой набор udev-правил (скриптов), позволяющих в автоматическом режиме переключить беспроводный 3G-адаптер из режима накопителя (как правило виртуальный CD-привод) в режим модема.

Подключаем 3G-модем к свободному USB-разъему малинки и смотрим какие устройства в /dev нам доступны для использования:

ls /dev | grep ttyUSB

Получим примерно следующий список файлов-устройств (последовательных портов):

ttyUSB0
ttyUSB1
ttyUSB2
ttyUSB3

Теперь не плохо бы узнать код производителя (Vendor ID, vid) и код устройства (Product ID, pid) для используемого модема, просмотрим список подключенных по USB к малинке устройств:

lsusb

Примерный вывод:

...
Bus 001 Device 008: ID 05c6:6000 Qualcomm, Inc. Siemens SG75
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

В данном случае модем определился как ‘Siemens SG75’ со следующими идентификаторами:

  • Vendor ID = 05c6 (Qualcomm, Inc.);
  • Product ID = 6000 (Siemens SG75).

Идентификаторы USB-устройств и их названия можно узнать на сайте проекта ‘Linux USB Project’, вот свежий список в формате TXT: http://www.linux-usb.org/usb.ids

Идентификаторы ‘Vendor ID’ и ‘Product ID’ зависят от типа используемого вами 3G-модема и будут отличаться от приведенного выше примера.

Теперь мы можем подключиться к любому из ttyUSB* используя эмулятор последовательного терминала ‘minicom’. О параметрах запуска и работе с программным эмулятором последовательного терминала ‘minicom’ можно узнать из его man-странички:

man minicom

В моем случае на прием команд согласились только два из портов: ‘ttyUSB0’ и ‘ttyUSB1’. Первый порт используется для управления модемом, а второй — для приема и передачи потока данных.

Подключимся к ‘ttyUSB0’:

minicom --device=/dev/ttyUSB0

При успешном подключении к порту увидим приветствие и информацию по вызову справки:

Welcome to minicom 2.7

OPTIONS: I18n
Compiled on Apr 22 2017, 09:14:19.
Port /dev/ttyUSB0, 11:47:54

Press CTRL-A Z for help on special keys

Для отображения списка команд (справки) нужно нажать комбинацию клавиш CTRL+A и отпустив их потом нажать Z, для выхода из справки нажимаем ENTER.

Теперь для тестирования и управления модема можно использовать AT-команды. Проверим отвечает ли нам модем — наберем команду «AT» и нажмем ENTER:

Press CTRL-A Z for help on special keys

AT
OK

Если все работает то получим ответ ‘OK’.

Используя AT-команды можно узнать разную полезную информацию о модеме и его состоянии, установить режим его работы, и даже отправить SMS (если поддерживается).

Список некоторых информационных AT-команд:

  • ATI  — вывести информацию о модеме;
  • AT+CGMI  — отобразить только производителя модема;
  • AT+CGMR  — вывести версию программного обеспечения;
  • AT^HWVER  — вывести версию аппаратного обеспечения;
  • AT+CGSN  — вывести IMEI;
  • AT+CIMI  — вывести IMSI;
  • AT^PREFMODE=? — вывести поддерживаемые режимы передачи данных;
  • AT+CSQ  — вывести уровень сигнала 3G;
  • AT+CBC  — уровень заряда батареи (если используется автономный модем или телефон);
  • AT^CVOICE=?  — поддерживает ли модем голосовые вызовы;
  • AT^SYSINFO  — вывести системную информацию (состояние, роуминг, режим).

Если какая-то из команд вывела ошибку и терминал отказывается отвечать — выполним выход из программы со сбросом состояния модема: нажимаем CTRL+A, Z и потом X. Теперь можно снова подключиться к порту модема используя minicom.

Запрос ‘AT^SYSINFO’ выведет информацию одной закодированной строчкой:

AT^SYSINFO
^SYSINFO:2,255,0,8,240

Формат выведенной информации: [status], [domain], [roaming status], [mode], [SIM state]. Сегменты разделены запятыми и имеют соответствующие текущим параметрам цифровые значения.

[status]:

  • 0 — No service (нет сигнала);
  • 1 — Restricted service (ограниченный доступ);
  • 2 — Valid service (сигнал ок);
  • 3 — Restricted regional service (ограниченный региональный доступ);
  • 4 — Power-saving and deep sleep state (спящий режим).

[domain]:

  • 0 — No service;
  • 1 — Only CS service;
  • 2 — Only PS service;
  • 3 — PS+CS service;
  • 4 — CS and PS not registered, searching.

[roaming status]:

  • 0 — Non roaming (роуминг не активен);
  • 1 — Roaming (в роуминге).

[mode]:

  • 0 — No service;
  • 1 — AMPS mode;
  • 2 — CDMA mode;
  • 3 — GSM/GPRS mode;
  • 4 — HDR mode;
  • 5 — WCDMA mode;
  • 6 — GPS mode;
  • 7 GSM/WCDMA;
  • 8 CDMA/HDR HYBRID;
  • 15 TD-SCDMA mode.

[SIM state]:

  • 0 — Invalid USIM card state or pin code locked;
  • 1 — Valid USIM card state;
  • 2 — USIM is invalid in case of CS;
  • 3 — USIM is invalid in case of PS;
  • 4 — USIM is invalid in case of either CS or PS;
  • 255 — USIM card is not existent.

Запрос ‘AT+CSQ’ выведет уровень сигнала:

AT+CSQ
+CSQ: 26, 99

В данном случае получено значение в формате ’26, 99′, где:

  • 26 — Received signal strength indicator (уровень сигнала в CSQ)
  • 99 — Bit Error Rate (счетчик ошибок)

Для перевода значения из CSQ в dBm можно использовать формулу:

dBm = -113 + N * 2

где N — это полученное после AT-команды значение CSQ.

dBm = -113 + 26 * 3 = -61 (отличное качество сигнала).

Чтобы вам было легче сориентироваться в значениях, приведу небольшую табличку:

Значение CSQ RSSI, dBm Описание
2 … 9 -109 … -95 Плохой сигнал
10 … 14 -93 … -85 Так себе, ОК
15 … 19 -83 … -75 Хороший сигнал
20 … 30 -73 … -53 Отличный сигнал

Запрос ‘AT^PREFMODE=?’ выведет список поддерживаемых режимов передачи данных для 3G-модема:

AT^PREFMODE=?
^PREFMODE:(2,4,8)

Возможные режимы работы модема:

  • 2 — CDMA2000 (1x), скорость обмена данными до 153 КБит/сек;
  • 4 — EVDO (Evolution Data Only), высокая скорость обмена данными;
  • 8 — гибридный, с автоматическим выбором типа подключения по состоянию сигнала.

Скорость передачи данных в разных ревизиях EVDO:

  • rev.0 — 2,4 Mbit/s на прием 0,153 Mbit/s на передачу;
  • rev.A — 3,1 Mbit/s на прием 1,8 Mbit/s на передачу;
  • rev.B — 73,5 Mbit/s на прием 27 Mbit/s на передачу.

Как видите, с помощью AT-команд можно узнать очень много полезной информации о модеме, она вам может пригодиться для отладки, мониторинга и сбора информации о модеме.

3G-модем и консольная звонилка WVDIAL

Для работы с 3G-USB модемом нам понадобится программа «wvdial», которая умеет выполнять дозвон к провайдеру с установленными параметрами, а также следить за состоянием сетевого подключения.

WVDial (WeaVe Dial) — это умная программа для организации подключений с использованием модемов через протокол PPP (Point-to-Point Protocol). Мы уже установили ее на этапе установки программ.

Документация по wvdial и параметрам его конфигурационного файла:

man wvdial
man wvdial.conf

Для обнаружения модема и создания базового файла с настройками, желательно запустить программу-конфигуратор:

sudo wvdialconf

Программа выполнит определение и тест модема, на основе полученных данных сгенерирует базовый конфигурационный файл:

Editing `/etc/wvdial.conf'.

Scanning your serial ports for a modem.

ttyUSB0<*1>: ATQ0 V1 E1 -- OK
ttyUSB0<*1>: ATQ0 V1 E1 Z -- OK
ttyUSB0<*1>: ATQ0 V1 E1 S0=0 -- OK
ttyUSB0<*1>: ATQ0 V1 E1 S0=0 &C1 -- OK
ttyUSB0<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 -- OK
ttyUSB0<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK
ttyUSB0<*1>: Modem Identifier: ATI -- Manufacturer: +GMI: Qualcomm
ttyUSB0<*1>: Speed 9600: AT -- OK
ttyUSB0<*1>: Max speed is 9600; that should be safe.
ttyUSB0<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 -- OK
...
Found a modem on /dev/ttyUSB0.
Modem configuration written to /etc/wvdial.conf.
ttyUSB0<Info>: Speed 9600; init "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0"
ttyUSB1<Info>: Speed 9600; init "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0"

Теперь файл «/etc/wvdial.conf» должен быть уже создан, в нем прописаны настройки и путь к файлу последовательного порта (/dev/ttyUSB0), через который будет работать модем. Откроем «wvdial.conf» для редактирования:

sudo nano /etc/wvdial.conf

Примерно так выглядит мой уже измененный конфигурационный файл:

[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CSQ
Init4 = AT^PREFMODE=8
Modem Type = Analog Modem
Phone = #777
ISDN = 0
Username = USER
Password = PASSWORD
New PPPD = yes
Modem = /dev/ttyUSB0
Baud = 9600

В параметрах Init1-init4 содержатся наборы AT-команд для управления модемом, здесь я вручную добавил строку «Init4 = AT^PREFMODE=8», которая принудительно пытается переключить модем в гибридный режим работы EVDO+CDMA2000 (8).

Если у вас в местности слабый и не стабильный сигнал, то возможно что стоит переключить модем на использование именно гибридного режима (8).

Строчка ‘Init3 = AT+CSQ’ заставляет модем вывести текущий уровень принимаемого сигнала, об этом я рассказывал в предыдущем разделе.

Следующие параметры в конфигурационном файле отвечают за дозвон и авторизацию, установите их в соответствии с инструкциями от своего провайдера:

  • Phone = #777 — номер телефона для дозвона;
  • Username = USER — имя пользователя;
  • Password = PASSWORD — пароль.

В случае если в файле «/etc/resolv.conf» прописаны статичные DNS-сервера целесообразно отключить получение их списка от провайдера 3G-интернета. Для этого в файл /etc/wvdial.conf нужно добавить следующую строчку:

Auto DNS = Off

Также в данном случае нужно открыть для редактирования файл «/etc/ppp/peers/wvdial»:

sudo nano /etc/ppp/peers/wvdial

Комментируем (ставим спереди значек решотки) в нем строчку:

#usepeerdns

Теперь мы можем запустить дозвон до провайдера и получить интернет подключение с помощью wvdial. Если у вас к малинке уже подключен интернет через внешний USB Ethernet адаптер, то интерфейс этого адаптера нужно предварительно деактивировать:

sudo ip link set dev eth1 down

Для запуска дозвона используем следующую команду:

sudo wvdial

Начнется процедура выполнения AT-команд и получения параметров соединения, IP-адресов.

--> WvDial: Internet dialer version 1.61
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
...
--> PPP negotiation detected.
--> Starting pppd at Mon Jun 25 15:05:21 2018
--> Pid of pppd: 2967
--> Using interface ppp0
--> local  IP address 10.10.10.82
--> remote IP address 10.10.11.3
--> primary   DNS address 192.168.10.121
--> secondary DNS address 192.168.10.122

На малинке должен появиться интернет через 3G-соединение. Будет создан и активирован интерфейс ppp0, это можно проверить выполнив команду ‘ip a’:

$ ip a
...
5: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 3
    link/ppp 
    inet 10.10.10.122 peer 10.1.1.3/32 scope global ppp0
       valid_lft forever preferred_lft forever

Проверяем пингом соединение с каким-то внешним сайтом:

ping reddit.com

Результат:

PING reddit.com (151.101.65.140) 56(84) bytes of data.
64 bytes from 151.101.65.140 (151.101.65.140): icmp_seq=1 ttl=57 time=131 ms
64 bytes from 151.101.65.140 (151.101.65.140): icmp_seq=2 ttl=57 time=123 ms
64 bytes from 151.101.65.140 (151.101.65.140): icmp_seq=3 ttl=57 time=120 ms
^C
--- reddit.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 120.250/125.185/131.506/4.698 ms

Интернет есть, все работает!

Прервать соединение через wvdial можно в окне терминала, где была запущена команда на старт, достаточно нажать комбинацию клавиш ‘CTRL+C’. Также можно принудительно завершить все процессы под именем wvdial следующей командой:

sudo killall wvdial

После деактивации 3G-подключения можем вернуть обратно интернет подключение через USB Ethernet адаптер (интерфейс eth1), активируем проводной интерфейс:

sudo ip link set dev eth1 up

Программу wvdial очень удобно запускать в мультиплексоре терминалов — TMUX (Terminal MUltipleXor). Это позволит выполнять программу в фоновом режиме и при необходимости наблюдать за состоянием соединения и процессом дозвона wvdial. Для этого запустим сначала сам TMUX:

tmux

В открывшемся терминале запускаем ‘wvdial’:

sudo wvdial

Теперь программа дозвона выполняется в программном терминале TMUX, чтобы отключиться от него и перейти в основной терминал достаточно нажать комбинацию клавиш ‘CTRL+b’, а потом отпустив их ‘d’. Чтобы обратно подключиться к терминалу TMUX с запущенным и работающем в нем wvdial достаточно выполнить команду:

tmux attach

TMUX — очень мощная программа, которая позволяет разделить экран (сессию) на несколько подтерминалов, запускать и управлять множеством сессий и содержит много других полезных и удобных возможностей.

Больше информации о этой программе можно узнать из ее man-страници:

man tmux

Режимы управления частотой CPU в Raspberry Pi и его температура

Ядро Linux управляет частотой микропроцессора (CPU) в одном из установленных режимов:

  • ondemand — по требованию, частота каждого ядра CPU возрастает при увеличении нагрузки;
  • performance — частота ядер CPU постоянно имеет максимальное значение;
  • powersave — энергосберегающий режим.

Узнать текущий режим управления частотой первого ядра CPU Raspberry Pi (отсчет начинается с 0) можно командой:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Узнаем режимы для каждого из ядер:

for i in /sys/devices/system/cpu/*/cpufreq/scaling_governor; do cat $i; done

Примерный вывод для 4х-ядерного микропроцессора малинки:

ondemand
ondemand
ondemand
ondemand

По умолчанию в малинке используется ‘ondemand’.

Текущий режим всех ядер CPU можно попробовать изменить например на ‘performance’ (максимальная частота), для этого нужно выполнить команду:

sudo sh -c 'for i in /sys/devices/system/cpu/*/cpufreq/scaling_governor; do echo performance > $i; done'

Таким же способом можно перевести все ядра в режим энергосбережения (минимальная частота):

sudo sh -c 'for i in /sys/devices/system/cpu/*/cpufreq/scaling_governor; do echo powersave > $i; done'

Cписок доступных рабочих частот всех ядер микропроцессора можно узнать командой:

for i in /sys/devices/system/cpu/*/cpufreq/scaling_available_frequencies; do cat $i; done

В моем случае доступны только по две частоты для каждого ядра:

600000 1200000

Минимальную и минимальную частоты первого ядра можно узнать следующими двумя командами:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

Частоты ядер микропроцессора в Raspberry Pi 3 Model B:

  • 600МГц — минимальная (постоянно включена в режиме powersave);
  • 1200МГц — максимальная (постоянно включена в режиме performance).

Узнаем текущие частоты всех ядер микропроцессора:

for i in /sys/devices/system/cpu/*/cpufreq/scaling_cur_freq; do cat $i; done

Вывод:

600000
600000
600000
600000

Я бы не рекомендовал изменять scaling_governor из значения по умолчанию ‘ondemand’ на ‘powersave’ или ‘performance’ если малинка будет работать в режиме роутера, режим ‘ondemand’ — оптимальный в большинстве случаев применения малинки.

Если все же требуется перманентно перевести микропроцессор малинки например в энергосберегающий режим, то это можно сделать добавив соответствующую конструкцию из команд в файл ‘rc.local’:

sudo nano /etc/rc.local

Добавляем в самый низ строку с командами:

/bin/sh -c 'for i in /sys/devices/system/cpu/*/cpufreq/scaling_governor; do echo powersave > $i; done'

или так (для 4х ядер CPU):

/bin/echo powersave > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
/bin/echo powersave > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor
/bin/echo powersave > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor
/bin/echo powersave > /sys/devices/system/cpu/cpu3/cpufreq/scaling_governor

Теперь после перезагрузки Raspbian микропроцессор будет находиться в режиме энергосбережения.

В зависимости от нагрузки на CPU его температура будет возрастать. Узнать температуру микропроцессора Raspberry Pi можно следующей командой:

cat /sys/class/thermal/thermal_zone0/temp

Результатом будет число (пример):

45622

Делим его на 1000 и получим: 45,622 градусов по Цельсию.

Также температуру чипа можно получить используя одну из утилит для работы с графическим процессором (GPU):

/opt/vc/bin/vcgencmd measure_temp

Примерный вывод:

temp=45.6'C

Настройка часов реального времени (RTC)

В прошлой статье я описывал как исправить, подключить и установить в корпус модуль часов реального времени DS1307. Данный модуль работает используя шину данных I2C.

В одной из прошлых статей я описывал как работать с шиной I2C. На этапе настройки малинки мы уже включили эту шину, теперь можно просканировать ее на предмет подключенных к ней устройств:

sudo i2cdetect -y 1

Пример результата выполнения команды:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Видим что обнаружены три устройства:

  • 0x3c — OLED-дисплей SSD1306;
  • 0x68 — модуль RTC DS1307;
  • 0x50 — I2C EEPROM 24C32, установленная на плате с DS1307.

Модуль часов определен и готов к использованию. Зарегистрируем модуль часов реального времени в операционной системе:

sudo sh -c 'echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device'

Теперь, если снова вывести список адресов I2C-устройств в консоль, то вместо адреса модуля «68» появятся «UU»:

Смена вывода адреса DS1307 после активации

Рис. 3. Смена вывода адреса DS1307 после активации.

Считаем текущее значение времени, установленное в RTC:

sudo hwclock -r

При первом подключении и использовании модуля получим дату 2000-01-01:

2000-01-01 02:00:03.093197+0200

Проверяем текущую дату и время в Raspbian, выполним любую из команд:

date
timedatectl

Если дата или время в системе отличается от реальных значений — исправляем их, сделать это можно следующей командой:

sudo timedatectl set-time '2050-11-23 08:10:40'

где:

  • 2050-11-23 — год в формате: год-мес-день;
  • 08:10:40 — время в формате: час:мин:сек.

По умолчанию в Raspbian включена служба NTP (Network Time Protocol), которая служит для синхронизации времени через интернет, поэтому делать правку даты или времени скорее всего не понадобится.

Теперь можем выполнить запись текущих значений даты и времени в модуль RTC:

sudo hwclock -w

Считываем значения из модуля RTC, убедимся что значения записались:

sudo hwclock -r

После выполнения команды должны увидеть текущие дату и время.

Теперь мы можем выполнять синхронизацию системного времени ОС Raspbian с временем в RTC используя следующую команду:

hwclock -s

При каждой загрузке малинки нужно выполнять синхронизацию времени ОС с данными даты и времени из RTC, поэтому мы автоматизируем этот процесс.

Команды для инициализации I2C модуля и синхронизации системного времени можно добавить в файл ‘/etc/rc.local’, но я предлагаю сделать для данной цели отдельный скрипт и юнит для systemd.

sudo nano /usr/local/sbin/systemd-i2chwclock.sh

Содержимое скрипта:

#!/bin/sh
# HWClock init script for systemd
/bin/echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
/bin/sleep 3
/sbin/hwclock -s
exit 0

Делаем файл исполняемым и запускаем его:

sudo chmod +x /usr/local/sbin/systemd-i2chwclock.sh
sudo /usr/local/sbin/systemd-i2chwclock.sh

Готовим юнит для systemd:

sudo nano /etc/systemd/system/i2chwclock.service
[Unit]
Description=I2C HWClock sync
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/systemd-i2chwclock.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Разрешаем запуск при старте системы:

sudo systemctl enable i2chwclock.service

Также, в данном случае, желательно отключить службу синхронизации времени через интернет. Узнаем установлена ли служба NTP:

sudo systemctl status ntp

Если же демон NTP установлен и запущен — остановим его и отключим:

sudo systemctl stop ntp
sudo systemctl disable ntp

Теперь можно перезагрузить малинку и проверить системное время — все должно быть в порядке!

Считываем показания термодатчика DS18B20

Датчик температуры DS18B20 установлен на плате модуля часов реального времени DS1307, его вывод данных подключен к пину интерфейса 1-Wire в Raspberry Pi, который соответствует IO4 (7-й вывод гребенки).

Интерфейс передачи данных 1-Wire (через один проводник) мы уже активировали на этапе базовой настройки операционной системы Raspbian.

Каждый датчик температуры DS18B20, подключаемый к малинке, получает свой уникальный идентификатор. В дереве устройств автоматически создается файловая структура, взаимодействуя с которой можно очень просто считать текущие данные из нужного нам датчика.

Выведем список директорий в дереве устройств, что имеют отношение к интерфейсу 1-Wire:

ls /sys/bus/w1/devices/

Примерный результат вывода:

28-021501b2baсf  w1_bus_master1

Для датчиков температуры DS18B20 создаются директории вида «28-XXXXXXXXXXXX», таким образом можно идентифицировать каждый из подключенных датчиков. В нашем случае, подключен всего один датчик температуры, он получил идентификатор «28-021501b2baсf».

В директории этого устройства содержатся некая структура файлов и директорий, смотрим их список:

ls /sys/bus/w1/devices/28-021501b2baсf

Вывод команды:

driver  hwmon  id  name  power  subsystem  uevent  w1_slave

В данном случае нас интересует файл под названием «w1_slave», выведем его содержимое в консоль:

cat /sys/bus/w1/devices/28-021501b2baсf/w1_slave

Примерный результат:

0e 02 4b 46 7f ff 0c 10 0b : crc=0b YES
0e 02 4b 46 7f ff 0c 10 0b t=32875

Здесь:

  • crc=0b YES  — говорит о том что контрольная сумма результата в порядке;
  • t=32875  — число, поделив которое на 1000 получим текущее значение температуры, в данном примере это 32,875 градуса по Цельсию.

Для получения только числового значения температуры можно воспользоваться чтением данных из другого файла:

cat /sys/bus/w1/devices/28-021501b2baсf/hwmon/hwmon0/temp1_input

Результат:

32875

Минус последнего метода в том, что здесь не указано верна ли контрольная сумма операции и можно ли доверять этому значению.

Полученные с помощью этих команд данные можно использовать в программах написанных на Bash, Python и других языках программирования.

Генерация звуковых сигналов через пьезо-зуммер

Пьезо-зуммер («пищалка») подключен к каналу IO18 (вивод 12 на гребенке малинки). Генерация звуковых сигналов осуществляется подачей импульсов разной частоты и длины на канал IO18.

В данном случае можно написать программу с несколькими вложенными циклами, которая будет генерировать очереди импульсов, а можно использовать функцию PWM (широтно-импульсная модуляция) в модуле Rpi.GPIO.

Подавая на пин 12 сигналы с определенными частотами и длительностью можно генерировать различные звуковые оповещения и мелодии.

В качестве примера приведу очень простую программу, которая генерирует «сигналы от инопланетян» Alien, звучит достаточно забавно.

nano ~/speaker-alien-signal-test.py

Скопируйте в открывшийся редактор следующий код:

#!/usr/bin/env python3     
# -*- coding: utf-8 -*-
# 
# Raspberry Pi Router speaker test.
# https://ph0en1x.net

import RPi.GPIO as GPIO
from random import randrange
from time import sleep

GPIO.setmode(GPIO.BCM)
# Speaker connected to IO18 (pin N12).
GPIO.setup(18, GPIO.OUT) 
# Start frequency=1Hz.
pwm = GPIO.PWM(18, 1) 
# Generate meandr signal (duty_cycle=50%) |_|^|_|^|... 
pwm.start(50)

try:
    while True:
        # Change frequency in random range 20Hz-10kHz.
        pwm.ChangeFrequency(randrange(20,10001))
        # Change timeout in random range 0.01-0.04 sec.
        sleep(randrange(1,5)/100)

except KeyboardInterrupt:
    pass

# Stop PWM, clean GPIO PIN state.
pwm.stop()
GPIO.cleanup()

Запускаем…

python3 ~/speaker-alien-signal-test.py

Прервать выполнение программы можно нажав комбинацию клавиш «CTRL+C» (break).

Чередуя комбинации «частота+длительность» сигнала можно создать свою звуковую мелодию. Согласитесь, что составлять такую мелодию из значений частот и временных задержек не очень удобно — потребуется не мало времени и без хорошего музыкального слуха тут не обойтись.

Компания Nokia в свое время создала специальный формат RTTTL (Ring Tone Text Transfer Language) для описания, передачи и хранения мелодий в своих мобильных телефонах.

Пример мелодии ‘Aqua — Barbie girl’ в формате RTTTL:

Barbie girl:d=4,o=5,b=125:8g#,8e,8g#,8c#6,a,p,8f#,8d#,8f#,8b,g#,8f#,8e,p,8e,8c#,f#,c#,p,8f#,8e,g#,f#

Ниже я покажу как можно проигрывать мелодии в формате RTTTL используя платформу Raspberry Pi и подключенный к ней динамик.

Прежде чем перейдем к программе нам понадобится установить модуль ‘rtttl’ для языка Python, который позволит перевести строчку мелодии формата RTTTL в массив с частотами и интервалами. Исходный код модуля и примеры по его использованию приведены на GITHUB’е разработчика.

Установим модуль для Python3 следующей командой:

sudo pip3 install rtttl

Создадим новый скрипт:

nano ~/speaker-rttl-test.py

Исходный код программы:

#!/usr/bin/env python3     
# -*- coding: utf-8 -*-
# 
# Raspberry Pi Router speaker RTTTL melody test.
# https://ph0en1x.net

import RPi.GPIO as GPIO
from rtttl import parse_rtttl
from time import sleep

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT) 
pwm = GPIO.PWM(18, 1) 
pwm.start(50)

song = ("Barbie girl:d=4,o=5,b=125:8g#,8e,8g#,8c#6,a,p,8f#," 
        "8d#,8f#,8b,g#,8f#,8e,p,8e,8c#,f#,c#,p,8f#,8e,g#,f#")
notes = parse_rtttl(song)

try:
    print("Playing: {} ...".format(notes['title']))
    for note in notes['notes']:
        if note['frequency'] == 0:
            note['frequency'] = 1
        pwm.ChangeFrequency(note['frequency'])
        sleep(note['duration']/1000)

except KeyboardInterrupt:
    pass

pwm.stop()
GPIO.cleanup()

Запуск:

python3 ~/speaker-rttl-test.py

Данная программа является немного измененным и дополненным вариантом предыдущего примера. Здесь добавлен парсинг кода песни в формате RTTTL и проигрывание полученных нот в цикле по-порядку.

Добавил еще небольшую поправку: если частота в списке нот равна нулю (для реализации паузы), то проигрываем сигнал с частотой 1Гц. Метод ‘pwm.ChangeFrequency’ в качестве аргумента не принимает значения равного 0 (будет выведена ошибка). К тому же в этом решении есть еще один плюс: если пауза длинная, то мы будем слышать как бы звук фоновых ударных с частотой 1Гц.

Для поиска текстов мелодий в формате RTTTL можно воспользоваться поисковыми системами, используйте следующую конструкцию поискового запроса: «RTTTL + имя_песни». Также есть сайты, которые содержат целые базы рингтонов, например — www.cellringtones.com.

Вот архив с кодами 10 000+ мелодий — 10000_melodies_rttl.7z (513КБ).

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

Таким образом, вы можете создать программу для проигрывания нужной мелодии и использовать ее вызов в различных скриптах на Bash или Python, озвучивая различные события в самодельном роутере на Raspberry Pi.

Управление RGB-светодиодом и реагирование на нажатия кнопок

О том как работать с кнопками и светодиодами, подключенными к GPIO Raspberry Pi, я уже описывал в прошлых статьях:

  • GPIO в Raspberry Pi, эксперимент со светодиодом и кнопкой
  • RPi.GPIO — входы, выходы, прерывания, PWM

Здесь приведу небольшой пример: будем в случайном порядке включать и выключать три цвета подключенного RGB-светодиода, при нажатии на одну из кнопок — перебор цветов остановится на текущем, при нажатии на другую кнопку — продолжится.

Если посмотреть на принципиальную схему, то светодиод и две из кнопок у нас подключены к следующим каналам GPIO:

  • LED Red — IO23 (вывод 16);
  • LED Green — IO24 (вывод 18);
  • LED Blue — IO25 (вывод 22);
  • Switch 1 — IO20 (вывод 38);
  • Switch 2 — IO21 (вывод 40).

Создадим новый файл скрипта:

nano ~/leds-switches-test.py

Код программы:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 
# Raspberry Pi Router LEDs+SWITCHes test.
# https://ph0en1x.net

import RPi.GPIO as GPIO

from random import choice, randrange
from time import sleep

GPIO.cleanup()
GPIO.setmode(GPIO.BCM)

# Prepare LEDs pins for OUTPUT.
leds_io = [23, 24, 25]
for led_io in leds_io:
    GPIO.setup(led_io, GPIO.OUT)

# Prepare SWITCHes pins for INPUT
switch_on = 20
switch_off = 21
GPIO.setup(switch_on, GPIO.IN)
GPIO.setup(switch_off, GPIO.IN)

change_color_on = True

def callback_start(channel):
    """ Start color changing. """
    global change_color_on
    change_color_on = True
    print('START')

def callback_stop(channel):
   """ Stop color changing. """
    global change_color_on
    change_color_on = False
    print('STOP')

GPIO.add_event_detect(
    switch_on, 
    GPIO.FALLING, 
    callback=callback_start, 
    bouncetime=300)
GPIO.add_event_detect(
    switch_off, 
    GPIO.FALLING, 
    callback=callback_stop, 
    bouncetime=300)

print("Press CTRL+C to exit...")
try:
    while True:
        io_num = choice(leds_io)
        io_level = GPIO.HIGH if randrange(0,2) else GPIO.LOW
        if not GPIO.input(io_num) == io_level and change_color_on:
            GPIO.output(io_num, io_level)
            sleep(0.1)
        sleep(0.01)

except KeyboardInterrupt:
    GPIO.cleanup()

Для запуска скрипта без указания в командной строке интерпретатора python3 сделаем файл исполняемым:

chmod +x ~/leds-switches-test.py

Запуск:

~/leds-switches-test.py

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

Вывод данных на OLED-дисплей

В статье «OLED дисплей SSD1306 (128х64px) и Raspberry Pi, подключение и эксперименты» я подробно расписал как выводить текст, геометрические фигуры и рисунки на дисплей SSD1306, который подключен к Raspberry Pi. Хочу заметить что в комментариях к этой статье вы найдете дополнительную полезную информацию, которой нет в самой статье.

В данном проекте использован точно такой же дисплей, предыдущее сканирование шины I2C показало что адрес этого дисплея на шине — 0x3c.

Набор скриптов для управления

Итак, сервер/роутер на основе raspberry Pi настроен, все службы работают, с использованием часов реального времени, светодиодов, пищалки, термодатчика, кнопок и дисплея разобрались.

Чтобы показать как это все можно связать вместе я написал несложную программу, которая являет собой набор Python-скриптов. Эта программа служит для вывода некоторой полезной информации на дисплей, управления кнопками с индикацией и звуковым оповещением для установленных событий, а также для безопасного завершения работы сервера.

Пять кнопок на корпусе малинки в данном случае выполняют следующие запрограммированные функции:

  1. Вызов меню, активация выбранного пункта;
  2. Выбрать предыдущий пункт меню;
  3. Выбрать следующий пункт меню;
  4. Вывод системной информации;
  5. Вывод пользовательской информации.

Вывод меню и различной информации на дисплей сервера, построенного на Raspberry Pi

Рис. 4. Вывод меню и различной информации на дисплей сервера, построенного на Raspberry Pi.

Кнопки 4 и 5 можно очень просто перепрограммировать на другие действия, в данном случае эти кнопки дублируют функционал пунктов меню 1 и 2, так сказать «горячие кнопки».

Пищалка задействована следующим образом:

  • звук 1 («сигнал от инопланетян») — при нажатии кнопок 1, 4 и 5;
  • звук 2 («клик») — при нажатии кнопок 2 и 3;
  • звук 3 («ошибка») — при пропадании интернет-соединения.

Включить или выключить озвучивание событий можно через пункт меню 3 или же в конфигурационном файле (дальше кратко — КФ).

Использование RGB-светодиода (Red Green Blue):

  • R — светится при отсутствующем интернет-подключении, а также при запуске процедуры завершения работы;
  • G — мигает в процессе сбора данных  для отображения системной и пользовательской информации;
  • B — мигает при нажатии любой из кнопок;
  • R+G+B — при запуске скрипта светятся все вместе.

В режиме бездействия экран малинки погашен, но через каждые 20 секунд отображается одна из анимаций, которые были подготовлены для примера:

  • Вращающийся логотип Debian;
  • Вращающийся атом;
  • Краткий анимультфильм про кота и паука.

Список анимаций для отображения можно задать в КФ, там же можно отключить анимации, а еще для этого служит 4-й пункт меню.

Анимация в данном случае выполняется поочередной последовательной сменой картинок, которые хранятся в папке ‘images/’ проекта со скриптами. Имена файлов для картинок с анимацией начинаются с префикса ‘anim_’, дальше следует название анимации (оно указывается в списке анимаций для отображения в КФ), а за ним следует номер кадра по порядку: 1, 2, 3…8, 9, a, b, c, d…z. Если кадры нумеровать используя числа больше 10-ти (11, 25…) то порядок выполнения анимации будет нарушен.

Таким образом, собрав в папку ‘images/’ картинки-кадры и прописав имя анимации в КФ вы сможете добавить свою оригинальную анимацию — это может быть ваш логотип, какое-то сообщение, например «Не лезь, стукнет током!» с рисунком молнии и т.п.

Теперь кратко о сборе данных для отображения пользовательской и системной информации. Получение значений курсов валют и криптовалют осуществляется с помощью открытых API таких сайтов как «Coinmarcetcap.com» и «Currencyconverterapi.com».

Примерную температуру корпуса мы получим из данных датчика DS18B20, температуру CPU и общее/занятое количество ОЗУ узнаем используя штатные средства GNU/Linux.

Для периодического мониторинга и отображения наличия доступа в интернет будет использоваться проверка подключения к DNS-серверу гугла на порт 53.

Архив программы (python-скрипты и ресурсы) v.1.2 —  Даташит на микросхему TDA7250 (35KB).

! Репозитории со скриптами на GitHub больше размещаться не будут. После покупки мегакорпорацией, блокировок аккаунтов и полезных репозиториев, а также ситуации с youtube-dl нет желания там присутствовать.

Файловая структура директории ‘rrouter’:

  • beeper.py — содержит класс, отвечающий за работу с звуковыми сигналами;
  • config.py — конфигурационный файл (КФ);
  • display.py — содержит класс, отвечающий за вывод информации на OLED-дисплей;
  • [images] — директория с иконками событий и рисунками для анимации;
  • __init__.py — скрипт инициализации модуля;
  • leds.py — класс для управления RGB-светодиодом;
  • menu.py — генерация и вывод пунктов меню;
  • rrouter.py — основной файл программы, запускатся и работает как фоновый процесс;
  • ssd1306.py — драйвер для OLED-дисплея SSD1306;
  • sysinfo.py — класс для сбора и вывода на экран системной информации;
  • usrinfo.py — класс для сбора и вывода на экран пользовательской информации (в данном случае курсов валют и криптовалют).

Файловая структура директории со скриптами

Рис. 5. Файловая структура директории со скриптами.

Хранить программу на малинке я предлагаю в домашней директории пользователя по умолчанию. Допустим что папка ‘rrouter’ из архива скопирована в домашнюю директорию пользователя ‘pi’ — «/home/pi/».

Перед использованием программы необходимо еще установить два питонных модуля:

  • beautifulsoup4 — для парсинга HTML-документов;
  • daemonize — для возможности выполнения программы в фоновом режиме как отдельный процесс со своими атрибутами;
  • requests — для выполнения HTTP-запросов к сайтам с курсами валют.
sudo pip3 install beautifulsoup4 daemonize requests 

Об использовании daemonize я уже рассказывал в одной из статей о безопасном завершении работы Raspbian нажатием на физическую кнопку.

Назначение переменных в конфигурационном файле:

  • pins — содержит список названий и соответствующих каналов GPIO;
  • ssd1306_12c_address — адрес модуля SSD1306 на шине I2C;
  • sounds_is_on — разрешить/запретить звуковые сигналы по умолчанию;
  • aminations_is_on — разрешить/запретить отображение анимаций по умолчанию;
  • animation_sets — набор из названий анимаций, которые должны отображаться в режиме простоя;
  • idle_time_to_sleep — время бездействия (после нажатия на одну из кнопок) для очистки экрана.

Выполним запуск программы с возможностью отладки и с выводом возможных ошибок в консоли:

/home/pi/rrouter/rrouter.py --manual

Безопасно прервать выполнение программы можно с помощью комбинации клавиш CTRL+C.

Если все хорошо, то перейдем к созданию systemd-юнита для автоматического запуска скрипта при старте операционной системы.

sudo nano /etc/systemd/system/rrouter-script.service

Содержимое юнита:

[Unit]
Description=Raspberry Pi router daemon
After=network.target

[Service]
Type=oneshot
User=root
ExecStart=/home/pi/rrouter/rrouter.py
ExecStop=/bin/kill -2 $MAINPID
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Разрешим запуск службы:

sudo systemctl enable rrouter-script.service

Запускаем, проверяем статус, если нужно останавливаем:

sudo systemctl start rrouter-script.service
sudo systemctl status rrouter-script.service
sudo systemctl stop rrouter-script.service

Перезапускаем малинку и проверяем запущен ли скрипт и правильно ли он выполняет свои функции.

Зная язык программирования Python вы можете модифицировать или дорабоатть скрипт так, как вам необходимо под ваши задачи или же просто в самообразовательных целях.

Другие полезности

Я заметил что иногда малинка отказывается нормально загружаться с первого раза, подключив дисплей к HDMI видео-выходу я увидел что процесс загрузки остановился на следующих строчках:

[  OK  ] Started /etc/rc.local Compatibility.
[  OK  ] Started Permit User Sessions.
         Starting Light Display Manager...
         Starting Hold until boot process finishes up...
         Starting Terminate Plymouth Boot Screen...

Как видим все зависло на этапе завершения процесса Plymouth Boot Screen. Пакет Plymouth нужен для возможности наблюдать красивый экран загрузки с разными лого и в высоком разрешении.

Малинка в режиме сервера/роутера отлично работает без подключенного дисплея, обычного экрана загрузки в текстовом режиме вполне хватит для информативных целей, было принято решение удалить пакет plymouth:

sudo apt-get remove plymouth

Теперь желательно перезагрузить малинку несколько раз и убедиться что все ОК.

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

startx

Для защиты сервера на Raspberry Pi от перебора паролей по SSH из внутренних сетей (подключения через интерфейсы интернета фильтруются файрволом) можно установить fail2ban:

sudo apt-get install fail2ban

Конфигурация по умолчанию уже настроена на мониторинг попыток перебора паролей для демона SSHD, здесь настраивать больше ничего не нужно.

Для теста скорости интернета можно установить программу speedtest-cli:

sudo apt-get install speedtest-cli

Запускаем:

speedtest-cli

Программа выполнит тесты и отобразит максимальную скорость скачивания и отдачи для активного в данный момент канала интернет, вот пример вывода данных:

Testing download speed......................
Download: 57.26 Mbit/s
Testing upload speed........................
Upload: 59.87 Mbit/s

В моем случае, роутер на основе Raspberry Pi и подключенного адаптера USB-Ethernet позволил получать стабильные 100 МБит  (примерно 12МБ/сек) при закачивании файлов с внутренней сети интернет-провайдера без значительных скачков и падений скорости.

Для тестирования производительности микропроцессора и памяти Raspberry Pi можно воспользоваться пакетом sysbench. Он позволит оценить разницу в производительности разных версий малинки, а также примерно сопоставить их с произвоительностью настольных систем для оценки возможности запуска различного ресурсоемкого ПО. Установим пакет:

sudo apt-get install sysbench

Запуск быстрого теста производительности CPU в 4 потока (в процессоре малинке 4 ядра):

sysbench --test=cpu --num-threads=4 run

По завершению работы программы в консоли будут выведены результаты теста, здесь нам наиболее интересна строчка «total time». В моем случае (Raspberry Pi 3 model B — ARMv7 Processor rev 4) тест завершился за 35,1910 секунд, если же его запустить в один поток то он выполнится примерно за 140 секунд.

Вот мы и имеем приблизительную цифру для оценки производительности CPU и сравнения ее с другими системами. Например, такой же тест на одном ядре (1 поток) микропроцессора Intel(R) Xeon(R) CPU E3-1241 3.50GHz будет завершен примерно за 9 секунд, здесь можно судить так: чтобы получить примерно такую же производительность нужен кластер из 4-х четырехядерных малинок.

Но опять же, здесь нельзя ставить в один ряд обычный серверный/десктопный процессор и микропроцессор на архитекутре ARM — у них разные возможности, наборы инструкций и разное назначение.

А теперь запустим тесты для определения скорости чтения и записи в оперативную память с различными размерами блоков (1КБ, 32КБ и 64КБ):

sysbench --test=memory --memory-block-size=1K --memory-scope=global --memory-total-size=1G --memory-oper=read run
sysbench --test=memory --memory-block-size=32K --memory-scope=global --memory-total-size=1G --memory-oper=read run
sysbench --test=memory --memory-block-size=64K --memory-scope=global --memory-total-size=1G --memory-oper=read run
sysbench --test=memory --memory-block-size=1K --memory-scope=global --memory-total-size=1G --memory-oper=write run
sysbench --test=memory --memory-block-size=32K --memory-scope=global --memory-total-size=1G --memory-oper=write run
sysbench --test=memory --memory-block-size=64K --memory-scope=global --memory-total-size=1G --memory-oper=write run

Результаты теста на моей малинке:

  • READ (1K) — 740.49 MB/sec;
  • READ (32K) — 11601.80 MB/sec;
  • READ (64K) — 22536.72 MB/sec;
  • WRITE (1K) — 544.77 MB/sec;
  • WRITE (32K) — 1829.46 MB/sec;
  • WRITE (64K) — 1957.27 MB/sec.

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

Чтобы оценить производительность микропроцессора и системы вцелом при выполнении различных операций (плавающая запятая, архивация, работа с MySQL и т.п.) можно воспользоваться комбайном под названием Phoronix Test Suite, который на данный момент поддерживает около 450 различных тестов и более 100 готовых наборов с тестами.

Доработки, установка других сетевых служб, усложнение сети

Здесь приведена достаточно простая схема реализации домашнего роутера (маршрутизатора). В ней нет вложенных сетевых туннелей, сложных правил маршрутизации, разбора пакетов по содержимому, сетевых служб работающих с разными более сложными и даже вложенными протоколами и т.п.

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

Если вам нужно прикрутить к роутеру из этой статьи: TOR, OpenVPN, RedSocks, Squid, LXC, Docker, Shadowsocks, Stunnel и т.п., то будьте готовы к тому, что придется самостоятельно разбираться и решать разными путями проблемы, который могут возникнуть в процессе какой либо достройки и/или обновления ПО, с учетом и пониманием того как изначально все настроено.

Все будущие доработки данной конфигурации с моей стороны, если на это появится надобность и желание, скорее всего будут оформлены в виде отдельных детально проработанных статей.

Устранение неполадок

В процессе эксплоатации может возникнуть ряд неисправностей, например по какой-то причине откажется стартовать какая-то служба и т.п.

Статус всех основных служб, которые мы настраивали в статье, можно посмотреть командами:

# DHCP-клиент
sudo systemctl status dhcpcd
# Служба для организации WLAN точки доступа
sudo systemctl status hostapd
# Самописный скрипт для IPTables
sudo systemctl status iptables
# DHCP-сервер от ISC
sudo systemctl status isc-dhcp-server
# Самописный скрипт для контроля интерфейсов ISC DHCP сервера
sudo systemctl status isc-watchdog
# Самописный скрипт для синхронизации времены с апаратными часами
sudo systemctl status i2chwclock
# Программа управления роутером написанная на Python
sudo systemctl status rrouter-script

Если какая-то служба не смогла запуститься то можно попробовать остановить/запустить ее вручную, вот пример для ‘rrouter-script’:

sudo systemctl stop rrouter-script
sudo systemctl start rrouter-script

Бывает что в следствии неконтроллируемых выключений и перезагрузок роутера (например пропадало электричество) какая-то из служб не смогла запуститься и даже ручной запуск не помогает.

В этом случае необходимо внимательно изучить вывод команды что показывает статус службы.

Для примера, если в статусе службы ‘isc-dhcp-server’ нашлась вот такая строчка:

Nov 28 19:24:06 rrouter isc-dhcp-server[720]: Segmentation fault

Видим здесь ошибку сегментации памяти — «Segmentation fault». Это значит что служба не смогла запустить бинарный файл, поскольку он не правильно обращается к памяти или же поврежден.

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

В таком случае, можно попробовать несколько раз перезагрузить малинку, как правило если разделы Linux были не корректно размонтированы перед выключением то при следующем старте ОС запустится программа проверки и исправления ошибок на диске — fsck (не сложно запомнить — от FileSystemChecK).

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

Чтобы программа fsck в принудительном порядке на этапе запуска Raspbian начала проверку подключенных устройств хранения данных на ошибки достаточно отредактировать файл:

sudo nano /boot/cmdline.txt

Там увидим длинную строку, в нее нужно добавить следующую директиву:

 fsck.mode=force

Например, частично эта строка с добавленной директивой может выглядеть вот так:

... rootfstype=ext4 elevator=deadline fsck.mode=force fsck.repair=yes rootwait

Директивы fsck:

  • «fsck.repair=yes» указывает что при наличии ошибок на диске на запрос о их исправлении нужно отвечать утвердительно — y/yes!
  • «fsck.mode=force» дает системе понять что проверку дисков нужно запускать в любом случае обязательно.

Сохранив изменения достаточно перезагрузить ОС командой:

reboot

После запуска снова проверяем статус всех служб, есть большая вероятность что теперь все будет в порядке!

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

Например если в логах увидели ‘I/O error’ или еще что-то подобное, связанное с картой памяти ‘mmcblk0’, то скорее всего она уже изношена и требует замены.

Команды для просмотра журналов системы, лог с момента последнего запуска ОС:

dmesg
sudo journalctl -b

В завершение

О питании роутера и коммутатора я уже рассказал в предыдущей статье по данному проекту, но думаю не лишним будет еще раз здесь упомянуть.

Для надежной работы Raspberry Pi необходим хороший и стабильный источник питания с постоянным напряжением +5В, иначе возможны периодические хаотические зависания системы и сбои.

Поэтому не пожалейте на него 10-15$, а также будет замечательно если перед ним будет стоять еще и источник бесперебойного питания. К тому же, весь комплект (малинка+свитч) можно питать от аккумуляторного блока (PowerBank), имеющего два порта USB по +5В и током не менее 2А. В качестве примера такого пауербанка, из не дорогих, можно привести: «Trust Urban» (2USB x 2,4A = total 4,8A)

Cо всем уважением, прошу не писать в комментариях просьб и вопросов наподобие: «а как настроить на малинке service_1+service_2+protocol_X+Z» или «опишите как связать сеть A с сетями B-C через шифрованные туннели с авторизацией и метриками» и т.п.

Я бы рад здесь привести руководства по настройке всевозможных служб и сетевых конфигураций, чтобы помочь людям, но на это все просто физически не хватит времени чтобы изучить, опробовать, отладить и описать. К тому же, ждут своей очереди к публикации еще и другие интересные статьи разного направления.

Пожалуйста, оставляйте комментарии с замечаниями и вопросами строго по теме статьи!

Краткое видео с демонстрацией меню программы:

Вот такой получился занимательный проект, надеюсь было не скучно. Желаю всем креативных идей и творческих успехов!

Полезные ссылки:

  1. Decibel — dB (wikipedia)
  2. List of WLAN channels (wikipedia)
  3. wiki.archlinux.org — Resolv.conf
  4. Список AT-команд для модемов (M2M SUpport Forum)
  5. RTTTL (wikipedia)
  6. What’s wrong with the Raspberry Pi (OWN YOUR BITS, technology with a focus on OpenSource)

Высокоскоростной Интернет разделил людей на две группы: одни подписываются на стриминговые сервисы, другие предпочитают по старинке хранить собственные копии фильмов и альбомов на жестком диске, особенно если это касается редких релизов, которых не найти онлайн. Но Netflix или Spotify легко запустить с любого устройства, а как получить доступ к файлам, хранящимся на диске, с телевизора или смартфона? Для этого нужно организовать домашний медиасервер. Это намного проще, чем кажется, и осуществимо даже стандартными средствами Windows.

Домашний медиасервер позволяет подключить все доступные устройства в единую беспроводную сеть и организовать общий доступ к музыке и фильмам на жестком диске, флешке и SD-карте. Это избавляет от необходимости хранить по копии фильма или альбома на ПК, планшете, смартфоне, ноутбуке и в памяти ТВ — достаточно будет одной копии на медиасервере.

Медиасервером можно сделать множество девайсов: 

  • Компьютер: актуальна рабочая станция или старый ПК
  • Роутеры с поддержкой DLNA
  • Микрокомпьютер
  • ТВ-Боксы
  • NAS (Network Attached Storage — сетевое хранилище)

По своей сути, все эти устройства представляют собой компьютер с процессором, видеоядром, оперативной памятью и диском для хранения файлов. Чтобы превратить их в медиасервер, нужна технология высокоскоростной передачи контента в режиме реального времени. Она называется DLNA.

DLNA представляет собой набор стандартов для объединения поддерживающих эту технологию устройств в единую домашнюю сеть для передачи медиаконтента. Чаще всего это телевизоры, принтеры, плееры и ресиверы, а также портативная техника — смартфоны, планшеты, ноутбуки и т. д. Многие производители используют DLNA в своих экосистемах под брендовыми названиями:

  • Samsung — Allshare
  • LG — SmartShare
  • Philips — Simple Share

Аналогом также является Apple AirPlay, однако он использует иные протоколы и работает только с устройствами Apple. 

Проще всего подружить медиасервер с ТВ, если последний поддерживает DLNA. В ином случае поможет подключение с помощью ТВ-бокса или микрокомпьютера.

Домашний медиасервер можно организовать на рабочем ПК. Понадобится лишь роутер и устройство с поддержкой DLNA, например, телевизор.

Если ТВ и ПК объединены одной домашней сетью, Windows 10 позволяет без лишних настроек передавать контент напрямую на устройство. Достаточно щелкнуть по файлу правой кнопкой мыши и выбрать нужный девайс из списка во вкладке «Передать на устройство» («Cast to device»).

Чтобы не кликать каждый раз по файлам на ПК, а выбирать их сразу с ТВ или планшета, понадобится настроить DLNA-сервер: 

  1. Открыть параметры потоковой передачи мультимедиа и включить эту функцию.
  2. Дать название своему серверу и открыть доступ нужным устройствам.
  3. Кликнув «Настроить» при выборе девайса, можно открыть передачу того или иного типа контента.

Теперь на ТВ и портативных устройствах появится доступный медиаконтент. Однако он будет в неотсортированном виде, хранить так сотни фильмов и альбомов невозможно. Понадобится настройка папок и категорий. Их возможно упорядочить даже с помощью Windows Media Player 11 и выше: щелкнуть правой кнопкой по разделу «Видео», выбрать «Управление видеотекой» и добавить в список папки с заранее отсортированными роликами. Аналогично с фото и музыкой.

Наконец, DLNA-сервер легко организовать с помощью программ, которые иногда называют медиацентрами. Они позволяют:

  • Упорядочивать медиатеку по любым категориям: исполнители, режиссеры, актеры, год выпуска и т. п.
  • Автоматически подгружать метаданные: достаточно загрузить файл с фильмом, чтобы программа сама подобрала к нему обложку, описание, список актеров и т. д.
  • Работать с субтитрами, плейлистами и любыми форматами видео, аудио и изображений.
  • Делать транскодинг — то есть перекодировать старый видеофайл в современный формат, удобоваримый для ТВ, либо превратить фильм на 50 Гб в 5 Гб, чтобы смартфон не зависал при его просмотре.

Существует множество медиацентров, самые популярные из них:

  • Kodi
  • Plex
  • Домашний медиа сервер (DLNA, UPnP, HTTP)
  • Samsung Smart View
  • Serviio

Минус организации медиасервера на ПК в том, что придется постоянно держать его включенным, чтобы все работало. Плюс программа медиацентра будет отнимать часть ресурсов, особенно при транскодировании. Можно, конечно, использовать отдельную машину, например, старый компьютер, но возможности системы будут ограничены его производительностью: далеко не каждый старый ПК сможет без лагов воспроизводить видео в 4К на ютубе. 

Некоторые роутеры с USB или SATA-разъемом умеют подрабатывать медиасервером. В характеристиках роутера должна быть указана функция DLNA-сервера. Также понадобится минимум 128 Мб оперативной памяти (лучше 256 Мб). Если сеть Wi-Fi слишком загружена в диапазоне 2.4 ГГц, пригодится двухдиапазонный роутер. Он поможет избежать потери пакетов, которые будут выражаться в лагах и фризах. Для нормальной работы скорость соединения должна быть не ниже 60 Мбит/с.

Обычно настроить DLNA на роутере можно прямо в его веб-интерфейсе: нужно включить саму функцию и выбрать папки с контентом. Далее можно подключать к нему смартфоны и телевизоры. Главное преимущество в простоте решения, но есть и недостатки:

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

Что, если телевизор недостаточно умный и не поддерживает DNLS? Тогда можно подключить к нему дополнительное устройство, к примеру, ТВ-бокс. Они поддерживают DLNS и предоставляют возможность загружать на флешку или SD-карту свои медиафайлы, чтобы просматривать их с ТВ, а иногда и других устройств. Более того, Андроид дает этим приставкам функциональность смартфона или планшета, позволяя устанавливать на них приложения, пользоваться стриминговыми сервисами, ютубом, играть в игры и т. д.

ТВ-боксом легко пользоваться: настройка под себя не отнимет много времени, и для большинства покупателей его возможностей будет достаточно. Но есть и минусы:

  • Недостаточная производительность. Пользователи жалуются на тормоза и лаги у приставок со слабым процессором, поэтому нужно внимательно смотреть характеристики и отзывы.
  • Перегрев, приводящий к троттлингу. Бюджетные модели оснащаются весьма скромным охлаждением. В итоге процессор при высокой нагрузке (например, игры или просмотр видео с транскодированием) достигает критических температур и сбрасывает частоты, теряя производительность, чтобы не сгореть. 
  • Некоторые устройства не поддерживают подключение жесткого диска, а на флешке или SD-карте помещается не вся медиатека.

Любители DIY могут сделать медиасервер на базе микрокомпьютера Raspberry Pi, ASUS Tinker Board или похожего. Такие обычно поставляются в виде платы без корпуса, на которой установлен ARM-процессор, ОЗУ, видеокарта, модули Wi-Fi и Bluetooth, порты USB, HDMI и Ethernet. Соответственно, к нему можно подключить почти любой ТВ и даже внешнюю звуковую карту.

Это позволяет точно подобрать модель по характеристикам под свои задачи и самостоятельно сконструировать корпус и систему охлаждения. К микрокомпьютерам можно подключить и SD-карты, и HDD (как USB, так и SATA через переходник). Мощности Raspberry Pi 3 Model B+ хватает, чтобы проигрывать фильмы в высоком разрешении и видео в 4K на ютубе. 

Чтобы превратить микрокопьютер в медиасервер, понадобится:

  1. Подключить к микрокомпьютеру блок питания, ТВ или монитор и, желательно, кулер для охлаждения.
  2. Установить с загрузочной SD-карты ОС-медиацентр Kodi (например, с помощью сборки LibreELEC, устанавливающейся автоматически). Сборка поддерживает русский язык и уже содержит в себе медиаплеер, позволяет устанавливать приложения, смотреть ютуб и все остальное.
  3. В настройках LibreElect (вкладке Network) активировать Wireless Access Point и задать пароль для сети.

Тем, кто не хочет заниматься конструированием корпуса и охлаждения, подойдет микрокомпьютер типа Intel Compute Stick. На него можно установить Windows 10 и работать хоть с привычными офисными приложениями, хоть с фотошопом, поэтому такая штука все чаще появляется в офисах. Соответственно, можно установить на него программу и использовать его в качестве медиацентра. Однако мощностей процессора Intel Atom x5 Z8330 1440 МГц не хватает для просмотра видео 4К, по крайней мере, в ОС Windows.

Сегодня появилась целая категория компьютеров-флешек и неттопов. Также есть чуть менее компактные платформы для ПК. Однако модели с мощным процессором стоят уже в одной ценовой категории с профессиональным решением для организации медиасервера — сетевым хранилищем или NAS.

NAS — это сетевые хранилища. Их предназначение — доставлять файлы так быстро, как это возможно. Но главное, что они позволяют подключить сразу несколько жестких дисков с возможностью моментально заменять их. Это позволяет организовать домашнюю медиатеку исполинских масштабов с фильмами в 4К и альбомами в Hi-Res.

Чтобы использовать NAS в качестве медиацентра, нужно внимательно изучить характеристики. Понадобится мощный процессор (хотя бы 2, а лучше 4 ядра) и ОЗУ объемом не меньше 2 Гб. Тогда не будет лагов при транскодинге и просмотре 4К. Многие модели позволяют добавить оперативки и улучшить скорость работы благодаря SSD и организации на нем кэш-памяти для быстрого доступа к часто используемым файлам.

Желательно подключить к NAS жесткий диск, заточенный под длительную работу нон-стоп. Для таких задач производители выпускают оптимизированные для NAS винчестеры.

В качестве ОС можно использовать Kodi, Plex, emby и другие. Однако главный недостаток NAS в том, что они созданы с оглядкой на продвинутых пользователей, поэтому настройка потребует определенных знаний и терпения.

Заключение

Медиасервер позволяет не только организовать гаджеты в удобную домашнюю экосистему, но и через Интернет открыть доступ к файлам в хранилище из любой точки земного шара. Так можно настроить собственный стриминг-сервис, чтобы слушать свою музыку и смотреть свои фильмы с портативного устройства везде, где позволяет скорость сети.

  • Дома беспроводной роутер дом ру
  • Домашний медиа сервер настройка роутера
  • Домашний интернет с роутером и приставкой
  • Дом ру уфа аренда роутера
  • Домашний интернет билайн со своим роутером