feat(ansible): add IoT VLAN 5 (192.168.5.0/24, szafa wifi)

MikroTik: add vlan5 interface, bridge VLAN entry (ether3 tagged),
IP 192.168.5.1/24, IPv6 from-pool, DHCP pool/server/network,
firewall rules allowing IoT internet-only (IPv4 and IPv6),
DNS input from vlan5.

OpenWrt: add switch VLAN 5 (WAN+CPU tagged), br-iot bridge on
eth0.5, iot interface, iot firewall zone (forward ACCEPT,
input REJECT).

Also remove ensure_order from all non-firewall api_modify tasks
as RouterOS does not support move on those paths.
This commit is contained in:
2026-05-13 22:27:25 +02:00
parent 120547b1b8
commit 38f0aa699f
9 changed files with 124 additions and 27 deletions
+15 -5
View File
@@ -6,13 +6,16 @@
# input: ACCEPT (SSH, ping reachable from MGMT network)
# forward: REJECT (nothing routes through mgmt)
#
# lan — client bridge (eth0.2, wireless clients)
# lan — client bridge (eth0.2, LAN ports)
# input: REJECT (clients cannot SSH into the AP itself)
# forward: ACCEPT (client traffic passes through to MikroTik,
# which does all actual firewalling)
# forward: ACCEPT (traffic passes through to MikroTik for firewalling)
#
# No forwarding rules between zones — traffic in/out of each zone goes
# directly to/from MikroTik over the trunk, not through this device.
# iot — IoT bridge (eth0.5, wifi only)
# input: REJECT (IoT devices cannot reach the AP itself)
# forward: ACCEPT (traffic passes through to MikroTik, which allows
# internet only and blocks all internal networks)
#
# No forwarding rules between zones — all inter-zone policy is on MikroTik.
- name: Configure firewall
community.openwrt.uci:
@@ -42,6 +45,13 @@
option output 'ACCEPT'
option forward 'ACCEPT'
config zone
option name 'iot'
list network 'iot'
option input 'REJECT'
option output 'ACCEPT'
option forward 'ACCEPT'
config rule
option name 'Allow-ICMP-mgmt'
option src 'mgmt'
+44
View File
@@ -0,0 +1,44 @@
---
- name: Load IoT WiFi password from OpenBao
ansible.builtin.set_fact:
openwrt_iot_wifi_password: >-
{{
lookup(
'community.hashi_vault.vault_kv2_get',
openbao_fields.iot_wifi.path,
engine_mount_point=openbao_kv_mount
).secret[openbao_fields.iot_wifi.password_key]
}}
no_log: true
- name: Configure IoT WiFi interface (szafa, WPA2, network iot)
community.openwrt.uci:
command: section
config: wireless
type: wifi-iface
name: iot_radio0
find:
device: radio0
ssid: szafa
value:
device: radio0
network: iot
mode: ap
ssid: szafa
encryption: psk2
key: "{{ openwrt_iot_wifi_password }}"
disabled: '0'
replace: true
notify: Reload wireless
- name: Enable radio0
community.openwrt.uci:
command: set
key: wireless.radio0.disabled
value: '0'
notify: Reload wireless
- name: Commit wireless config
community.openwrt.uci:
command: commit
key: wireless
+9
View File
@@ -0,0 +1,9 @@
---
# Secret references only; actual values are loaded from OpenBao/Vault at runtime.
openbao_kv_mount: secret
openbao_fields:
iot_wifi:
path: openwrt_iot_wifi
password_key: password
+6 -2
View File
@@ -24,9 +24,11 @@
- address: 192.168.3.1/24
interface: vlan3
network: 192.168.3.0
- address: 192.168.5.1/24
interface: vlan5
network: 192.168.5.0
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure IPv6 addresses
community.routeros.api_modify:
@@ -43,6 +45,8 @@
- address: 2001:470:61a3:100::1/64
advertise: false
interface: vlan4
- address: ::ffff:ffff:ffff:ffff/64
from-pool: pool1
interface: vlan5
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
+18 -12
View File
@@ -8,7 +8,6 @@
- name: dockers
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure VLAN interfaces
community.routeros.api_modify:
@@ -26,9 +25,12 @@
comment: SERVER LAN
interface: bridge1
vlan-id: 4
- name: vlan5
comment: IOT
interface: bridge1
vlan-id: 5
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure interface lists
community.routeros.api_modify:
@@ -38,7 +40,6 @@
comment: contains interfaces facing internet
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure interface list members
community.routeros.api_modify:
@@ -52,7 +53,6 @@
list: wan
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure bridge ports
community.routeros.api_modify:
@@ -85,7 +85,6 @@
interface: ether11
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure bridge VLAN membership
community.routeros.api_modify:
@@ -95,6 +94,9 @@
tagged: sfp-sfpplus2,ether3
untagged: ether1,ether2,ether9
vlan-ids: 2
- bridge: bridge1
tagged: bridge1,ether3
vlan-ids: 5
- bridge: bridge1
tagged: sfp-sfpplus2
untagged: ether10
@@ -104,7 +106,6 @@
vlan-ids: 4
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure IPv4 pools
community.routeros.api_modify:
@@ -116,9 +117,11 @@
- name: dhcp_pool1
ranges: 192.168.255.1-192.168.255.9,192.168.255.11-192.168.255.254
comment: MGMT DHCP pool
- name: dhcp_pool2
ranges: 192.168.5.50-192.168.5.250
comment: IOT DHCP pool
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure DHCP servers
community.routeros.api_modify:
@@ -134,9 +137,13 @@
interface: bridge1
lease-time: 30m
comment: MGMT
- name: dhcp3
address-pool: dhcp_pool2
interface: vlan5
lease-time: 30m
comment: IOT
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure DHCP networks
community.routeros.api_modify:
@@ -148,9 +155,11 @@
- address: 192.168.255.0/24
dns-none: true
gateway: 192.168.255.10
- address: 192.168.5.0/24
dns-server: 192.168.5.1
gateway: 192.168.5.1
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
# TODO: IPv6 pools are useful when we have dynamic prefix, but we don't
# We can remove it now
@@ -163,7 +172,6 @@
prefix-length: 64
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure DNS
community.routeros.api_find_and_modify:
@@ -195,7 +203,6 @@
type: internal
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure UPnP global settings
community.routeros.api_find_and_modify:
@@ -217,7 +224,6 @@
type: internal
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure IPv6 ND defaults
community.routeros.api_find_and_modify:
@@ -29,7 +29,6 @@
value: y
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure container mounts
community.routeros.api_modify:
@@ -43,7 +42,6 @@
src: /tmp1/tailscale-root
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure tailscale container
community.routeros.api_modify:
@@ -63,4 +61,3 @@
workdir: /
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
+32
View File
@@ -53,6 +53,11 @@
comment: Allow from SRV to CAM
in-interface: vlan4
out-interface: vlan3
- action: accept
chain: forward
comment: Allow from IOT to internet only
in-interface: vlan5
out-interface-list: wan
- action: accept
chain: forward
comment: Allow from dockers to everywhere
@@ -136,6 +141,17 @@
dst-port: 53
in-interface: dockers
protocol: tcp
- action: accept
chain: input
comment: Allow DNS from IOT
dst-port: 53
in-interface: vlan5
protocol: udp
- action: accept
chain: input
dst-port: 53
in-interface: vlan5
protocol: tcp
- action: accept
chain: input
comment: Allow BGP from SRV
@@ -368,6 +384,11 @@
comment: Allow from SRV to CAM
in-interface: vlan4
out-interface: vlan3
- action: accept
chain: forward
comment: Allow from IOT to internet only
in-interface: vlan5
out-interface-list: wan
- action: accept
chain: forward
comment: Allow from dockers to everywhere
@@ -445,6 +466,17 @@
dst-port: 53
in-interface: dockers
protocol: tcp
- action: accept
chain: input
comment: Allow DNS from IOT
dst-port: 53
in-interface: vlan5
protocol: udp
- action: accept
chain: input
dst-port: 53
in-interface: vlan5
protocol: tcp
- action: accept
chain: input
comment: Allow BGP from SRV
-2
View File
@@ -64,7 +64,6 @@
routing-table: main
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure BGP templates
community.routeros.api_modify:
@@ -96,4 +95,3 @@
templates: klaster
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
-3
View File
@@ -12,7 +12,6 @@
user: "{{ routeros_pppoe_username }}"
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure 6to4 tunnel interface
community.routeros.api_modify:
@@ -25,7 +24,6 @@
remote-address: 216.66.80.162
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true
- name: Configure veth interface for containers
community.routeros.api_modify:
@@ -41,4 +39,3 @@
comment: Tailscale container
handle_absent_entries: remove
handle_entries_content: remove_as_much_as_possible
ensure_order: true