Всем привет, понадобилось мне для домашней автоматизации Home Assistant управлять списком адресов в Mikrotik’е, поискав в гугле ничего внятного не нашел, пришлось писать самому
Зачем это нужно? Дома в сети есть девайсы (планшет, телефоны, телевизоры…) периодически есть необходимость лишать их доступа в интернет, молодые родители меня поймут 🙂
Что понадобится:
- Маршрутизатор Mikrotik
- Home Assistant в моем случае hass.io
- AppDaemon — это такая среда выполнения Python скриптов для автоматизаций, подробнее тут
Начнем.
Для начала сделайте адреса необходимых устройств статическими в DHCP сервере, это нужно для того что-бы IP адреса не изменялись. Далее нам нужно создать Address List в Mikrotik’е (IP > Firewall > Address Lists) Add New
- Name: CHILDREN_BLOCK_INET (тут называете список как вам нравится, без пробелов)
- Address: 192.168.0.51 (адрес устройства, который хотим блокировать)
- Comment: iPad (ВАЖНО: здесь название устройства, будет отображаться в HA)
PS: Поле Comment важно заполнять уникальным т.к. на его основе будет создаваться сущность в данном случае switch.mtk_al_ipad
Далее нам нужно создать правило фильтрации в Mikrotik’е (IP > Firewall > Filter Rules) Add New:
- Enabled: Yes
- Chain: forward
- Protocol: 6 (tcp)
- Out. Interface: ether1 (интерфейс который смотрит в интернет в моем случае это ether1)
- Src. Address List: CHILDREN_BLOCK_INET (создавали ранее)
- Action: reject
- Reject With: tcp reset
- Comment: CHILDREN_BLOCK_INET
Созданное правило перемещаем наверх, для того что бы оно отрабатывало как можно раньше, на этом этапе можно проверить работу правила, взять гаджет проверить интернет, зайти в (IP > Firewall > Address Lists) включить правило для устройства, интернет должен пропасть. Перейдите в System > User и создайте нового пользователя homeassistant, он нам понадобится для управления списком из HA.
С Mikrotik’ом всё, переходим в HA, у меня hass.io через него устанавливаем Add-on AppDaemon если у вас не hass.io, то AppDaemon скорее всего установить можно, каким то другим способом, но я не задавался таким вопросом 🙂
в AppDaemon прописываем в конфиг python_packages «librouteros==3.0.0» это модуль для взаимодействия с Mikrotik у меня получилось так:
«disable_auto_token»: false,
«system_packages»: [],
«python_packages»: [
«librouteros==3.0.0»
],
«init_commands»: []
}
После перезапуска AppDaemon’а, установится librouteros и в папке конфигурации HA должна появится папка appdaemon, создаем папку appdaemon/apps/mikrotik это папка нашего приложения, в ней создаем два файла mikrotik.py и mikrotik.yaml
mikrotik.yaml:
module: mikrotik
class: Mikrotik
host: ‘192.168.0.1’
username: ‘homeassistant’
password: ‘__YOUR_PASSWORD__’
addrlist: ‘CHILDREN_BLOCK_INET’
mikrotik.py:
import re
import appdaemon.plugins.hass.hassapi as hass
import time
import librouteros
from librouteros.login import plain, token
class Mikrotik(hass.Hass):
def initialize(self):
self.log(«Mikrotik»)
self.handles = {}
self.run_every(self.update, datetime.datetime.now(), 10)
self.api = librouteros.connect(self.args[«host»], self.args[«username»], self.args[«password»])
self.listen_event(self.state_change, event = «call_service»)
def update_addr_list(self):
lst = self.args[«addrlist»]
lists = self.api(‘/ip/firewall/address-list/print’)
for row in lists:
if row[‘list’] != lst:
continue
addr_id = row[‘.id’]
sensor_name = ‘switch.mtk_al_’ + re.sub(r»\W «, «», row[‘comment’], flags=re.I).replace(» «, «_»)
self.log(‘sensor_name: {}’.format(sensor_name))
sensor_name = sensor_name.lower()
self.handles[sensor_name] = row
self.handles[sensor_name][‘addr_id’] = addr_id
def update(self, kwargs):
self.update_addr_list()
for row in self.handles:
state = «off»
if self.handles[row][‘disabled’] == True:
state = «on»
self.set_state(row, state = state, attributes = {«friendly_name»: self.handles[row][‘comment’], «address»: self.handles[row][‘address’], ‘list’: self.handles[row][‘list’], ‘icon’: ‘mdi:earth’, ‘addr_id’: self.handles[row][‘addr_id’]})
def state_change(self, event_name, data, kwargs):
entity = data[«service_data»][«entity_id»]
if(data[«service»] == «turn_off» and entity in self.handles):
self.set_list_state(False, self.handles[entity][‘addr_id’])
if(data[«service»] == «turn_on» and entity in self.handles):
self.set_list_state(True, self.handles[entity][‘addr_id’])
def set_list_state(self, state, addr_id):
params = {‘disabled’: state, ‘.id’: addr_id}
t = self.api(‘/ip/firewall/address-list/set’, **params)
tuple(t)
self.update(None)
при копировании данного кода отсюда, могут поломаться отступы(особенность языка Python) имейте это ввиду. После сохранения AppDaemon увидет изменения и запустит приложение автоматически
Данный код писался с мобилки и на красоту не претендует 🙂 Надеюсь кому то будет полезно.
Добавить комментарий