Documentation for setting up MikroTik routers for use with Telekom / MagentaTV.
- Introduction
- Prerequisites
- PPPoE credentials
- Default configuration of RB5009UG+S+IN
- Setting up the basic network and connectivity
- Extended network configuration
- Activate Internet detection
- Configure NTP client
- Configure timezone (optional)
- Services
- DNS Caveats
There are many good routers for consumer households. The decision to use a MikroTik router, which you would be more likely to find in a network lab, was based on previous exposure and the intention to reduce the total number of devices. It could have been custom hardware with PFsense or OPNsense on top, but since the network will also have WiFi meshing in the future, the MikroTik router can act directly as a coordinator (for MikroTik APs) without the need for another device, and the solution is hopefully also more power-efficient than a dedicated mini-PC.
Custom routing solutions like MikroTik routers can be configured down to the smallest detail, but it is easy to get lost in these details, especially if the configuration is not done on a daily basis.
This documentation is mainly intended to serve me as a reference for the configuration steps carried out (and why they were necessary / useful), but perhaps it could be helpful for others as well.
Internet connection: Telekom with BNG and MagentaTV
-
Existing setup
-
AVM Fritz!Box 4040 as router
-
Zyxel VMG1312-B30A as external modem (VDSL2 and also taking care of VLAN 07 tagging)
-
Network:
10.0.0.0/16
-
DHCP
-
Static leases (and IP-addresses) for well-known hosts
-
Dynamic IP-addresses for guests (range:
10.0.234.0/24
)
-
-
-
New router: RB5009UG+S+IN
-
will reuse the existing modem until fiber gets installed
-
when fiber is available, the SFP port will carry the GPON SFP module
-
Telekom sells the Digitalisierungsbox Glasfasermodem which is a Zyxel PMG3000-D20B. This modem has a SC/APC socket, the wall box has a LC/APC socket.
(Some tutorials say one needs aONT-Anschlusskennung
, for me using the modem ID during configuration was just fine. ONT might be required for business accounts though.) -
Corning has fiber cables in various lengths for a moderate price (but they have only 2 mm white cables, the 3 mm ones are yellow).
-
-
UPDATE: Usage of the SFP proved to be flaky, issues seem to be caused by the MikroTik side:
-
erroneous temperature readings of the SFP by MikroTik leading to the SFP being shut down
-
auto-negotiation not working (worked around by setting the
sfp-sfpplus1
interface toauto-negotiation=no speed=1Gbps
) -
finally the RB5009UG+S+IN not recognizing the SFP after about 9 months (a hEX S had no issues with the SFP module and the fiber connection seemed to continue to work…)
The SFP has been replaced by the Glasfaser Modem 2 which seems to be more of a media converter than an actual modem. Works fine for now but now the setup is back to 2 devices. As the included fibre cable is quite short, it got replaced by a longer fiber cable from InLine.
The regular Telekom-PPPoE user consists out of multiple parts derived from the contract data.
The full PPPoE username would be:
AAAAAAAAAAAATTTTTTTTTTT#[email protected]
with
-
A => Anschlusskennung
-
T => T-Online-Nummer
-
M => Mitbenutzernummer
(If the AAAAAAAAAAAATTTTTTTTTTT
part is 24 characters long, the #
character before the MMMM part can be omitted.)
RouterOS (v7.14) comes with this default configuration.
The default configuration script can be queried with this command
/system/default-configuration/script print
or to show all default configuration scripts:
/system/default-configuration print
-
MikroTik
The SFP interface might become the new WAN device when using fiber. As it is not used for the internal network it can be already removed.
/interface bridge port
remove [find interface=sfp-sfpplus1]
"Quick Set" helps with the initial setup, especially when the network address shall be changed.
Setting | Value | Comment |
---|---|---|
Mode |
[x] Router |
|
Port |
|
|
Address Acquisition |
|
|
PPPoE User |
||
PPPoE Password |
|
|
PPPoE Service Name |
|
(optional) |
IP Address |
|
|
Netmask |
|
|
Bridge All LAN Ports |
[ ] |
|
DHCP Server |
[x] |
|
DHCP Server Range |
|
|
NAT |
[x] |
-
MikroTik
The network is already set up with 192.168.88.1/24
. This snippet changes the respective addresses and ranges.
For consistency all these commands should be executed at once:
/ip pool
set [find name=default-dhcp] name=dhcp-LAN ranges=10.0.234.1-10.0.234.254
/ip dhcp-server
set [find address-pool=default-dhcp] address-pool=default-LAN
/ip address
set [find address=192.168.88.0/24] \
address=10.0.0.0/16 \
network=10.0.0.0 \
interface=bridge
/ip dhcp-server network
set [find address=192.168.88.0/24] \
address=10.0.0.0/16 \
netmask=16 \
gateway=10.0.0.1 \
dns-server=10.0.0.1
/ip dns static
set [find address=192.168.88.1] \
address=10.0.0.1 \
name=router
Set up a VLAN interface for the PPPoE client. This is only required when the modem doesn’t take care of tagging.
Depending on the modem, interface
can be any of:
-
ether1
(external modem without VLAN tagging) -
sfp-sfpplus1
(SFP modem without VLAN tagging)
/interface vlan
add interface=ether1 vlan-id=7 name=vlan07-telekom comment=Telekom
-
MikroTik
Depending on the modem configuration interface
can be any of:
-
vlan07
(modem has no VLAN tagging) -
ether1
(modem does VLAN tagging) -
sfp-sfpplus1
(SFP modem does VLAN tagging)
As default the PPPoE client is disabled to prevent it from starting before configuration is complete.
/interface pppoe-client
add interface=vlan07-telekom add-default-route=yes \
use-peer-dns=yes \
name=pppoe-out1 \
user="AAAAAAAAAAAATTTTTTTTTTT#[email protected]" \
password="12345678" \
disabled=yes \
comment=Telekom
In addition to specific interfaces the firewall configuration can use more generic interface lists.
The PPPoE client’s interface must be added to the WAN
interface list to make it work.
/interface list member
add list=WAN interface=pppoe-out1 comment=Telekom
/routing igmp-proxy interface
add interface=pppoe-out1 alternative-subnets=87.141.215.251/32 upstream=yes comment=MagentaTV
add interface=bridge comment=MagentaTV
-
MikroTik
/ip firewall address-list
add address=224.0.0.0/4 list=Multicast comment=MagentaTV
add address=232.0.0.0/16 list=Multicast comment=MagentaTV
add address=239.35.0.0/16 list=Multicast comment=MagentaTV
/ip firewall filter
add chain=input action=accept dst-address-list=Multicast place-before=2 comment=MagentaTV
add chain=forward action=accept dst-address-list=Multicast place-before=2 comment=MagentaTV
/interface bridge
set [find where name=bridge and comment=defConf] \
igmp-snooping=yes igmp-version=3 mld-version=2 multicast-router=permanent comment=MagentaTV
-
MikroTik
/ip dhcp-server lease
add client-id=1:22:33:44:55:66:77 mac-address=22:33:44:55:66:77 address=10.0.25.2 comment="Notebook-1"
add client-id=1:12:23:34:45:56:67 mac-address=12:23:34:45:56:67 address=10.0.25.11 comment="Android-5"
📎
|
The |
-
MikroTik
/ip dns static
add name="Notebook-1" address=10.0.25.2
add name="Android-5" address=10.0.25.11
Or with the lan
domain configured:
/ip dns static
add name="Notebook-1.lan" address=10.0.25.2
add name="Android-5.lan" address=10.0.25.11
Fritz!OS (tested with v7.29) provides an API to query data from the router.
This data can be reused to configure the MikroTik router.
The Fritz2Tik documentation describes the details and steps needed to transform the data accordingly.
DHCP option 119
can be used to provide a default search domain (list) to clients.
The domain names used are based on DNS labels (RFC 1035 - 4.1.4) which is not very convenient if one has to derive them on its own… But there is a nice online tool helping with that: DHCP Option 119 Encoder
Search domain of: lan
/ip dhcp-server option
add code=119 name=domain-search-list value="0x03'lan'0x00"
or e.g. search domain list of: lan;foo
(don’t use box
as it’s a potential TLD since 2016-11-11):
/ip dhcp-server option
add code=119 name=domain-search-list value="0x03'lan'0x0003'foo'0x00"
Use the domain search option as part of an option set:
/ip dhcp-server option sets
add name=domain-search-set options=domain-search-list
Configure the DHCP server to use the given option set:
/ip dhcp-server
set [find name=dhcp-LAN] dhcp-option-set=domain-search-set
RouterOS supports setting up online time / bandwidth restrictions for clients. This functionality is called Kid Control.
-
MikroTik
/ip kid-control
add name=Time \
mon=0s-1h,16h-1d \
tue=0s-1h,16h-1d \
wed=0s-1h,16h-1d \
thu=0s-1h,16h-1d \
fri=0s-1h,16h-1d \
sat=0s-1h,12h-1d \
sun=0s-1h,12h-1d
add name=Time-Bandwidth \
mon=0s-1h,16h-1d \
tue=0s-1h,16h-1d \
wed=0s-1h,16h-1d \
thu=0s-1h,16h-1d \
fri=0s-1h,16h-1d \
sat=0s-1h,12h-1d \
sun=0s-1h,12h-1d \
rate-limit=70M
📎
|
For times up to midnight one has to use:
For times starting at |
For various reasons one might want to use custom server for DNS resolution instead the ones provided by the ISP. Reasons could be eg.:
-
content filtering (malicious sites, spam domains, etc.)
-
speed
-
some domain names not resolving properly
-
cached and outdated ones being resolved
-
and more…
A non-exhaustive list of some better known public DNS provider:
Example for setup using non-filtering Cloudflare DNS server:
/ip dns
set allow-remote-requests=yes servers=1.1.1.1,1.0.0.1
Configure the PPPoE client to ignore the DNS servers provided by the ISP:
/interface pppoe-client
set [find name=pppoe-telekom] use-peer-dns=no
One can even prevent users to use their own DNS settings and force them to use the router for look ups by redirecting all request to the router:
/ip firewall nat
print
add action=dst-nat chain=dstnat in-interface-list="LAN" \
src-address=!10.0.0.1 dst-port=53 to-addresses=10.0.0.1 \
protocol=udp comment="DNS redirect (UDP)"
add action=dst-nat chain=dstnat in-interface-list="LAN" \
src-address=!10.0.0.1 to-addresses=10.0.0.1 dst-port=53 \
protocol=tcp comment="DNS redirect (TCP)"
RouterOS has a builtin DDNS client using its own service but allows also custom scripts to be used
The builtin client is easy to use but does not allow custom names. Setup is easy but the name is based on the serial number of the router, so the DNS name will definitely change in case of a replacement.
Name consists of 12 character serial number appended by .sn.mynetname.net.
Activate builtin DDNS client:
/ip cloud
set ddns-enabled=yes
-
MikroTik
Another option is to use a custom script with one of the many available DDNS provider.
Having checked some of the free DDNS provider, these are my favorites:
-
FreeDNS
While most services require username / password AND the new IP address to perform the update FreeDNS has a nice feature, where one just performs a HTTPGET
on a URL such as https://sync.afraid.org/u/RANDOM_TOKEN/ to update the related subdomain.
FreeDNS detects the IP by it self. Really simple! -
Duck DNS
This DDNS has a feature very similar to FreeDNS. Just performing a HTTPGET
on https://www.duckdns.org/update?domains=YOUR_SUBDOMAIN&token=YOUR_TOKEN&ip= triggers the update.
If the value forip
is omitted, DuckDNS detects the IP itself and by that makes the calling script quite simple.
When one installs a script on the router, one has to assign a name to the script.
For the PPP connection this script can be configured to be called on-up
(when the connection has been established).
When the PPP connection is established, the custom script gets called and does a few things:
-
It uses the name of the script as service name for logging purposes.
-
Before it does any updates, it tries to validate the connection is really working by pinging a remote party.
-
If the connection has been validated, the sync URL is called.
The script can be either created via the the WebFig (System
/ Scripts
/ Add New
).
Setting | Value |
---|---|
Comment (used to store the sync URL) |
|
Name |
|
Don’t Require Permissions |
[x] |
Policy |
[x] read |
Script |
content of DDNS.rsc |
or created via shell:
/system script
add dont-require-permissions=no policy=read,write,policy,test \
name=FreeDNS comment="https://sync.afraid.org/u/your_token/" \
source="#!rsc\
\n#\
\n# Requires RouterOS\
\n#\
\n# MikroTik script to update the DNS entry when Internet connection has b\
een\
\n# established via PPP.\
\n#\
\n# Assign this script in the PPP profile as \"on-up\" script and assign t\
he\
\n# profile to the PPPoE connection.\
\n#\
\n# Permissions required:\
\n# - read\
\n# - write\
\n# - policy\
\n# - test (to execute ping)\
\n#\
\n\
\n:local notSetYet \"Comment NOT set up to hold sync URL yet\";\
\n\
\n# get name of script\
\n:local serviceName [:jobname]; # eg. \"FreeDNS\"\
\n\
\n# retrieve value of sync URL from comment of this script\
\n:local syncURL [/system/script { get [find name=\"\$serviceName\"] comme\
nt }];\
\n\
\n# abort if the URL hasn't been set up by user yet\
\n:if (!(\"\$syncURL\"~\"^http\")) do={\
\n # set default value if no value has been set for comment yet\
\n :if (\"\$syncURL\" = \"\") do= {\
\n /system/script { set [find name=\"\$serviceName\"] comment=\"\$n\
otSetYet\" };\
\n }\
\n\
\n :log error \"\$serviceName: \$notSetYet\";\
\n :error \$notSetYet;\
\n}\
\n\
\n{\
\n :local maxDelay 10;\
\n :local counter 0;\
\n\
\n # check if Internet is up, pinging the nameserver of Cloudflare in t\
his case\
\n :while ([:typeof ([:ping address=1.1.1.1 count=1 as-value]->\"time\"\
)] = \"nothing\") do={\
\n :set counter (\$counter + 1);\
\n\
\n # if max delay has been exceeded: abort\
\n :if (\$counter > \$maxDelay) do={\
\n :local msg \"Failed to detect Internet => no update\";\
\n\
\n :log warning \"\$serviceName: \$msg\";\
\n :error \$msg;\
\n } else={\
\n # bit of delay between attempts\
\n :delay 500ms;\
\n }\
\n }\
\n}\
\n\
\n:do {\
\n # call update endpoint and store response\
\n :local result [/tool fetch url=\"\$syncURL\" as-value output=user]\
\n :if (\$result->\"status\" = \"finished\") do={\
\n # add a new line as sentinel in case \"data\" has none\
\n :local response (\$result->\"data\" . \"\\n\") ;\
\n\
\n # retrieve only the first line of \$response\
\n :local endOfFirstLine ([:find \$response \"\\n\"]);\
\n :set response ([:pick \$response 0 \$endOfFirstLine]);\
\n\
\n :log info \"\$serviceName: \$response\";\
\n :put \$response;\
\n }\
\n} on-error={\
\n :log warning \"\$serviceName: Failure while calling update endpoint\
\";\
\n}\
\n"
If the sync URL changes, the comment filed can be updated accordingly using either WebFig or the CLI.
/system script
set [find name=FreeDNS] comment="https://sync.afraid.org/u/your_new_token/"
WireGuard requires the configuration of a dedicated interface and a dedicated network. In addition, each WireGuard peer must be manually assigned an IP address. (A peer can be a "Road Warrior" client or a remote location to which a secure connection is to be established). While manually assigning IP addresses works for a site-to-site configuration or a "Road Warrior" setup with a few clients, a different setup may be required for larger deployments.
📎
|
In this setup, port |
/interface wireguard
add listen-port=13231 mtu=1420 name=wireguard1 comment="Digital Home"
(The created interface will automatically get a computed, random public key).
/ip address
add address=172.17.2.1/24 network=172.17.2.0 interface=wireguard1 \
comment="Digital Home"
/ip firewall filter
add action=accept chain=input dst-port=13231 protocol=udp \
comment="Digital Home - allow WireGuard"
/interface list member
add interface=wireguard1 list=LAN comment="Digital Home"
(This could be more sophisticated if one uses more zones, etc.)
Peers need to know the public key of the router as their WireGuard peer. The public key can be looked up in WebFig or retrieved via console:
:put [/interface wireguard get [find name=wireguard1] "public-key" ]
This is the configuration of peer Digital nomad - 001
:
Setting | Value | Comment |
---|---|---|
Name |
|
Arbitrary, here the same name as on the router side for recognition. |
Address |
|
Address from the |
DNS server |
|
Address of the router in the |
Setting | Value | Comment |
---|---|---|
Public key |
|
Public key retrieved from router. |
Endpoint |
|
DNS name by which the router can be found and the |
Allowed IPs |
|
Whitelist of destination IPs that are to be routed through this peer (in this case all traffic) and from which traffic is allowed. |
After setting up the WireGuard tunnel on a specific device, the public key of this device is required to make a final configuration on the router.
/interface wireguard peers
add allowed-address=172.17.2.2/32 interface=wireguard1 \
public-key="public_key_of_001" \
comment="Digital nomad - 001"
-
MikroTik
-
WireGuard
Loopback NAT allows access of an internal service (forwarded port) by the external IP, e.g. when using a DynDNS name and a port as an external party would do. RouterOS does not have rules configured out of the box to support loopback NAT, but it’s easy although a bit unusual to setup.
When using PPP there are basically two options:
-
Update the IP of the configured IP interface. This would require some changes on PPP on-up script…
-
Use the DynDNS and let the router do the resolution of the name dynamically.
The following steps describe the last option.
/ip firewall address-list
add address=your.dyndns.name.com list=WAN-IP
/ip firewall nat
add action=masquerade chain=srcnat comment="Hairpin NAT" \
dst-address=10.0.0.0/16 \
src-address=10.0.0.0/16 \
place-before=0
This rule has to be the first one as it has to work before any of the traffic might get rejected.
Instead of using the WAN IP directly, we use the WAN-IP
address list which resolves the WAN IP auto-magically.
/ip firewall nat
add action=dst-nat chain=dstnat comment="Minecraft TCP" \
dst-address-list=WAN-IP dst-port=1337 protocol=tcp \
to-addresses=10.0.0.65 to-ports=25565
add action=dst-nat chain=dstnat comment="Minecraft UDP" \
dst-address-list=WAN-IP dst-port=1337 protocol=udp \
to-addresses=10.0.0.65 to-ports=25565
The dst-port
is the external port where the services is made publicly available whereas to-ports
is the port where the service is available on the internal host.
The modem resides behind the router and has its own address / network. It’s possible to access the modem with a few configuration adjustments.
The modem (either VDSL or fiber) is attached to ether1
.
Add NAT rule to the firewall for the modem interface:
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1 \
comment="Modem ether1"
The modem has the address 192.168.1.1/24
.
Assign ether1
a dedicated IP in the network range of the modem to allow routing:
/ip address
add address=192.168.1.2/24 interface=ether1 network=192.168.1.0 \
comment="Zyxel VMG1312-B30A"
Assign the modem a name (so that one does not have to remember its network/IP):
/ip dns static
add address=192.168.1.1 name=modem.lan comment="Zyxel VMG1312-B30A"
The modem has the address 192.168.100.1/24
.
Assign ether1
a dedicated IP in the network range of the modem to allow routing:
/ip address
add address=192.168.100.2/24 interface=ether1 network=192.168.100.0 \
comment="Glasfaser Modem 2"
Assign the modem a name (so that one does not have to remember its network/IP):
/ip dns static
add address=192.168.100.1 name=gmodem2.lan comment="Glasfaser Modem 2"
The modem is attached to sfp-sfpplus1
.
Add NAT rule to the firewall for the modem interface:
/ip firewall nat
add action=masquerade chain=srcnat out-interface=sfp-sfpplus1 \
comment="Modem SFP+"
The modem has the address 10.10.1.1/24
.
Assign sfp-sfpplus1
a dedicated IP in the network range of the modem to allow routing:
/ip address
add address=10.10.1.2/24 interface=sfp-sfpplus1 network=10.10.1.0 \
comment="Digitalisierungsbox Glasfasermodem"
Assign the modem a name (so that one does not have to remember its network/IP):
/ip dns static
add address=sfp-sfpplus1 name=fiber-modem.lan \
comment="Digitalisierungsbox Glasfasermodem"
Applying this setting will make RouterOS try to detect the "Internet".
It’s activated mostly to allow the mobile app to show some nice graphs about bandwidth usage…
As this feature might mix up interface lists (and by that firewall settings), it is safer to create interface lists solely for the purpose of Internet detection.
/interface list
add name=di-where-detect
add name=di-detected-lan
add name=di-detected-wan
add name=di-detected-internet
/interface detect-internet
set detect-interface-list=di-where-detect \
lan-interface-list=di-detected-lan \
wan-interface-list=di-detected-wan \
internet-interface-list=di-detected-internet
/interface list member
add interface=pppoe-out1 list=di-where-detect
/system ntp client
set enabled=yes
/system ntp client servers
add address=europe.pool.ntp.org
Per default auto-detection of the time zone is enabled. One can still specify the timezone manually.
/system clock
set time-zone-name=Europe/Berlin
-
MikroTik
To start web-ssl
one needs to create a certificate which can’t be done solely on the MikroTik itself.
/certificate
add name=SSL common-name=SSL key-size=2048
create-certificate-request template=SSL key-passphrase=<passphrase of your choice>
Copy the files to a system with OpenSSL
.
openssl rsa -in certificate-request_key.pem -text > certificate-request2.pem
openssl x509 -req -days 9999 -in certificate-request.pem -signkey certificate-request2.pem -out mikrotik_ssl.crt
Upload the created files to the MikroTik.
Configure the imported file as certificate.
/certificate import file-name=mikrotik_ssl.crt
passphrase: ******
certificates-imported: 1
private-keys-imported: 0
files-imported: 0
decryption-failures: 0
keys-with-no-certificate: 0
Configure the imported key file.
/certificate import file-name=certificate-request2.pem
passphrase: *****
certificates-imported: 0
private-keys-imported: 1
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0
/certificate print
Flags: K - PRIVATE-KEY; T - TRUSTED
Columns: NAME, COMMON-NAME, FINGERPRINT
# NAME COMMON-NAME FINGERPRINT
0 SSL SSL abc...
1 KT mikrotik_ssl.crt_0 SSL efg...
Configure web-ssl
to use the certificate and enable the service:
/ip service
set [find name=www-ssl] certificate=mikrotik_ssl.crt_0 disabled=no
-
MikroTik
When switching from VDSL to fiber it might seem that the connection does not work properly.
The reason could be actually local DNS caching, here www.heise.de
is resolved to ip.block.dt.de
:
$ ping www.heise.de
PING ip.block.dt.de (46.29.100.42): 56 data bytes
64 bytes from 46.29.100.42: icmp_seq=0 ttl=52 time=29.764 ms
64 bytes from 46.29.100.42: icmp_seq=1 ttl=52 time=29.047 ms
64 bytes from 46.29.100.42: icmp_seq=2 ttl=52 time=29.401 ms
...
One can either reboot or flush the DNS cache:
sudo systemd-resolve --flush-caches
sudo resolvectl flush-caches
or when DNS resolution is using dnsmasq
sudo killall -HUP dnsmasq