Недавно мне посчастливилось заняться достаточно интересной практической задачей по организации общественного доступа в Интернет для международной компании «Coffee Сup», имеющей 5 собственных баров формата «кофе с собой» в разных городах, а так же дилеров по всей России и странах СНГ. Нужно все сделать, так как мы любим: желательно быстро и достаточно качественно. Гостевой доступ в Интернет организуется не только ради удобства пользователей сервиса, но и, в первую очередь, с точки зрения пользы для бизнеса: принудительно смотришь рекламу и получаешь свой бесплатный Интернет. В наше время, это уже абсолютно повсеместный сервис, встречаемый от метро и аэропортов, до торговых центров и других общественных площадок. Этими удаленными осенними вечерами родилось решение «сделай все своими руками», поэтому делюсь опытом и практическими наработками. Сразу забегу вперед, стоимость решения на один бар вышла 3700 рублей за оборудование и совсем немного сверху в счет аренды сервера. Но вернемся к нашей задаче.

С чего мы начали, так это с поиска готовых решений на рынке. С этим нет проблем, поддержка различного оконечного оборудования, «дружественный» интерфейс по его подключению на аутсорсинг, обещанная гарантия, что все по закону, всего 1000 рублей в месяц абонентской платы за каждое подключение. А для «Coffee Сup» это уже 5000 рублей/месяц, что равно 60 000 рублей/год (не считая оборудование). Поиском готовых аппаратно-программных реализаций даже не занимались – полная скука, даже можно сказать осенняя хандра. В общем, не наш метод. Надо во всем самим разобраться и все сделать самому.

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

  1. Разобраться в нормативно-правовых актах, чтобы все было по закону.

  2. Выбрать и закупить необходимое оборудование.

  3. Настроить и интегрировать оборудование в уже существующую инфраструктуру баров.

  4. Настроить Hotspot (сконфигурировать роутеры и сделать страницы авторизации на сервисе под задачи маркетинга).

  5. Настроить централизованное управление (удаленное управление маршрутизаторами, базу данных, backend и frontend).

Нормативно-правовые акты

Обо всем по порядку. Нам нужны постановления правительства России и от 31 июля 2014 г. №758 «О внесении изменений в некоторые акты …» и от 12 августа 2014 г.  №801 «О внесении изменений в некоторые акты …». Одно дополняет второе, как видно, между ними успело пройти целых 2 недели. В соответствии с ними (немного перефразировано для большей ясности):

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

Это единственно приемлемое решение в настоящее время, все остальные предлагаемые законом решения нам явно не подходят (паспорта, госуслуги и т.д.). Цитируем снова:

сведения о пользователях …, а также об объеме и времени оказания им услуг связи хранятся … не менее 6 месяцев.

Что понимать под «объемом оказания им услуг связи» мы решили уточнить у роскомнадзора, написали им письмо и ничего до сих пор не получили в ответ. Остается на наше усмотрение: под объемом будем понимать результаты «NetFlow» (сбора информации об открытых пользователями соединениях, подробнее можно прочитать на https://en.wikipedia.org/wiki/NetFlow).

С этим разобрались, уже хорошо. Дошло дело до всеми любимого федерального закона от 27 июля 2006 г. №152-ФЗ «О персональных данных». Закон в принципе понятный, уже обкатанный вдоль и поперек, технически сложного он ничего не содержит – сплошная организационная рутина: согласия, политики, приказы и т.д. Попадаем ли мы со своим Hotspot под его действие? Ведь мы будем хранить просто номера телефонов… Ответ – не попадаем. Точку в этом вопросе в настоящее время ставит роскомнадзор на своем сайте в разделе вопросов и ответов (https://15.rkn.gov.ru/p8880/p15987/):

Согласно ст. 3 Федерального закона от 27.07.2006 №152-ФЗ «О персональных данных»

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

Оборудование

Приступаем к технической части. В качестве оборудования было решено приобретать роутеры MikroTik по следующим причинам: поддерживают технологию Hotspot, отличное качество,  высокая гибкость, дружелюбные русскоязычные сообщества. Самое главное, наличие возможности работы в диапазоне 2.4 и 5 ГГц, чтобы нашему WiFi никто не мешал. Выбрали «hAP ac lite TC» (подробно про него можно посмотреть на сайте производителя https://mikrotik.com/product/RB952Ui-5ac2nD-TC, в характеристиках нам все нравится, особенно «Operating System RouterOS»). 3700 рублей каждый, отличная цена. Из рекомендаций – вполне можно приобретать изделия, бывшие в употреблении, рынок в Москве наиболее насыщенный и приятный по ценам, а доставка сейчас работает отлично в любой регион. Арендовали в Интернете Linux сервер, особо каких-то требований к этому вопросу тоже не предъявляли.

Интеграция

Все бары уже имели подключение к Интернет. Везде по-разному, где-то стоял 4G USB модем в другом роутере, где-то использовался мобильный WiFi роутер со встроенным аккумулятором. Изменять существующую инфраструктуру было запрещено из-за боязни, что что-нибудь перестанет безвозвратно работать, а все переделывать и безосновательно финансово удорожать проект – не хотелось. MikroTik везде интегрировался без проблем. Например, покажем как настроено получение Интернет по WiFi (как настроено это дело по кабелю от другого роутера или через 4G USB модем оставлю без комментариев):

/interface wireless security-profiles set [ find default=yes ] supplicant-identity=MikroTik

add authentication-types=wpa2-psk disable-pmkid=yes eap-methods="" group-ciphers=tkip mode=dynamic-keys name=OPERATOR supplicant-identity="" unicast-ciphers=tkip wpa2-pre-shared-key=1111111111111

/interface wireless set [ find default-name=wlan1 ] band=2ghz-onlyn country=russia disabled=no frequency=auto name=wlan1-station security-profile=OPERATOR ssid=OPERATOR-9392 station-roaming=enabled

Добавили скрипт в dhcp-client и скорректировали работу своего NAT (можно было бы настроить masquerade, однако вспомнили презентацию технического специалиста компании MikroTik «My holy war against masquerade», а также, что masquerade частный случай SRC-NAT и отказались от этой идеи):

/ip firewall nat
add action=src-nat chain=srcnat comment=OPERATOR-NAT out-interface=wlan1-station src-address=192.168.2.0/24 to-addresses=10.0.0.100

add action=src-nat chain=srcnat comment=HOME-NAT out-interface=wlan1-station src-address=192.168.1.0/24 to-addresses=10.0.0.100

/ip dhcp-client
add disabled=no interface=wlan1-station use-peer-dns=no use-peer-ntp=no

#Script for src-NAT
:local OUTINTERFACE wlan1-station;
:local COMMENT OPERATOR-NAT;
:local COMMENT2 Home-NAT;
:local IPFORNAT [/ip dhcp-client get [find interface=$OUTINTERFACE] address];
#delete mask in ip
:local IPFORNATSHORT [:pick $IPFORNAT 0 [:find $IPFORNAT "/"]];
/ip firewall nat set [find comment=$COMMENT] to-addresses=$IPFORNATSHORT;
/ip firewall nat set [find comment=$COMMENT2] to-addresses=$IPFORNATSHORT;

Интернет до MikroTik-ов получили, далее настроили качественно и безопасно наши роутеры в  качестве точки доступа. Опишем только интересное. Сделали два профиля безопасности для WiFi (free и staff), включили сразу 3 WiFi сети: две для staff (для обоих диапазонов 2.4 и 5 ГГц, так как не все оборудование в барах умеет работать в 5 ГГц) и одну free (только на 5 ГГц). На 2.4 ГГц free решили не делать, так как приоритет отдан предоставлению Интернет пользователям с современными мобильниками, и кроме того наши роутеры умеют делать до 4 точек доступа одновременно. Рекомендовали барам все оборудование переподключить на staff, так как позже была задана приоритезация трафика в маршрутизаторах, а это значит, что никто из гостей нам не провалит "служебный" Интернет. В настройках WiFi оставили много параметров по-умолчанию, чтобы поддерживать максимальный парк подключаемых устройств. Важно помнить, что беспроводной интерфейс, выступающий в качестве клиента WiFi (через который мы забираем Интернет), должен быть обязательно master.

/interface wireless security-profiles
set [ find default=yes ] supplicant-identity=MikroTik

add authentication-types=wpa-psk,wpa2-psk eap-methods="" management-protection=allowed name=coffeecup_free supplicant-identity=""

add authentication-types=wpa2-psk disable-pmkid=yes eap-methods="" management-protection=allowed mode=dynamic-keys name=coffeecup_staff supplicant-identity="" wpa2-pre-shared-key=2222222222222

/interface wireless
set [ find default-name=wlan1 ] antenna-gain=0 band=2ghz-g/n channel-width=20/40mhz-XX country=russia disabled=no frequency=auto frequency-mode=manual-txpower installation=indoor mode=ap-bridge name=wlan1-COFFEECUP_2_staff security-profile=coffeecup_staff ssid=CoffeeCup_Staff2 station-roaming=enabled wireless-protocol=802.11 wps-mode=disabled

set [ find default-name=wlan2 ] antenna-gain=0 band=5ghz-n/ac channel-width=20/40/80mhz-XXXX country=russia disabled=no frequency=auto frequency-mode=manual-txpower installation=indoor mode=ap-bridge name=wlan2-COFFEECUP_5_staff security-profile=coffeecup_staff ssid=CoffeeCup_Staff station-roaming=enabled wps-mode=disabled

add default-forwarding=no disabled=no keepalive-frames=disabled mac-address=02:00:00:AA:00:00 master-interface=wlan2-COFFEECUP_5_staff multicast-buffering=disabled name=wlan3-COFFEECUP_5 security-profile=coffeecup_free ssid=CoffeeCup_FreeWiFi wds-cost-range=0 wds-default-cost=0 wps-mode=disabled

Настроили firewall, обязательно сделали отдельное правило для icmp (чтобы не было скрытых проблем с раздачей Интернет от вышестоящих маршрутизаторов) и заложили будущий VPN. Пример для 4G свистка:

/ip firewall filter
add action=accept chain=input comment="Accept established,related" connection-state=established,related
add action=drop chain=input comment="Drop invalid" connection-state=invalid
add action=accept chain=input comment="Accept input icmp" protocol=icmp
add action=accept chain=input comment="Accept input ovpn" in-interface=ovpn-coffeecup
add action=accept chain=input comment="Accept input DNS for bridge_guest" dst-port=53 in-interface=bridge_guest protocol=udp
add action=drop chain=input comment="Drop all input from !bridge" in-interface=!bridge
add action=accept chain=forward comment="Accept established,related" connection-state=established,related
add action=drop chain=forward comment="Drop invalid" connection-state=invalid
add action=drop chain=forward comment="Drop all from WAN to !DSTNAT" connection-nat-state=!dstnat connection-state=new in-interface=LTE1_WAN

Qos выполнили через маркировку трафика, скоростные лимиты выбрали из реальных измерений (мы использовали сервис от Яндекс «Интернетометр»):

/ip firewall mangle
add action=mark-connection chain=prerouting comment="Managment connections" dst-address=192.168.15.21 dst-port=22,8291 new-connection-mark="Managment connections" passthrough=yes protocol=tcp

add action=mark-connection chain=forward comment="VIP connection" connection-mark=no-mark new-connection-mark="VIP connection" passthrough=yes src-address-list=VIP

add action=mark-packet chain=forward comment="VIP packets" connection-mark="VIP connection" new-packet-mark="VIP packets" passthrough=yes

add action=mark-connection chain=forward comment="LAN=>WAN connections" connection-mark=no-mark in-interface=bridge new-connection-mark="LAN=>WAN connections" out-interface=LTE1_WAN passthrough=yes

add action=mark-packet chain=forward comment="LAN=>WAN packets" connection-mark="LAN=>WAN connections" new-packet-mark="LAN=>WAN packets" passthrough=yes

add action=mark-connection chain=forward comment="Guest=>WAN connections" connection-mark=no-mark in-interface=bridge_guest new-connection-mark="Guest=>WAN connections" out-interface=LTE1_WAN passthrough=yes

add action=mark-packet chain=forward comment="Guest=>WAN packets" connection-mark="Guest=>WAN connections" new-packet-mark="Guest=>WAN packets" passthrough=yes

add action=mark-packet chain=output comment="Managment packets" connection-mark="Managment connections" new-packet-mark="Managment packets" passthrough=yes

add action=mark-connection chain=postrouting comment="OVPN connections" dst-address=IP_OUR_SERVER dst-port=1190 new-connection-mark="OVPN connections" out-interface=LTE1_WAN passthrough=yes protocol=tcp

add action=mark-packet chain=postrouting comment="OVPN packets" connection-mark="OVPN connections" new-packet-mark="OVPN packets" passthrough=yes

/queue tree
add comment="Guest (bridge-guest)" max-limit=10M name=Guest parent=bridge_guest
add comment="LAN (bridge)" max-limit=10M name=LAN parent=bridge
add comment="WAN (pppoe)" max-limit=10M name=WAN parent=LTE1_WAN
add name=Guest_other packet-mark=no-mark parent=Guest
add name="LAN_LAN=>WAN" packet-mark="LAN=>WAN packets" parent=LAN
add limit-at=128k max-limit=512k name=LAN_managment packet-mark="Managment packets" parent=LAN priority=1
add name=LAN_other packet-mark=no-mark parent=LAN
add name=LAN_ovpn packet-mark="OVPN packets" parent=LAN
add name=LAN_vip packet-mark="VIP packets" parent=LAN priority=7
add name="WAN_Guest=>WAN" packet-mark="Guest=>WAN packets" parent=WAN
add name="WAN_LAN=>WAN" packet-mark="LAN=>WAN packets" parent=WAN priority=7
add name=WAN_ovpn packet-mark="OVPN packets" parent=WAN priority=7
add name=WAN_vip packet-mark="VIP packets" parent=WAN priority=6
add name="Guest=>WAN" packet-mark="Guest=>WAN packets" parent=Guest queue=pcq-download-default

Задействовали семейные DNS сервера от Яндекса: все-таки рабочий Интернет, да и место общественное.

/ip dns set allow-remote-requests=yes servers=77.88.8.7,77.88.8.3

На практике было установлено, что некоторые провайдеры блокируют использование не своих DNS-серверов. Чтобы решить это, можно получать адреса DNS серверов от вышестоящего маршрутизатора при работе DHCP-клиента (активация use-peer-ntp) или вложить свои DNS запросы в VPN туннель, а на арендуемом сервере настроить NAT и включить ip forward:

#На роутере:
/ip route
add distance=1 dst-address=77.88.8.3/32 gateway=192.168.15.1
add distance=1 dst-address=77.88.8.7/32 gateway=192.168.15.1

#На сервере:
iptables -t nat -A POSTROUTING -s 192.168.15.0/24 -o eth0 -j SNAT --to your_server_ip
echo '1' > /proc/sys/net/ipv4/ip_forward

Hotspot

Настало время настройки технологии Hotspot непосредственно на роутерах. MikroTik из коробки поддерживает саму технологию, однако мы ее кастомизировали под "Coffee Cup", а также выполнили все требования российского законодательства. В процессе был найден полезный ресурс (https://mikrotik-training.ru/), посвященный настройке оборудования MikroTik, наработками которого мы воспользовались в своем проекте. Приступим к описанию. Создали профиль для Hotspot. При подключении к сети free роутер показывает web страницы авторизации в сервисе Hotspot от имени сайта coffeecuptogo.com, время жизни «cookie» задали 4 часа  (по истечении которых пользователя отправляются на переподключение). Работа технологии Hotspot, разумеется, касается только гостевой сети.

/ip hotspot profile
set [ find default=yes ] dns-name=coffeecuptogo.com hotspot-address=192.168.10.1 html-directory=flash/hotspot http-cookie-lifetime=4h name=coffeecup

/ip hotspot
add address-pool=pool_guest addresses-per-mac=1 disabled=no idle-timeout=none interface=bridge_guest name=hotspot_coffeecup

/ip hotspot user profile
set [ find default=yes ] keepalive-timeout=1h mac-cookie-timeout=4h

Здесь же в профиле пользователей создали скрипты, которые автоматически срабатывают при подключении и отключении пользователей. Логика у обоих скриптов одинаковая. Сначала собирается информацию на роутере, затем она отправляется методом http-get на наш сервер, на котором все это аккумулируется в базу данных (разберем ее позднее). Для защиты своего сервера от спама придумали ключ, который также передается и, в первую очередь, проверяется на сервере. На роутере собирается: имя роутера (для каждого бара задали его индивидуально), текущее время и дата на роутере (удобно их забирать здесь, а не получать на сервере, чтобы не заморачиваться потом в backend-е с часовыми поясами в разных барах), mac гостя, его ip в гостевой сети, а также текущие белый и серый ip адреса роутера (белый адрес мы берем через внешний сервис, хотя нет проблем его забирать на нашем сервере через массив $_SERVER в PHP, на котором написан наш backend), номер телефона клиента, который мы позже будем получать через форму авторизации в Hotspot и присваивать его значение в качестве имени пользователя (на сервер отправляется с первой цифрой 7), а также имя хоста телефона (может потом пригодится где-нибудь в маркетинге или статистике). Кстати новые версии iOS при подключении к точке доступа без пароля не передают имя хоста, что реализовано с целью сохранения конфиденциальности. Переменной LOGIN мы передаем отключился (LOGIN=2) ли клиент или наоборот подключился (LOGIN=1). Скрипт для аутентификации имеет вид:

#Out interface to internet
:local INTERNETINTERFACE pppoe-out1;
:local APIKEY 12345;
#status ---> log in
:local LOGIN 1;
:local SITE oursite;
:local PORT 1500;

:local nas [/system identity get name];
:local today [/system clock get date];
:local time1 [/system clock get time ];
:local ipuser [/ip hotspot active get [find user=$user] address];
:local usermac [/ip hotspot active get [find user=$user] mac-address]
:local hour [:pick $time1 0 2]; 
:local min [:pick $time1 3 5]; 
:local sec [:pick $time1 6 8];
:set $time1 [:put ({hour} . {min} . {sec})] 
:local mac1 [:pick $usermac 0 2];
:local mac2 [:pick $usermac 3 5];
:local mac3 [:pick $usermac 6 8];
:local mac4 [:pick $usermac 9 11];
:local mac5 [:pick $usermac 12 14];
:local mac6 [:pick $usermac 15 17];
:local USERLONG "7$user";
:set $usermac [:put ({mac1} . {mac2} . {mac3} . {mac4} . {mac5} . {mac6})]
#ip addresses:
:local whiteip ([/tool fetch url="https://site_for_white_ip/" output=user as-value]->"data");
:local grayip [/ip address get [find interface=$INTERNETINTERFACE] address];
#delete mask in ip
:local grayipshort [:pick $grayip 0 [:find $grayip "/"]];

#What host-name
:foreach i in=[/ip dhcp-server lease print as-value where address=$ipuser] do={
	:if (($i->"address")=$ipuser) do={
		:set $host [($i->"host-name")];
	}
}

do {/tool fetch url="https://$SITE:$PORT/\?api=$APIKEY&device=$nas	&tel=$USERLONG	&status=$LOGIN	&ipgray=$grayipshort	&ipnat=$ipuser	&mac=$usermac	&date=$today	&time=$time1	&host=$host"	keep-result=no} on-error={};	

Скрипт для деаутентификации имеет вид:

#Out interface to internet
:local INTERNETINTERFACE pppoe-out1;
:local APIKEY 12345;
#status ---> log out
:local LOGIN 2;
:local SITE oursite;
:local PORT 1500;

:local nas [/system identity get name];
:local today [/system clock get date];
:local time1 [/system clock get time ];
:local hour [:pick $time1 0 2]; 
:local min [:pick $time1 3 5];
:local sec [:pick $time1 6 8];
:set $time1 [:put ({hour} . {min} . {sec})] 
:local USERLONG "7$user";
#ip addresses:
:local whiteip ([/tool fetch url="https://site_for_white_ip/" output=user as-value]->"data");
:local grayip [/ip address get [find interface=$INTERNETINTERFACE] address];
#delete mask in ip
:local grayipshort [:pick $grayip 0 [:find $grayip "/"]];

do {/tool fetch url="https://$SITE:$PORT/\?api=$APIKEY&device=$nas	&tel=$USERLONG	&status=$LOGIN	&ipgray=$grayipshort	&date=$today	&time=$time1"	keep-result=no} on-error={};

О том, что мы сохраняем и можем использовать в маркетинговых целях информацию о наших клиентах, а также конкретно какую именно информацию и пользовательское согласие на это, мы оформили в политике конфиденциальности, показываемой на странице авторизации в Hotspot. Теперь разберем сердце нашего сервиса, а именно скрипт, который будет автоматически выполняться на роутере каждые 10 секунд (через scheduler, разумеется). Для его работы донастроили логирование:

/system logging add action=hotspot topics=hotspot,debug,info,!account
/system logging action add name=hotspot target=memory

Наш скрипт обнаруживает в логе MikroTik сообщение с темой «hotspot» со словами «login failed». Эти записи будут появляться автоматически. Со стороны клиента это выглядит так: загрузилась форма авторизации на Hotspot, пользователь ввел свой телефонный номер, нажал кнопку получить пароль, в течение 10 секунд ему приходит пароль посредством SMS, пользователь вводит этот пароль и получает Интернет. На роутере это выглядит немного по-другому: произошла попытка авторизации на сервисе Hotspot неизвестного пользователя (ошибка «login failed»), скрипт получает имя этого пользователя (из того же лога) и его короткий пароль посредством http-get на наш backend (на сервере генерируются случайные пароли в нужном нам формате, опишем это позже), создает такого пользователя Hotspot, отправляет номер телефона и пароль методом http-get в SMS центр (который пересылает пароль на номер пользователя) и «очищает» лог с темой «hotspot» (уменьшает его до 1 строки и сразу увеличивает до 1000 строк). Случайный пароль генерируется на сервере, потому что RouterOS не имеет встроенной функции генерации случайных чисел, а самодельные решения из математических операций со временем (и т.п.) не всегда дают нужный результат. Создание такого механизма на MikroTik заслуживает независимого исследования. Кроме этого сделали защиту от пользователей, которые попытаются получить много SMS (и обнулить наш счет в SMS центре). Для этого воспользовались не по назначению возможностями firewall, а именно адрес листом. Каждого пользователя Hotspot (фактически его номер телефона) скрипт записывает в  /ip firewall address-list на 5 минут, а при попытке аутентификации на Hotspot, проверяет, нет ли там такого пользователя. Побочным явлением этого решения является появление «посторонних» записей в address-list – попытка RouterOS определить IP адрес для каждой DNS записи. Просто не обращаем на это внимание. В качестве SMS центра выбран sms.ru, так как у заказчика уже был с ними договор и оформлены все необходимые документы, в следствие чего уже был закреплен корректный caller id «Coffee Cup» (в качестве номера телефона, от имени которого приходят SMS).

:local SITE oursite;
:local PORT 1500;

:foreach line in=[/log find buffer=hotspot message~"login failed"] do={
	:do {:local content [/log get $line message];
	:local pos1 [:find $content " (" 0];
	:if ($pos1 != " ") do={
		:local uname ""; 
		:set uname [:pick $content ($pos1-10) ($pos1-0)];   
		:local unameforsms "7$uname";

		#Cheks user from spam
		:local sendtest yes;
			:foreach i in=[/ip firewall address-list print as-value where list=spam_cheks_list] do={
				:if (($i->"address")=$uname) do={
					:set $sendtest no;
				}
			}
					
	:if ($sendtest=yes) do={
		/ip firewall address-list add list=spam_cheks_list address=$uname timeout=00:05:00;
		#Password generation 
		local pass ([/tool fetch url="https://$SITE:$PORT" output=user as-value]->"data")
		#Add hotspot user
		do {/ip hotspot user add name=$uname} on-error={};
		do {/ip hotspot user set password=$pass numbers=[find name=$uname]} on-error={};
		#SMS
		do {/tool fetch url="https://sms.ru/sys/send.php\?AUTH_DATA&phones=$unameforsms&mes=$pass" keep-result=no} on-error={}; 
		:delay 1;
	}
	}
}
}
#Clear hostpot log
/system logging action set hotspot memory-lines=1;
:delay 1;
/system logging action set hotspot memory-lines=1000;

Российское законодательство обязывает нас сохранять объем оказания пользователям услуг связи, поэтому настроили связку коллектора и клиента «Net-flow». На сервере с backend-ом:

apt install flow-tools
nano /etc/flow-tools/flow-capture.conf

#comment all
#IMPORTANT Traffic Flow Version need 5 !!
-w /var/log/flow -n 275 -N 3 192.168.15.1/0/1234

На MikroTik (обращаем внимание на версию 5 протокола, так как коллектор работает именно с ней):

/ip traffic-flow set enabled=yes interfaces=bridge_guest
/ip traffic-flow target add dst-address=192.168.15.1 port=1234 version=5

Кроме этого с целью сохранения конфиденциальности от третьих лиц (в том числе провайдера Интернет) передачу «Net-flow» трафика осуществляем по VPN каналу (ширины его полностью хватает для этой задачи). Настало время разобраться с формой авторизации в сервисе. При создании Hotspot в RouterOS появляется набор каталогов и файлов, отвечающих за его работу. Нас интересуют файлы /flash/hotspot/login.html и /flash/hotspot/alogin.html. Первый – это страница авторизации на сервисе, а вторая – это страница, которая будет показана пользователю после успешной авторизации. Подробнее об этом можно почитать тут https://wiki.mikrotik.com/wiki/Manual:Customizing_Hotspot.

"Родная" структура каталогов и файлов Hotspot на MikroTik
"Родная" структура каталогов и файлов Hotspot на MikroTik

Сверстали (переделали) login.html под заказчика, сохранили необходимую RouterOS структуру web страницы. Подробно расписали политику конфиденциальности.

Переделанная страница авторизации на сервисе Hotspot
Переделанная страница авторизации на сервисе Hotspot

Очень хотелось на странице alogin.html просто сделать редирект на сайт заказчика, но у этого решения есть большой минус: сайт подгружается не моментально (временная задержка на редирект, да и скорость Интернета не всегда достигает отличных значений). Если сверстать эту страницу и положить ее в память роутера, то она будет показана пользователю моментально. То, что мы и сделали. Единственное ограничение - это объем страницы, ведь в нашем маршрутизаторе всего 16 Мб памяти и львиную ее долю забирает созданная RouterOS структура файлов и каталогов Hotspot. Можно, конечно, присоединить USB flash, но не очень хочется занимать свободный (не всегда) единственный USB порт на MikroTik. Мы уместили alogin.html со всеми ссылками в 500 кб. На этом настройка Hotspot закончена, настал черед  разобрать backend.

Управление

Начнем с сервера. На нем работает база данных MySQL,  в которую накапливается информация о регистрациях пользователей в Hotspot, передаваемая скриптами роутеров. Принимается и сохраняется в базу данных информация посредством backend страницы на PHP, она же генерирует пароли для пользователей. Создали админку для заказчика и прокинули VPN до роутеров (надо же их администрировать кому-то). Теперь подробнее.

Как мы помним, маршрутизаторы передают нам: имя роутера, текущее время и дату, mac гостя, его ip в гостевой сети, а также текущие белый и серый ip адреса роутера, номер телефона клиента, имя хоста телефона и статус (авторизация или деавторизация). Все это аккумулируется в таблице registration. Информацию о барах (имя устройства MikroTik и описательная информация о его расположении) накапливается в таблице coffeepoints (здесь нам все сразу известно). По просьбе заказчика ввели излишнюю таблицу users, в которой накапливается информация о пользователях сервиса: номер телефона, и в каком баре впервые он появился. Создали техническую таблицу status, в которой переводится придуманные нами коды 1 или 2 в значения login и logout. Для резервного копирования базы данных лучше, конечно, настроить автоматическую репликацию, однако в связи с не большими объемами хранения информации в нашем проекте мы пошли другим путям: в cron еженедельно выполняется mysqldump базы данных, результаты периодически копируются в ручную на локальный хост.

Структура базы данных
Структура базы данных

Разберем одностраничный код backend. В общем виде там все работает так: проверяется корректность передаваемого на сервер APIKEY, если все верно, тогда наполняется база данных. Сначала извлекается из базы данных информация, описывающая бар. Затем проверяется, новый ли пользователь пришел в бар (в этом случае заполняется таблица users), или информация о нем уже содержится в базе данных. Переводятся в текст коды status. Затем вся необходимая информация заполняется в таблицу registrations. Если APIKEY не передавался (или не верен), то просто генерируется случайный пароль.

//Проверка корректности ключа
if ( $key_from_get === $api ) {
	Защита от спама пройдена
}
else {
	//Выводим просто временный пароль
	$pas1d = random_int (0, 9);
	$pas2d = random_int (0, 9);
	$pas3d = random_int (0, 9);
	$pas4d = random_int (0, 9);
	$password = "$pas1d$pas2d$pas3d$pas4d";
	echo $password;
}

Осталось поговорить про админку, с которой заказчик сможет работать самостоятельно. Можно, конечно, просто установить на сервер готовые решения по работе с базой данных посредством web интерфейса (вроде phpmyadmin или adminer), но мы сделали все под ключ. Так как web дизайн это не наш конек, да и интереса к нему особо нет, то воспользовались нашим любимым getbootstrap.com. На выходе - строгий адаптивный frontend. В разделе «Регистрации» отображается журнал регистраций в сервисе, т.е. таблица registrations базы данных.

Админка для сервиса (раздел "Регистрации")
Админка для сервиса (раздел "Регистрации")

В разделе «Пользователи» видим информацию из таблицы users, в разделе «Бары» из coffeepoints, в разделе «Статусы» из status, а раздел «Подключения» введен для отладки. Поля дата и время передаются роутерами не в совсем красивом формате, что можно преобразовывать на нашем backend, но на функционал это не сильно влияет. Добавили возможность фильтровать вывод, а также экспорт в "MS Exel". Да и вообще здесь можно писать код в свое удовольствие, с делом и просто так. Не судите строго.

Админка для сервиса (раздел "Пользователи")
Админка для сервиса (раздел "Пользователи")

Пару слов о настройке VPN. Разумеется, VPN сервер вертится здесь же на арендуемом сервере (вот такой комбайн вышел), в качестве протокола выбран OpenVPN, как наиболее гибкий, безопасный и стабильный. С его настройкой нет никаких проблем: сделали инфраструктуру открытых ключей, нагенерировали сертификатов, самоподписали их. RouterOS, правда, умеет пока работать только с TCP соединением для OpenVPN, но это не беда. В целом, соединения устанавливаются и работают годами без проблем. В результате имеем удаленный доступ до роутеров из любой точки мира, самое главное не забываем работать в «Safe mode» (режим MikroTik, при котором в случае долгого обрыва канала управления маршрутизатор автоматически отменяет последнее изменение своей конфигурации), ведь настраивать удаленно firewall - это верная примета к дальней поездке. А также обращаем внимание на то, что по нашей ошибке при переносе настроенных конфигураций между роутерами, возможно совпадение mac адресов сетевых интерфейсов, что может доставить немного хлопот.

Заключение

Наконец наша статья подошла к концу. Опираясь на имеющиеся в Интернете наработки,  мы самостоятельно запустили сервисы Hotspot для баров компании «Coffee Сup», функционирующих в рамках действующего российского законодательства, используя силу оборудования MikroTik, мощь PHP и универсальность MySQL. Не боимся экспериментировать и разбираться с разными технологиями. Всех с наступающим 2021 годом!