forked from nberlee/bonjour-reflector
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial Mikrotik/RouterOS container docs
- Loading branch information
Showing
3 changed files
with
223 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
|
||
# Setup container and network | ||
|
||
This step-by-step guide will help you setup your mikrotik router to run the reflector container. It assumes you have one bridge with vlans configured. The container will only respond to tagged vlans. Any untagged traffic will be dropped. | ||
|
||
## Enable container support | ||
|
||
1. Add the package containers by [downloading](https://mikrotik.com/download) the `extra package` for your CPU architecture, extract it and upload `container7.*-cpuarch.npk` to the root of your RouterOS, reboot. | ||
2. After the reboot, make sure the package is installed by running `/system package print` (or winbox system -> packages) and check if the package is listed. | ||
3. Enable container mode - Make sure you are in neighbourhood of your router and execute `/system/device-mode/update container=yes`, follow instructions on screen. Validate the container mode is enabled by running `/system/device-mode/print` and check if `container: yes` is listed. | ||
|
||
## Setup network | ||
1. Create a veth interface to be used by the reflector container, this interface will be used to connect the container to the bridge. The address and gateway are not used, but are required to create the interface. `/interface/veth/add name=veth1-reflector address=127.1.0.10/32 gateway=127.1.0.1` | ||
|
||
2. Create a bridge port for the veth interface. Make sure to change the `bridge=` to your bridge name. `ingress-filtering=no` on the port is really needed, not sure why, as in the next step we assign the vlans ids. use a non existent pvid, as it won't be needed. `/interface/bridge/port/add bridge=bridge1 edge=yes frame-types=admit-only-vlan-tagged ingress-filtering=no interface=veth1-reflector learn=yes multicast-router=permanent point-to-point=yes pvid=999` | ||
3. Add `veth1-reflector` as tagged port to the vlans you want to use. | ||
|
||
Change the `bridge` to your bridge and `vlan-ids` to the vlans you want to use. | ||
|
||
Please note, these commands open an editor, to save the changes press `ctrl+o` to exit the editor. Interfaces are comma separated, so if you want to add multiple interfaces, add a comma between them. | ||
|
||
```mikrotik | ||
/interface/bridge/vlan/edit [/interface/bridge/vlan/find bridge=bridge1 vlan-ids=100] tagged | ||
``` | ||
```mikrotik | ||
/interface/bridge/vlan/edit [/interface/bridge/vlan/find bridge=bridge1 vlan-ids=101] tagged | ||
``` | ||
```mikrotik | ||
/interface/bridge/vlan/edit [/interface/bridge/vlan/find bridge=bridge1 vlan-ids=103] tagged | ||
``` | ||
|
||
# Configure container | ||
The container is only ~8MB on disk, if your router doesn't have a lot of storage, tmpfs can be used to store the container. See this youtube of Mikrotik for more info: https://www.youtube.com/watch?v=KO9wbarVPOk and make sure to replace the paths below with the tmpfs 'disk' path. | ||
|
||
## Image pull configuration | ||
The reflector container is hosted on github container registry. To be able to pull the image, you need to configure the registry. This can be done by adding a registry to the router. | ||
|
||
```mikrotik | ||
/container config set registry-url=https://ghcr.io tmpdir=tmpfs/pull | ||
``` | ||
|
||
The `tmpdir` can be any directory, if your router has enough memory it is recommended if you are using tmpfs. | ||
|
||
## config.toml | ||
The config.toml file is used to configure the reflector. | ||
|
||
See the [config.md](../config.md) for detailed explaination. | ||
|
||
Edit your own `config.toml` and upload it to your router in a directory, for example the default `/pub` directory, as its not strait forward to create a directory in RouterOS. | ||
|
||
## Container mount | ||
Create a container mount to the directory you uploaded the `config.toml` to. Make sure to change the `src` to the path you uploaded the file to. | ||
|
||
```mikrotik | ||
/container mounts add dst=/config name=reflector-config src=/pub | ||
``` | ||
(RouterOS can only mount directories, not files.) | ||
|
||
## Container logging | ||
RouterOS doesn't show the container logs in the log viewer as the loglevel is not high enough. This can be changed by adding a logging rule. | ||
|
||
```mikrotik | ||
/system logging add topics=container | ||
``` | ||
|
||
|
||
## Create container | ||
Creating the container is better to be done using a script. As updating a container in RouterOS is still relatively hard, and there is no docker-compose way of doing it, we need to remove the old container and create a new one. The script below will do this for you. Replace the `containers/` in `rootdir` with the directory you want to store the container incase you are using tmpfs. | ||
|
||
If you just want to test: | ||
```mikrotik | ||
/container/add remote-image=ghcr.io/nberlee/bonjour-reflector:main int=veth1-reflector root-dir=containers/reflector mounts=reflector-config logging=yes start-on-boot="yes" comment="bonjour-reflector" | ||
``` | ||
|
||
|
||
A more permanent, status checking, and updating script: | ||
```mikrotik | ||
/system script add dont-require-permissions=no name=recreate-reflector-container owner=admin policy=read,write,test source=":local tag \"ghcr.io/nberlee/bonjour-reflector:main\";\r\ | ||
\n:local interface \"veth1-reflector\";\r\ | ||
\n:local containerLogging \"yes\";\r\ | ||
\n:local mount \"reflector-config\";\r\ | ||
\n:local rootdir \"containers/reflector\";\r\ | ||
\n\r\ | ||
\n#pinghost for internet connectivity check\r\ | ||
\n:local pinghost \"ghcr.io\";\r\ | ||
\n\r\ | ||
\n# check if container is already running and remove stopped containers\r\ | ||
\nforeach container in=[/container/find tag=\$tag] do={\r\ | ||
\n :local status [/container/get \$container status];\r\ | ||
\n if (\$status != \"running\") do={\r\ | ||
\n /container/remove \$container;\r\ | ||
\n }\r\ | ||
\n if (\$status = \"running\") do={\r\ | ||
\n :error \"container already running\";\r\ | ||
\n }\r\ | ||
\n}\r\ | ||
\n\r\ | ||
\n# test if we have internet connectivity\r\ | ||
\n:local continue true;\r\ | ||
\n:while (\$continue) do={\r\ | ||
\n do {\r\ | ||
\n /ping address=\$pinghost count=1;\r\ | ||
\n :set continue false;\r\ | ||
\n } on-error={\r\ | ||
\n delay 1s;\r\ | ||
\n }\r\ | ||
\n} \r\ | ||
\n\r\ | ||
\n:local reflector [/container/add remote-image=\$tag int=\$interface root-dir=\$rootdir mounts=\$mount logging=\$containerLogging start-on-boot=\"yes\" comment=\"bonjour-reflector\"];\r\ | ||
\n:while ([/container/get \$reflector status] != \"stopped\") do={ :delay 1s; }\r\ | ||
\n/container/start \$reflector;\r\ | ||
\n\r\ | ||
\n" | ||
``` | ||
execute the script | ||
```mikrotik | ||
/system/script/run recreate-reflector-container | ||
``` | ||
|
||
observe your container is running: | ||
```mikrotik | ||
/container/print | ||
``` | ||
|
||
You may want to add the script to the scheduler to run it every 5 minutes or at boot. This way the container will be recreated if it crashes or is stopped for some reason. | ||
|
||
## Update container | ||
The script can be used to update the container as well. Just stop the container and start the script in the future. | ||
|
||
# Troubleshooting | ||
The container is minimal and has no shell. So you can't login to the container. You can however check the logs by looking in the RouterOS log. | ||
## Container not starting | ||
Check the RouterOS log for errors. If you see the following error: | ||
``` | ||
Could not find config file | ||
``` | ||
This means the container could not find the `config.toml` file. Make sure you uploaded the file to the correct directory and mounted it correctly. | ||
|
||
--- | ||
``` | ||
failure: could not add | ||
``` | ||
Please make sure your RouterOS has enabled container support. See step 3 in `Enable container support`. | ||
|
||
--- | ||
## No MDNS/SSDP is reflected | ||
Make sure traffic is going into the container and is coming out. You can do see this in winbox with the following steps: | ||
1. Tools -> Packet Sniffer | ||
2. Tab Filter, Interfaces -> select veth1-reflector | ||
3. Make sure direction is any and no other filters are set. Press Apply, then press Start. | ||
4. Press Packets and add VLAN to the columns. by clicking on the arrow next to the column names -> Show Columns -> VLAN -> OK | ||
5. Do not forget to stop the packet sniffer when you are done. | ||
|
||
* tx = packets going into the container | ||
* rx = packets coming out of the container | ||
|
||
If you see packets going in but not coming out, run the container in verbose mode by adding `/bonjour-reflector -verbose` to Cmd in the container settings. Then check the RouterOS logs. You should all packets that are actionable by the reflector. These include: | ||
* SSDP query packet received: | ||
* SSDP advertisement packet received: | ||
* SSDP query response packet received: | ||
* Bonjour packet received: | ||
* Packet sent: | ||
* Replied to %v for ip %s | ||
|
||
Were `response packet` means that there is actual SSDP sessions set up. Which is a good sign. | ||
|
||
If you see packets coming out of the container but no response packet are received make absolute sure you have assigned the correct vlan ids on the bridge for the veth1-reflector interface. Also check if the veth1-reflector interface port is set to `ingress-filtering=no` and `frame-types=admit-only-vlan-tagged-and-priority-tagged`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
The config.toml file is used to configure the reflector. | ||
|
||
* `net_interface` is the interface the container will use to send and receive packets. In a container this is always `eth0`. | ||
* `devices` is a list of devices that will be available to the `shared_pools` vlan ids. Only devices that are listed here will be available to the shared_pools. The `origin_pool` is the vlan id that the device is connected to. The `shared_pools` are the vlan ids that the device will be available to. | ||
|
||
This example we have the following networks: | ||
* Media network `100`, the reflector will use ip `192.168.100.2` on this network. | ||
* Client network `101`, the reflector will use ip `192.168.101.2` on this network. | ||
* IoT network `103`, the reflector will use ip `192.168.103.2` on this network. | ||
|
||
In this example the following devices are available to the networks: | ||
* Bedroom TV `71:27:06:20:A7:E6` is connected to the media network `100` and is available to the client network `101` and IoT network `103`. | ||
* Onkyo amplifier `01:10:B1:E1:69:98` is connected to the media network `100` and is available to the client network `101` and IoT network `103`. | ||
* NVidia Shield `00:04:4B:5D:F2:D3` is connected to the media network `100` and is available to the client network `101` and IoT network `103`. | ||
* Volumio bathroom `DC:A6:32:2B:31:19` is connected to the IoT network `103` and is available to the client network `101`. | ||
|
||
Please note, this is not bidirectional. This means in this example the reflector will deny initiated MDNS/SSDP from the Nvidia Shield in `100` to connect to the client network. But it will allow the client network to connect to the Nvidia Shield in `100`. So `origin_pool` is the network the device is connected to, and `shared_pools` are the networks the device is available to. | ||
|
||
```toml | ||
net_interface = "eth0" | ||
|
||
[devices] | ||
|
||
[devices."71:27:06:20:A7:E6"] | ||
description = "Bedroom TV" | ||
origin_pool = 100 | ||
shared_pools = [101, 103] | ||
|
||
[devices."01:10:B1:E1:69:98"] | ||
description = "Onkyo amplifier" | ||
origin_pool = 100 | ||
shared_pools = [101, 103] | ||
|
||
[devices."00:04:4B:5D:F2:D3"] | ||
description = "NVidia Shield" | ||
origin_pool = 100 | ||
shared_pools = [101, 103] | ||
|
||
[devices."DC:A6:32:2B:31:19"] | ||
description = "Volumio bathroom" | ||
origin_pool = 103 | ||
shared_pools = [101] | ||
|
||
[vlan] | ||
|
||
[vlan.100] | ||
ip_source = "192.168.100.2" | ||
|
||
[vlan.101] | ||
ip_source = "192.168.101.2" | ||
|
||
[vlan.103] | ||
ip_source = "192.168.103.2" | ||
``` |