Всё началось с того, что меня достал мой роутер.
Кинетики, конечно, хорошие, но всё чаще он начал тормозить, требовать перезагрузки, веб-интерфейс начинал отвечать ооочччеееень мееедлееенннооооооо....
И не сказать чтобы трафик большой.
Но надо было что-то делать: то ли покупать новый, то ли пытаться перепрошить старый, например на OpenWRT - но без гарантий что это как-то поможет. Ведь как ни крути - ограниченный обьем памяти, "диска", слабый процессор.
К тому же, OpenWRT хоть и Линукс, но достаточно нестандартный, заточенный как раз под такие конфигурации.
А что, если как раньше, до появления WiFi-роутеров?
Когда-то в качестве роутера для домашней локальной сети некоторые использовали отдельный (старый) компьютер: там настраивался софт, который занимался дозвоном до провайдерского пула, раздавал адреса и трафик...
Вот только сейчас вместо старого шумного системного блока можно использовать маленькую аккуратную коробочку TV-бокса (или даже просто старый ноутбук - но TV-бокс помощнее будет).
К тому же на нем можно сразу настроить ТСПУ(б) - технические средства противодействия угрозам блокировок. Но это уже другая история.
Итак, архитектура решения вырисовывается следующая:
- мини-компьютер с линуксом, в данном случае Debian на arm64, но это непринципиально
- к локальной сети он подключается через единственный имеющийся у него ethernet-порт
- входящие подключения, аплинки - оптика от провайдера, сотовый интернет через операторов - все через usb-адаптеры
- раздача WiFi в локальной сети - через "точки доступа".
Забегая вперед - так оказалось даже лучше.
Установка самой ОС зависит от конкретного устройства, для ноутбука - по-своему, для коробочки TV-бокса или там RaspberryPI - по-своему.
Это не принципиально, главное получить в результате полноценный линукс, в котором можно устанавливать любые стандартные программы, и собирать нестандартные.
Прежде всего, требуется зафиксировать IP-адрес роутера, например, так:
(разумеется, всякие NetworkManager-ы лучше отключить, во избежание самодеятельности)
vim /etc/network/interfaces
----------------------
auto end0
iface end0 inet static
address 192.168.1.5
netmask 255.255.255.0
----------------------
Адрес 192.168.1.5 - чисто для примера, он не обязан быть каким-то конкретным, это просто адрес этого роутера в сети.
Маршрута по умолчанию default route тут нет, потому что всё это будет настраиваться в процессе.
Вообще, это настроечный файл от интересной системы: по идее в него должны вноситься разные интерфейс с указанием их настроек - какие получают адреса по dhcp, какие указываются статически, какие должны настраиваться автоматом при загрузке, а какие - при появлении.
При этом также выполняются скрипты из каталогов типа /etc/network/if-up.d/ - if-down.d
Это позволяет собрать однотипные скрипты для разных интерфейсов в одном месте, иногда это удобно.
Например, в данном случае настраивается встроенный сетевой интерфейс, статически, с указанием о том что это произойдет автоматически при загрузке.
Но можно было бы и вручную, командами ifup - ifdown, или вообще ip link / ip addr.
Пока этого достаточно, но к этому файлу еще вернемся.
Следующий этап - настройка DNS.
Тут без оригинальности, обыкновенный bind9, он же named:
apt install bind9Прописываем домашние компьютеры с фиктированными адресами (необязательный шаг):
vim /etc/bind/named.conf.local
zone "home" {
type master;
file "/etc/bind/db.home";
allow-query { any; };
};
vim /etc/bind/db.home
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA gate.home. root.gate.home. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS gate.home.
gate IN A 192.168.1.5
k2 IN A 192.168.1.6
printer IN A 192.168.1.2
....
Тут в общем-то особо нечего настраивать. так как в локальной сети это единственный DNS-сервер.
Ну можно в качестве лайфхака в поле Serial при каждом изменении писать текущую дату, например 2511111835, это гарантирует что serial будет каждый раз новый.
Но вряд ли это нужно в локалке.
Теперь некоторые другие настройки:
vim /etc/bind/named.conf.options
options {
directory "/var/cache/bind";
//forwarders {
// 8.8.8.8;
//};
//forward only;
dnssec-validation auto;
listen-on port 53 { 192.168.1.5; };
deny-answer-addresses {
10.0.0.0/8;
127.0.0.0/8;
169.254.0.0/16;
172.16.0.0/12;
192.168.0.0/16; };
};
То есть, слушаем запросы только на внутреннем IP, и заодно блокируем возможность прислать нам подменные адреса на наши же внутренние системы (на эту тему тут была как-то статья).
Смысл локального DNS-сервера, во-первых, в хранении имен для некоторых локальных устройств, чтобы не запоминать, а во-вторых - кеширование ранее полученных, на всякий случай.
Можно еще настроить форвардинг для запросов на удаленный защищенный сервер - если пустить трафик к нему по защищенному каналу. Тут он закомментирован.
Остается добавить:
vim /etc/resolv.conf
nameserver 192.168.1.5
Теперь все запросы обрабатываются через собственный DNS-сервер.
Раздача адресов и настроек по локальной сети - через DHCP.
По ряду причин используется udhcpd - это DHCP-сервер, "встроенный" в busybox, который в свою очередь понадобится чуть позже, так что лучше сразу его и использовать:
apt install udhcpdНастраивается он одним файлом:
vim /etc/udhcpd.conf
start 192.168.1.20
end 192.168.1.254
interface end0
option domain home
opt dns 192.168.1.5
option subnet 255.255.255.0
opt router 192.168.1.5
option lease 864000 # default: 10 days
#static_lease 00:60:08:11:CE:3E 192.168.0.44 optional_hostname
Нужно не забыть включить этот демон в /etc/default/udhcpd:
DHCPD_ENABLED="yes"Периодически демон сбрасывает информацию о выданных адресах в файл, указанный в ��онфиге, по умолчанию /var/lib/misc/udhcpd.leases
Демон изначально рассчитан на встроенные системы, поэтому пишет "на диск" по-минимуму.
Заставить его принудительно это сделать можно отправкой сигнала USR1:
kill -SIGUSR1 <pid>Посмотреть, что он там понавыдавал можно командой dumpleases - это может быть полезно, если нужно понять что там есть в сети и с какими MAC-адресами.
В общем-то уже можно с этим работать: сервер выдаст IP-адрес, и ответит на DNS-запрос, особенно для локальных устройств в сети home
Теперь самое главное - подключение интернета.
Одна из самых полезных фишек Кинетика - умение автоматически переключать каналы с основного на резервный. Примерно то же самое сделаю и тут.
Для этого существуют разные способы, включая специальное ПО - но тут можно обойтись простыми скриптами.
Логика будет простая:
- создается список каналов - аплинков, для каждого устанавливается приоритет, метрика.
- при подключении любого канала создается запись в специальном каталоге, по которой можно идентифицировать канал и интерфейс. Если такой есть в списке - для него создается default route с заданной метрикой
- специальный скрипт периодически проверяет доступность канала, пингуя один и тот же IP-адрес
- если пинг прошел - приоритет сохраняется, если не прошел - меняется на приоритет в 10 раз больше, то есть технически канал по-прежнему в списке, но по факту выключен из маршрутизации.
- если интерфейс отключен - он автоматически будет исключен из проверяемых, а маршрут через него удален.
Для этого создается список /etc/uplinks.conf, а временные файлы будут создаваться в /run/uplinks, который смонтирован из tmpfs, то есть по сути в памяти.
Такая схема позволяет контролировать любые аплинки, независимо от того как именно они реализованы.
Основной провайдер - оптика, GPON, которая заходит в операторский модем.
Доступ к настройкам этого модема у абонентов отсутствует, хотя у техподдержки удаленно он есть.
Значит, по умолчанию они могут делать с его помощью что угодно, хоть сканирование сети - поэтому подключать его напрямую в локальную сеть не стоит, да и незачем, всё равно реальный выход в интернет - через PPPoE.
Второго ethernet-порта в девайсе нет, но есть два USB: один из них можно задействовать под USB-сетевую карту.
При этом в системе появляется сетевой интерфейс типа enx00e099199d7f.
Кинетик в данном случае поступал стандартно: получал через DHCP адрес на этом интерфейсе, потом устанавливал PPPoE соединение.
Но зачем там IP адрес, если он всё равно не используется, а PPPoE работает на уровне L2, через ethernet? Достаточно сделать интерфейс активным, а потом использовать стандартную программу pppd.
Для работы с PPPoE есть даже специальная программа, pppoe, но соединение с ее помощью то рвалось, то не устанавливалось вообще, поэтому лучше оказалось использовать стандартный плагин rp-pppoe.so:
vim /etc/ppp/peers/optic
plugin rp-pppoe.so enx00e099199d7f
user <username>
noauth
mtu 1490
mru 1490
noipdefault
nodefaultroute
persist
maxfail 0
holdoff 10
ifname optic
Важный нюанс - поле mtu: PPPoE "отъедает" под заголовки часть стандартного пакета 1500, поэтому его необходимо уменьшить, чтобы работало.
Но слишком сильно уменьшать нельзя, будет тормозить.
/etc/ppp/option - делаем пустым, чтобы не мешало ничего
/etc/ppp/pap-secrets и /etc/ppp/chap-secrets одинаковые:
<username> * <password> *Настроим NAT:
/etp/ppp/ip-up.d - убрать оттуда всё лишнее понаставленное пакетами без спроса, добавить свой скрипт:
vim /etp/ppp/ip-up.d/set-masq
--------------------------------------
#!/bin/sh
if [ "x$PPP_IFACE" != "x" ] ; then
iptables -t nat -A POSTROUTING -o "$PPP_IFACE" -j MASQUERADE
iptables -t mangle -A FORWARD -o "$PPP_IFACE" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -A FORWARD -o "$PPP_IFACE" -j ACCEPT
iptables -A FORWARD -i "$PPP_IFACE" -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i "$PPP_IFACE" -j DROP
fi
--------------------------------------
chmod 755 /etp/ppp/ip-up.d/set-masq
Скрипт на отключение:
vim /etp/ppp/ip-down.d/del-masq
----------------------------------
#!/bin/sh
if [ "x$PPP_IFACE" != "x" ] ; then
iptables -t nat -D POSTROUTING -o "$PPP_IFACE" -j MASQUERADE
iptables -t mangle -D FORWARD -o "$PPP_IFACE" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -D FORWARD -o "$PPP_IFACE" -j ACCEPT
iptables -D FORWARD -i "$PPP_IFACE" -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -D FORWARD -i "$PPP_IFACE" -j DROP
fi
----------------------------------
chmod 755 /etp/ppp/ip-down.d/del-masqЗапускаем:
ip link set dev enx00e099199d7f up
pppd call optic
ip addr
optic: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1490 qdisc pfifo_fast state UNKNOWN group default qlen 3
link/ppp
inet 10.12.13.14 peer 10.14.22.33/32 scope global ppp0
valid_lft forever preferred_lft forever
Установка маршрута по умолчанию запрещена, поэтому для теста его нужно установить вручную:
ip route add default via 10.14.22.33 dev ppp0
ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=109 time=18.2 ms
Интернет заработал, хотя пока что это "восход солнца вручную". Так надо.
По умолчанию мы не знаем, подключена ли эта сетевая карта, если ли там что-то "с той стороны" - поэтому настраиваем автоподключение.
Первоначальный вариант предполагал запуск всего через udevd, но тут выяснилось, что оно почему-то не работает, не может ничего запустить (хотя на машине без systemd всё работает как ожидается).
Уговаривать не хотелось, поэтому вопрос был решен в лоб:
По крону запускается скрипт:
/usr/local/bin/start_pppoe
#!/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH
export HOME=/root
log=/var/log/ppp/pppoe.log
# имя "сетевой карты", через которую устанавливается соединение
INTERFACE='enx00e099199d7f'
# проверка наличия - т.к. она может быть не подключена
ip link show dev $INTERFACE > /dev/null 2>&1
if [ $? -eq 1 ]; then
exit 0
fi
# проверка активности (по наличию local link ipv6), если нет - поднимаем
ip -6 addr show dev $INTERFACE | grep 'inet6 fe80:' > /dev/null 2>&1
if [ $? -eq 1 ]; then
ip link set dev $INTERFACE up
sleep 2
fi
# проверка работы нужного pppd
ps ax| grep -v grep | grep 'pppd call optic' > /dev/null 2>&1
if [ $? -eq 0 ]; then
exit 0
fi
echo "Start PPPoE for $INTERFACE" >> $log
/usr/sbin/pppd call optic
sleep 2
Если карты нет - выход, если есть неактивная - поднимаем, если нет еще pppd - запускаем, ждем 2 сек и выходим.
Следующий запуск - pppd будет на месте, второго запуска не будет.
Но в случае чего - pppd запустится повторно.
В системе при этом появляется сетевой интерфейс optic с выданными ему IP-адресами.
Кстати, в том же /etc/network/interfaces можно было бы указать виртуальный интерфейс типа ppp, и запускать его командой ifup - но тут есть тонкий нюанс: после этого соответствующие программы ifup-ifdown будут считать что интерфейс активен - но если по какой-то причине pppd не будет работать, то возникнет несоответствие между ожиданием и реальностью.
Проверка наличия процесcа по факту наличия самого процесса - гораздо надежнее.
Теперь сотовые модемы:
Про установку Olax уже писал: эфирная MIMO-антенна, наведение на сотовую вышку, подбор диапазона и т.д.
При подключении по USB в системе создается сетевой интерфейс, на который по DHCP модем выдает адрес. При настройке маршрута через модем - работает интернет.
То есть, нужно отслеживать появление в системе нужного сетевого интерфейса, поднять его, получить IP-адрес от модема, причем только IP-адрес, не затрагивая остальные настройки, и настроить маршрут.
Так получилось, что поиск в залежах старого хлама дал несколько еще рабочих USB-модемов.
Их удалось подлечить, установить симкарты и использовать вместе с новым - в качестве эксперимента, "почему бы и нет?"
Правда, свободный USB-порт оставался один - но есть ведь USB-хабы?
Таким образом получаем еще 4 порта.
Два Huawei E3372h-153, Hilink, полностью одинаковые.
Каждому своя антенна и своя вышка, в разных направлениях.
Как и Olax - они при подключении выглядят как сетевые карты, на которые можно получить от модема адрес, настроить маршрут - в общем всё так же.
Для Olax это 192.168.100.0/24, для Hilink по умолчанию 192.168.8.0/24, но можно через вебинтерфейс поменять например на
Теперь сотовые модемы
Про установку Olax уже писал: эфирная MIMO-антенна, наведение на сотовую вышку, подбор диапазона и т.д.
При подключении по USB в системе создается сетевой интерфейс, на который по DHCP модем выдает адрес.При настройке маршрута через модем - работает интернет.
То есть, нужно отслеживать появление в системе нужного сетевого интерфейса, поднять его, получить IP-адрес от модема, причем только IP-адрес, не затрагивая остальные настройки, и настроить маршрут.
Так получилось, что поиск в залежах старого хлама дал несколько еще рабочих USB-модемов.
Их удалось подлечить, установить симкарты и использовать вместе с новым - в качестве эксперимента, "почему бы и нет?"
Правда, свободный USB-порт оставался один - но есть ведь USB-хабы? Таким образом получаем еще 4 порта.
Два Huawei E3372h-153, Hilink, полностью одинаковые. Каждому своя антенна и своя вышка, в разных направлениях.
Как и Olax - они при подключении выглядят как сетевые карты, на которые можно получить от модема адрес, настроить маршрут - в общем всё так же.
Для Olax это 192.168.100.0/24, для Hilink по умолчанию 192.168.8.0/24, но можно через вебинтерфейс поменять например на 192.168.9.0/24 - так получаем три разных сети для трех разных модемов.
Нюанс тут вот в чем: Olax создает свой интерфейс, который система переименовывает под его MAC-адрес (предсказуемые имена устройств, то, сё), и оба Hilink-а создают свои интерфейсы, которые система тоже пытается переименовать под их MAC-адреса - а они у них одинаковые!
Естественно, не может.
Это как раз можно исправить через udevd: все модемы подключаются через один хаб, но через разные его порты, и вот название этого порта можно использовать для того, чтобы поименовать сетевые интерфейсы.
Подключаем сразу два Hilink и Olax.
У двух из них вот эти "предсказуемые имена" типа eth32fd344as, третий не смог переименоваться и остался eth0 - на него и посмотрим:
readlink /sys/class/net/eth0
../../devices/platform/usbdrd/fe500000.dwc3/xhci-hcd.4.auto/usb1/1-1/1-1.1/1-1.1:1.0/net/eth0
udevadm info -a -p /sys/devices/platform/usbdrd/fe500000.dwc3/xhci-hcd.4.auto/usb1/1-1/1-1.1/1-1.1:1.0/net/
eth0 | grep KERNELS
KERNELS=="1-1.1:1.0"
KERNELS=="1-1.1"
KERNELS=="1-1"
KERNELS=="usb1"
KERNELS=="xhci-hcd.4.auto"
KERNELS=="fe500000.dwc3"
KERNELS=="usbdrd"
KERNELS=="platform"
Можно взять один из признаков и использовать его как ключ, скажем, "1-1.1"
При этом глазами видно, что модем вклюен в 1 порт хаба, и можно предположить что у других гнезд другие адреса (и это можно проверить, для других модемных интерфейсов).
Пишем такие правила:
/etc/udev/rules.d/70-huawei.rules
SUBSYSTEM=="net", ACTION=="add", KERNELS=="1-1.1", NAME="usbnet1"
SUBSYSTEM=="net", ACTION=="add", KERNELS=="1-1.2", NAME="usbnet2"
SUBSYSTEM=="net", ACTION=="add", KERNELS=="1-1.3", NAME="usbnet3"
SUBSYSTEM=="net", ACTION=="add", KERNELS=="1-1.4", NAME="usbnet4"
Теперь, при подключении в этот хаб любого подобного устройства созданный сетевой интерфейс получает названия типа usbnetX, в зависимости от конкретного порта. А различить, какой это из модемов можно по IP-адресу сети, которую он создает.
Для этого нужно установить DHCP-клиент - и можно использовать все тот же busybox (пусть безобразно - но однообразно)
apt install udhcpcОн работает со скриптами, которым передает получаемые данные. Срипт по умолчанию /etc/udhcpc/default.script.
Поскольку в данном случае от него не требуется ничего кроме получения IP-адресов - сохраним этот скрипт на всякий случай, и исправим под себя, просто удалив всё что касается route и resolv:
cp /etc/udhcpc/default.script /etc/udhcpc/default.script.old
vim /etc/udhcpc/default.script
-------------------------
.....
case $1 in
bound|renew)
# Configure new IP address.
# Do it unconditionally even if the address hasn't changed,
# to also set subnet, broadcast, mtu, ...
busybox ifconfig $interface ${mtu:+mtu $mtu} \
$ip netmask $subnet ${broadcast:+broadcast $broadcast}
log info "$1: IP=$ip/$subnet router=$router domain=\"$domain\" dns=\"$dns\" lease=$lease"
;;
deconfig)
busybox ip link set $interface up
log notice "deconfigured"
;;
leasefail | nak)
log err "configuration failed: $1: $message"
;;
*)
echo "$0: Unknown udhcpc command: $1" >&2
exit 1
;;
esac
-------------------------
Можно проверить:
ip link set dev usbnet1 up
udhcpc -i usbnet1 -q -n
udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.9.100, server 192.168.9.1
udhcpc: lease of 192.168.9.100 obtained from 192.168.9.1, lease time 86400
ip addr dev usbnet1
usbnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether 0c:5b:8f:27:9a:64 brd ff:ff:ff:ff:ff:ff
inet 192.168.9.100/24 scope global usbnet4
valid_lft forever preferred_lft forever
inet6 fe80::e5b:8fff:fe27:9a64/64 scope link
valid_lft forever preferred_lft forever
Теперь снова возвращаемся к /etc/network/interfaces
Там можно перечислить нужные интерфейсы, указав для них дополнительные параметры, и задать их как "запускаемые при подключении"
# usb modems
allow-hotplug /usbnet*
iface usbnet1 inet dhcp
nat 1
iface usbnet2 inet dhcp
nat 1
iface usbnet3 inet dhcp
nat 1
iface usbnet4 inet dhcp
nat 1
При появлениив системе интерфейса с таким именем - он будет поднят автоматически. Слово dhcp означает, что настройки интерфейс получит по DHCP.
А вот параметр nat в документации не определен: на самом деле это означает, что при запуске скриптов в каталогах /etc/network/if-up.d - if-down.d среди переменных среды появится такая IF_NAT=1.
Это позволяет добавить свой скрипт, который при виде этой переменной установит настройки для NAT.
Точнее, скриптов будет два, установка и удаление:
/etc/network/if-up.d/sNAT
#!/bin/sh
if [ "x$IF_NAT" = "x1" ] ; then
iptables -t nat -A POSTROUTING -o "$IFACE" -j MASQUERADE
iptables -A FORWARD -o "$IFACE" -j ACCEPT
iptables -A FORWARD -i "$IFACE" -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i "$IFACE" -j DROP
fi
/etc/network/if-down.d/dNAT
#!/bin/sh
if [ "x$IF_NAT" = "x1" ] ; then
iptables -t nat -D POSTROUTING -o "$IFACE" -j MASQUERADE
iptables -D FORWARD -o "$IFACE" -j ACCEPT
iptables -D FORWARD -i "$IFACE" -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -D FORWARD -i "$IFACE" -j DROP
fi
Теперь получается так:
При подключении USB-модема создается интерфейс, которые переименуется в зависимости от гнезда USB-хаба.
После этого этот интерфейс получает IP-адрес через DHCP (udhcpc), и выполняется скрипт sNAT, который настраивает NAT через него.
И наконец, один из самых старых модемов - Huawei e173, еще из тех времен, когда 3G было новой технологией.
У него в принципе тоже есть сетевой интерфейс, NDIS, но работает от как-то странно, поэтому подключаться будет как тогда, в те времена - через PPP.
При подключении создаются три serial ports - /dev/ttyUSB0-2.
Первый обычно использовался для установления связи, PPP, второй - "диагностический" (не очень понятно в чем диагностика), и третий - в него во время работы валится статистика, и кроме того он способен реагировать на AT-команды даже тогда, когда первый порт занят.
Есть нюанс в том, что сложно гарантировать, что /dev/ttyUSB0 относится именно к первому порту именно этого модема.
Там уже столько всего понавключено, и другие модемы тоже могут создавать свои порты.
Поэтому переименуем нужные - и снова через udevd, создав очередные правила:
/etc/udev/rules.d/99-e173.rules
ACTION=="add", SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="12d1", ENV{ID_MODEL_ID}=="1436", ENV{MINOR}=="0", SYMLINK+="e173_at", MODE="0666"
ACTION=="add", SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="12d1", ENV{ID_MODEL_ID}=="1436", ENV{MINOR}=="1", SYMLINK+="e173_diag", MODE="0666"
ACTION=="add", SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="12d1", ENV{ID_MODEL_ID}=="1436", ENV{MINOR}=="2", SYMLINK+="e173_pcui", MODE="0666"
# NDIS интерфейс
ACTION=="add", SUBSYSTEM=="net", ENV{ID_VENDOR_ID}=="12d1", ENV{ID_MODEL_ID}=="1436", NAME="eth0e173"
NDIS мы использовать тут не будем, а вот tty-порты превращаются в /dev/e173_x, причем конкретно для этого модема.
Остается только написать конфиг для PPP. Он практически такой же, какие были во времена еще аналоговых модемов:
/etc/ppp/peers/modem
connect "/usr/sbin/chat -v -f /etc/ppp/chat/modem"
/dev/e173_at
115200
noipdefault
nodefaultroute
persist
noauth
ipparam "modem3g"
connect-delay 500
user gdata
-ipv6
lock
ipcp-accept-local
holdoff 10
maxfail 0
ifname modem3g
Разница разве что в наличии нового параметра ifname, определяющего название интерфейса вместо типового pppX, и в том, что указанная скорость порта 115200 - формальность, на самом деле скорость определяется соединением USB автоматически, 12 или 480 Мбит/с.
А так - то же самое, и скрипт дозвона почти такой же:
/etc/ppp/chat/modem
ABORT BUSY
ABORT ERROR
ABORT 'NO CARRIER'
REPORT CONNECT
TIMEOUT 2
"" AT
OK AT+COPS=1,2,"25002"
OK AT+CGATT=1
OK "ATE1V1&D2&C1S0=0+IFC=2,2"
"" "ATD*99#"
CONNECT
Из особенностей - номер дозвона *99#, принудительный выбор оператора AT+COPS=1,2,"25002" (Мегафон), а также заранее настроенная точка доступа, AT+CGDCONT=1,"IP","internet" - хотя это тоже можно было включить в скрипт.
Вообще есть много полезных AT-команд, но их описание само по себе займет много места, при том, что сейчас почти никто уже этим не пользуется, а кто пользуется - знает где их найти.
В итоге запуск подключения сводится к вызову pppd call modem, после чего соединение должно установиться, и должны отработать скрипты настройки NAT, точно так же как у PPPoE, только с другим названием интерфейса.
И точно так же, установка маршрута через это соединение - потом отдельно.
Даже запуск pppd по той же схеме: периодический запуск скрипта, который проверяет наличие портов модема, и поднимает ��оединение, если его еще нет.
#!/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH
log=/var/log/ppp/modem3g.log
DEVICE='/dev/e173_at'
if [ ! -L "$DEVICE" ]; then
exit 0
fi
ps ax| grep -v grep | grep 'pppd call modem' > /dev/null 2>&1
if [ $? -eq 0 ]; then
exit 0
fi
echo "Start PPP for $DEVICE" >> $log
/usr/sbin/pppd call modem
sleep 2
Это у нас получается соединение на 3G, с максимальной скоростью около 5 Мбит/с. Когда-то - невиданные скорости!
Если 3G недоступно, и нет никаких специально запрещающих настроек - модем может попытаться установить соединение в EDGE, или даже GPRS1, со скоростью в десятки килобит в секунду.
Был еще более старый модем ZTE какой-то там - но вот он уже толком не заработал: запредельное по современным меркам потребление тока, ему только одному нужен хаб с внешним питанием.
Ну и ладно, всё равно в хабе свободные порты закончились.
Остается только настроить default route для каждого интерфейса, с разными приоритетами, которые задаются через metric.
Для этого в скрипте /etc/udhcpc/default.script добавим пару строчек:
...
log info "$1: IP=$ip/$subnet router=$router domain=\"$domain\" dns=\"$dns\" lease=$lease"
mkdir -p /run/uplinks
echo "$ip $subnet $router" > /run/uplinks/$interface
;;
...При получении адреса будет создаваться файл /run/uplinks/usbnetX с примерно таким содержанием:
192.168.9.100 24 192.168.9.1И для PPP добавим подобный скрипт в /etc/ppp/ip-up.d/
/etc/ppp/ip-up.d/set-uplink
#!/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH
if [ "x$PPP_IFACE" != "x" ] ; then
mkdir -p /run/uplinks
echo "$PPP_LOCAL 32 $PPP_REMOTE" > /run/uplinks/$PPP_IFACE
fi
exit 0
Теперь после подключения всего этого зоопарка в каталоге /run/uplinks находятся файлы, соответствующие интерфейсам, а в них указаны IP-адреса шлюзов.
ls -l /run/uplinks/
total 20
-rw-r--r-- 1 root root 31 Dec 17 17:37 modem3g
-rw-r--r-- 1 root root 31 Dec 17 17:33 optic
-rw-r--r-- 1 root root 40 Dec 17 17:27 usbnet1
-rw-r--r-- 1 root root 44 Dec 17 17:27 usbnet3
-rw-r--r-- 1 root root 40 Dec 17 17:27 usbnet4
Зададим файл с приоритетами, /etc/uplinks.conf
192.168.9.1 = 60
192.168.8.1 = 70
192.168.100.1 = 50
optic = 40
modem3g = 100Чем меньше число - тем выше приоритет.
И наконец, скрипт, который всё это свяжет вместе:
#!/bin/sh -x
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH
# check uplinks
dir="/run/uplinks"
conf="/etc/uplinks.conf"
set_route(){
if [ -n "$metric" ] && [ -n "$gw" ] && [ -n "$iface" ] ; then
bad=$(( $metric * 10 ))
curr=$(ip route show| grep "default via $gw" | awk '{print $7}')
if ping -I $iface -c 2 -n -q 8.8.8.8 -W 2 > /dev/null 2>&1; then
if [ "x$curr" != "x$metric" ] ; then
while ip route del default via $gw dev $iface 2> /dev/null; do :; done
ip route add default via $gw dev $iface metric $metric 2> /dev/null
fi
else
if [ "x$curr" != "x$bad" ] ; then
while ip route del default via $gw dev $iface 2> /dev/null; do :; done
ip route add default via $gw dev $iface metric $bad 2> /dev/null
fi
fi
fi
}
if [ ! -f "$conf" ]; then
echo "No $conf found!"
echo
exit 1
fi
while [ true ] ; do
if [ -d $dir ]; then
cd $dir
for iface in * ; do
[ -e "$iface" ] || continue
if [ -d /sys/class/net/$iface ] ; then
read -r ip mask gw < $iface
if [ -n "$ip" ] && [ -n "$mask" ] && [ -n "$gw" ] ; then
metric=$(awk -v key="$gw" 'BEGIN { FS = " *= *" } $1 == key { print $2; exit }' $conf)
if [ ! -n "$metric" ]; then
metric=$(awk -v key="$iface" 'BEGIN { FS = " *= *" } $1 == key { print $2; exit }' $conf)
fi
set_route
fi
else
rm $dir/$iface
fi
done
fi
sleep 10
done
exit 0
Коротко суть - для каждого файла проверяем его приоритет либо по адресу gateway (сотовые модемы), либо по имени интерфейса (PPP-соединения), проверяем доступность и корректируем приоритеты.
И вот теперь - у роутера аж целых пять аплинков, как в том старом анекдоте про дв�� билета и проездной.
Выдергиваем оптику - интернет работает, выдергиваем модемы по очереди - интернет работает, и даже 3G всё еще позволяет смотреть видеоролики...
Хотя, конечно, если недружественная организация потребует от операторов отключить всё - то и отключится всё.
Но это уже не технический вопрос.
Ах да, ведь обычный роутер еще умеет WiFi раздавать!
Пишут про "мощные антенны", чуть ли не супер-технологии, позволяющие радиоволнам избирательно огибать железобетонные стены и заглядывать в каждый уголок.
Но гораздо надежнее работают примитивные "точки доступа", они же "усилители WiFi", которые на самом деле не умеют ничего кроме раздачи подключенного к ним проводного езернета.
Их можно поставить столько, сколько нужно, и там, где нужно, кинув в помещение кабель, и не ломая себе голову поиском оптимального размещения единственного роутера.
Они не умеют в WiFi 5-6-7, но по сути они нужны только для поддержки различных IoT-девайсов, а там всё это великолепие и не требуется.
Кстати, интересный момент: вышеуказанные "точки доступа" я брал когда-то именно для целей "расширения сети" - вот только они отвратительно работали, постоянно теряли сеть, через них не шло соединение и т.д.
Уже хотел выкидывать бесполезный мусор - но тут заменил сам роутер Кинетик и решил попробовать еще раз. И оказалось, что без него они прекрасно работают!
Да, роутеры Кинетик тоже могут работать в режиме повторителя, "повторяя" основной роутер Кинетик - по сути делая то же самое что эти "точки доступа", и делают это неплохо - но вместе друг с другом.
Чую тут какой-то подвох, но обосновать не могу...