Mikrotik – VOIP QoS – Simple Queues

Another bit of helpful code for Mikrotik. We were getting some crackling on our VOIP phone system when the internet connection was maxed out, the following code let phone traffic run smoothly, based on the UDP ports the VOIP service uses. Adjust to your VOIP providers ports, and adjust your LAN targets as needed.

There are a few concepts to be aware of:

  1. Connection Marks — an identifying marker applied by the router to a connection passing through it. Markers are used for other rules to affect these connections.
  2. Packet Marks — an identifying market applied by the router, to the packets inside of a given connection. Markers will be used to escalate the priority of our RTP (Audio) Packets.
  3. SIP – VOIP Control Signalling Channels — e.g., Source phone > Target Phone + Extension, everything about the phone call.
  4. RTP – VOIP Audio Data — e.g. Compressed AAC audio content sent from the phone in packets.
  5. Mikrotik Queues — Basically, Quality of Service (QoS) pools of bandwidth, and reserving speed for a specific type of traffic (VOIP first, web-downloads last).
  6. Mikrotik Parent Queues — A total “pool” of available bandwidth, to be provided to children.
  7. Mikrotik Child Queues — A reserved portion of bandwidth assigned to a type of traffic that child is handling.

Note — If you have FastTrack enabled, it tends to bypass Queues, you may need to disable FastTrack to enforce your Queues, which may drastically increase CPU usage under high loads. For our RB3011-RM, running at 100Mbps, we hit 10-15% CPU load with fast-track disabled.

#Mark SIP Connections
#These numbers are for our VOIP provider, 8x8, different providers have different numbers.
#SIP All - Control:UDP/5060,5196-5199
#RTP All - Audio:UDP/3478-3480,15044,2222-2269,16384-16404,30000-30040
##RTP STUN:UDP/3478-3480
##RTP Polycom Phones:UDP/2222-2269
##RTP Linksys Phones:UDP/16384-16404
##RTP AAC Audio:UDP/30000-30040
#You can change optionally add a dst-address for the IP or IP Address List of your VOIP Provider's Servers, I prefer to keep it simple and focus on ports.
#Mark the SIP Connections with a Connection Mark.
/ip firewall mangle add chain=forward protocol=tcp port=5060,5196-5199 action=mark-connection new-connection-mark=VOIP-SIP-Connection comment="Mark VOIP/SIP Connections"
#Mark SIP Packets, inside of the marked SIP Connections.
/ip firewall mangle add chain=forward connection-mark=VOIP-SIP-Connection action=mark-packet new-packet-mark=VOIP-SIP-Packet comment="Mark VOIP/SIP Packets"
#Mark RTP Connections, change to the port number of your VOIP Calls
/ip firewall mangle add action=mark-connection chain=forward new-connection-mark=VOIP-RTP-Connection port=3478-3480,15044,2222-2269,16384-16404,30000-30040 protocol=udp comment="Mark RTP Connections"
#Mark RTP Packets, inside of the marked RTP Connections. These "rotate" port numbers rapidly, but are generated from the Connections. 
/ip firewall mangle add action=mark-packet chain=forward connection-mark=VOIP-RTP-Connection new-packet-mark=VOIP-RTP-Packet comment="Mark VOIP/RTP Packets"
#Escalate the DSCP Value for the RTP packets to Critical Priority as they pass through the router. This should be respected even beyond our own network, but our ISP and further hops out.
/ip firewall mangle add chain=postrouting action=change-dscp new-dscp=46 passthrough=yes packet-mark=VOIP-RTP-Packet comment="Change RTP Packets DSCP Value"
#There are two types of queues: Parent (Total pool of bandwidth), and Child (Total consumer of bandwidth)
#Prority, measured from 1 (Highest Priority/Most Important) to 8 (Lowest Priority/Least Important)
#Create a simple parent queue, with your total pool of bandwidth, for your target bridge or LAN subnet, syntax is Upload/Download. This is for a 20Mbps Upload, and 170Mbps Download internet connection.
#Use your real-world numbers -- not what is on the ISP's account package!
#Create the Parent Queue.
/queue simple add max-limit=20M/170M name="Office Parent Queue" target=
#Create the Child Queue for RTP Traffic, priority 1/1 (Upload/Download). Each VOIP phone call takes up 256KBps, so 2M/2M is for 8 VOIP calls.
/queue simple add limit-at=2M/2M max-limit=2M/2M name="VOIP-RTP Queue" parent="Office Parent Queue" target= priority=1/1 packet-mark=VOIP-RTP
#Create the Child Queue for SIP Traffic, priority 2/2
/queue simple add limit-at=2M/2M max-limit=2M/2M name="VOIP-SIP Queue" parent="Office Parent Queue" target= priority=2/2 packet-mark=VOIP-SIP
#Create the Child Queue for all unmarked traffic (everything else), priority 8/8.
/queue simple add max-limit=15M/160M name="All Other Traffic" parent="Office Parent Queue" target= priority=8/8 packet-mark=no-mark
#You can monitor if your marks are applying, through IP > Firewall > Connections > Add Column: Connection-Mark > Sort by Connection-Mark, and through watching Queues, and watching the trees colors during a speed test. Run a VOIP call while trying to max out the internet.


Mikrotik – Simple WAN Hard Failover

It is amazing how many ways there are to configure a simple WAN Failover on a Mikrotik. This post, contains three simple lines of code, that will perform a hard failover: Use a primary connection 100% of the time, if the primary line becomes unable to ping an external IP, switch entirely over to the failover line. When the primary comes back up, return to primary.

A common weakness of the simple “check-gateway” ping on a route, is if you are not in bridged mode — because your ISP does not offer true PPPoE bridged mode, the failover will not occur in any event except physical-disconnection — your Mikrotik will always be able to ping the gateway is it directly plugged into. What we really care about, is loss of internet access — not just electrical connectivity. When testing failover, disconnect the input, not the cable to your router or the modem’s power.

A common internet setup:

ISP <> Coax Cable / Fiber <> Modem/ISP-Gateway <> Ethernet Cable <> Ether1 Mikrotik

If you unplug the power of the modem, or disconnect the ethernet cable going to your router, your failover usually will test just fine, because the route to your gateway has been lost — but it won’t work if the ISP has issues.

For a proper test – to simulate the ISP having internal routing problems, or your area’s network node goes down, disconnect at the Coax/Fiber side — one step behind the Modem.


One of the more common methods of failover with Mikrotik is using netwatch to monitor interfaces ability to ping external IPs, if a down state is detected, running a script that changes priority of the primary route, or disables an interface or route entirely. These scripts are normally run every 5-10 seconds. I feel uncomfortable with this method, because complexity increases substantially for failing back to the primary interface. Some code can get pretty intricate.


The below code is simple and reliable, but not immediate. If you want zero-loss in connectivity, you’ll probably need to use scripts for a quicker response.

With these route-based rules, failover times are about 15 seconds. From the time internet connectivity stops, to failing over, to workstations regaining internet access, is about 5-15 seconds. From testing, failing back to primary is a little quicker, maybe 5 seconds.

The way the code operates, is pinging a public DNS server, set to Scope 10. The primary route you use for internet access, is also in Scope 10. Route distance is 1.

Distance is a routing metric, that determines the priority that a route will be taken. The lower the distance — the higher priority it takes for flowing traffic. For example, a route at distance 5, will be taken over a route at distance 10.

When the Check-Gateway ping which is forced to flow through our primary ISP gateway of fails, it’s distance is increased to 200 and it is marked as unreachable/inactive. Now the next lowest route is “2”, the failover route.

The ping will continue to run on the primary route, once the DNS server responds, the route will be re-enabled automatically, bringing it’s distance back to 1 — a priority higher than distance 2 — the failover route — traffic resumes flowing through the primary pipe.

#This hard-codes the Verizon Public DNS Server ( to always go out the primary gateway's IP (usually the gateway IP provided by your ISP), *recursively*, you want to confirm connectivity. Only choose a reliable server (Google is, Comcast is, Verizon is, etc).
#Note that this will make ONLY go through your primary gateway, if your primary gateway stops working, and you're on the failover line, you won't be able to ping this server.
#The scope of 10 is the default scope, which includes any routes you add that don't have a different scope.
/ip route add dst-address= gateway= scope=10 comment="Validate Primary Gateway"
#This runs the ping that checks for connectivity. Distance is  1 -- the lower the number, the higher the priority. Traffic will flow through the lowest-numbered route that is reachable/working.
/ip route add gateway= distance=1 check-gateway=ping comment="WAN Primary"
#This is the failover route, ISP Gateway for the failover line distance is 2, higher than the default route.
/ip route add gateway= distance=2 comment="WAN Secondary"


Mikrotik IKEv2 VPN Server Setup Guide

Looking for a detailed guide on configuring a Mikrotik IKEv2 VPN server? Need your on-the-road devices to be able to remotely access your internal LAN? Then you’ve come to the right place 🙂

The major functional benefit of IKEv2, over L2TP/IPsec VPNs, is that L2TP only allows one source IP per client, while IKEv2 has no limit. If you have say, three Windows laptops all on the same internet connection (hotel WiFi or hotspot) trying to connect into the company VPN, only the most recent connection will remain live — just one laptop at a time. You could always side-step the issue by using a cell-phone hotspot for each laptop — which changes the source IP, but that isn’t always an available option. IKEv2 doesn’t have this L2TP-based issue, so load up as many clients as you want.

With that said, IKEv2 is substantially harder to configure for the first time than L2TP/IPsec, and harder to configure for OSX clients for the first time.

  • L2TP: DNS Hostname/IP + user/password + shared secret
  • IKEv2 is: DNS Hostname + Certificate Authority + Server Certificate + Machine Certificate

With this guide, it shouldn’t be too hard to knockout.



As of 01/30/2018 writing this guide, there is a bug with certificates in the Mikrotik Current Release Channel (6.41) — causing the error: “unable to get local issuer certificate”. Sometimes IKEv2 connects perfectly… With the exact same code, more often than not on 6.41, you’ll get the “local issuer certificate depth 0” error under the the Mikrotik Log in the IPsec category. Use the BugFix/Stable channel (currently 6.39.3) and everything works A-OK.

Create Certificates

We are making the Mikrotik router the Certificate Authority, which signs a TLS-Server certificate linked to it’s DNS name, and then also signs machine-specific certificates.

This means you are authenticating computers by machine — not by a username/password. If you want usernames + passwords on top of machine certificates, you’ll need to configure radius authentication, which is beyond the scope of this article.

Default expiration for keys is 365 days (1 year), so I set it to 3650 (10 years), hence the “days-valid” argument.

Adjust the common name to be your company’s DNS address of the VPN Appliance. e.g. vpn.yourdomain.com. In my instance, I configured the CA-Crl-Host to be the LAN IP address of the device.

We create a Certificate Authority, so certificates can be created. We create and sign a TLS-Server certificate which will allow the Mikrotik to receive connections.

##Mikrotik IKEv2 VPN Server Guide
#Create your Root Certificate Authority
###Replace common name with Public DNS name of VPN appliance, and replace ca-crl-host IP with IP of LAN router.
/certificate add common-name="vpn.yourdomain.com Root CA" name=ca days-valid=3650
/certificate sign ca ca-crl-host=
#Delay pause due to it taking about 0.5s for the CA to be ready for terminal to access it.
:delay 2
#Create your VPN Server Certificate. Ensure to change common-name to DNS of VPN Server, and add the IP of the VPN server as alternative name.
/certificate add common-name=vpn.yourdomain.com subject-alt-name=IP:vpn.yourdomain.com key-usage=tls-server name=vpnserver1 days-valid=3650
/certificate sign vpnserver1 ca=ca

Configure Mikrotik IKEv2 Settings

We are going to have our VPN clients connect to their own subnet, rather than snatching IP addresses from the DHCP server in your primary LAN. This also lets you manage the VPN clients subnet with custom rules if needed, very helpful for controlling access or shaping traffic.

#Create the VPN Bridge
/interface bridge add name=vpn-bridge
#Add an IP address to the VPN bridge, making it act as a gateway for VPN clients
/ip address add interface=vpn-bridge address= comment="VPN Bridge IP"
#Configure the IPSec Proposal encryption levels
#SHA1 and AES-128-cbc required for Windows 7 clients
#SHA256 and AES-256-cbc required for OSX
/ip ipsec proposal set [ find default=yes ] auth-algorithms=sha1,sha256 enc-algorithms=aes-128-cbc,aes-256-cbc pfs-group=modp2048
#Create an IP pool for VPN clients
/ip pool add name=vpn-pool ranges=
#Configure a Mode Config to use that pool -- CHANGE THE IP ADDRESS to your to your internal Domain Controller/DNS server. If you don't have one, use the IP of the vpn-bridge.
/ip ipsec mode-config add address-pool=vpn-pool address-prefix-length=32 name=vpn-config system-dns=no static-dns=
#Configure IPSec to allow peers to connect, as long as they follow these encryption rules
/ip ipsec peer add address= auth-method=rsa-signature certificate=vpnserver1 dh-group=modp1024,modp2048 enc-algorithm=aes-256 exchange-mode=ike2 generate-policy=port-strict hash-algorithm=sha256 mode-config=vpn-config passive=yes
#Configure IPSec Policy to allow connection to the following networks.
/ip ipsec policy set 0 dst-address= src-address=

Export Machine Certificates

Time to create, and export the certificates our workstations will need.

#Export certificates so clients can use their cert. They will need to import the trusted Certificate Authority, and then import their personal cert, which should be password protected.
#Export the root Certificate Authority, this will be saved into the root of "Files" tab, no password. Drag cert_export_ca.crt to desktop.
#This certificate is imported to the Trusted Root Certificate Authorities > Certificates store.
#Start > Run > MMC.exe > File > Add Snap-In > Computer Account > Trusted Root Certificate Authorities > Right-Click > Import > Certificates > Import .CRT file (cer_export_ca.CRT)
/certificate export-certificate ca

#Create each client machine certificate, make it match the hostname of the local machine.
/certificate add common-name=computer1 key-usage=tls-client name=computer1 days-valid=3650
/certificate sign computer1 ca=ca

#Export the client's certificate. Matches the "name" of the certificate. Exports a .P12 password protected file, ready for import into a Windows machine.
#Start > Run > MMC.exe > File > Add Snap-In > Computer Account > Personal > Right-Click > Import > Certificates > Import .P12 file (e.g. cert_export_computer01.p12)
#This certificate is imported to the LOCAL COMPUTER Account > Personal > Certificate Store
/certificate export-certificate computer1 export-passphrase=SuperSecretPassword type=pkcs12


Install Certificates on Windows

From Winbox > Files, drag your exported files to your local PC. They should be named:

  • cert_export_ca.crt (Trusted Root Certificate Authority)
  • cert_export_computername.p12 (PKCS#12 / PFX Encrypted Client Certificate)

Start > Run > mmc.exe > File > Add/Remove Snap-In > Certificates > Local Machine

Certificates (Local Computer) > Trusted Root Certification Authorities > Right-Click > All Tasks > Import > Browse > cert_export_ca.crt > OK.

Certificates (Local Computer) > Personal > Right-Click > All Tasks > Import > Browse > Change File Name Filter from X.509 to .p12 (Personal Information Exchange) >  cert_export_computername.p12 > Enter Password > Check: Mark this key as exportable > Next > OK.


Configure VPN Connection on Windows

Start > Control Panel > Network and Sharing Center > Set up a new connection or network

Connect to a Workplace/VPN > No, create new > Use Internet (VPN) > Internet Address: vpn.yourdomain.com > Check: Don’t connect now/Setup later.

Network and Sharing Center > Adapter Settings (left) > right Click VPN Connection > Properties > Security: Type: IKEv2: Use Machine Certificates > OK

As long as you have already successfully imported your CA and computer certificates into the computer’s Local Store, you should now be able to connect.

Windows 10 users may need to also edit the Metro Window’s settings to use Certificate Authentication instead of user.



Install Certificates on MacOS

Open KeyChain Access

Get the .cert_export_ca.crt and cert_export_computername.p12 certificates onto the Mac computer.

File > Import: cert_export_ca.crt > System > Browse to System > find vpn.yourdomain.com > Open > Trust: Always Trust > Close

File > Import: cert_export_ComputerName.crt > System > Browse to System > find ComputerName > Open > Trust: Always Trust > Close

Configure VPN Connection on MacOS

Apple’s built-in VPN client doesn’t give us many options, one of the missing settings, which should really just be a checkbox under System Preferences, is disabling EAP. The only way around it I’ve found, is to obtain Apple Configurator from the App Store, and create a custom profile that installs a IKEv2 Policy along with the certificates. Configurator loads in those extra invisible buttons into an important file.

Open the App Store > Apple Configurator > Install > Open.

File > New Profile


Browse to the CA cert file, also browse to the machine .P12 cert file, enter the password > Enter. Both should appear as trusted since you already marked them as trusted under Keychain Access.


  1. Name: Company VPN
  2. Type: IKEv2
  3. Server: vpn.yourdomain.com
  4. Remote Identifier: vpn.yourdomain.com
  5. Local Identifier: ComputerName (must be ExAct)
  6. Machine Authentication: Certificate, select cert_export_MachineName
  7. Enable Perfect Forward Secrecy: Checked
  8. Encryption Algorithm: AES-256
  9. Integrity Algorithmy: SHA-256
  10. Diffie-Hellman Group: 14 (2048 bit)

File > Save As > Name

On Mac > Double-Click the Saved Profile > Install

Now Open System Preferences > Network, Your VPN connection should have been created, and can now connect without issue — woohoo!


Wow, that was a lot of work, hoping you got it going, thanks for reading this far, and good luck in all your future endeavors!

Mikrotik L2TP IPsec Dedicated VPN Appliance Setup

Mikrotik L2TP IPSec VPN Guide – Start to Finish Appliance

There are a small number of L2TP IPSec VPN guides, I found them pretty frustrating, and often conflicting when integrating into an existing network. This guide provides full configuration steps for a Mikrotik L2TP/IPSec VPN appliance. It does not have to be the primary router. VPN clients are integrated into their own network/bridge, and from there, can connect in to the primary LAN.

First Steps

Update the Router Operating System

  • System > Packages > Check for Updates > Current > Download and Install

Disable Beeping Sounds on Boot

  • System > Routerboard > Settings > Silent Book: Checked > OK

After reboot, upgrade the Router Firmware

  • System > Routerboard > Upgrade
  • System > Reboot > OK

Now Reset the router to defaults

  • System > Reset Configuration > OK

Disable the DHCP server

  • IP > DHCP Server > Select > X (Disable)


Set an identity

  • System > Identity > COMPANY-VPN

Add a static IP to bridge.

  • IP > Addresses > + (Add) > IP/subnetmask (e.g.

Add ETH2 to bridge

  • Bridge > port > + (Add) > ether2-master > bridge

Create two NAT rules (if not already present), a NAT for Internet Access from the LAN, and a NAT for LAN access from the VPN clients.

  • IP > Firewall > NAT > + (Add) > Chain:srcnat > Out Interface: Ether1 (WAN Port) > Action: Masquerade
  • IP > Firewall >  NAT > + (Add) > Chain: srcnat > Out. Interface: bridge (LAN bridge) > Action: Masquerade


Security Hardening

Disable Unused Services

By default a Mikrotik comes with all services enabled

Disable the services you don’t use.

  • IP > Services > Disable all except for Winbox (TCP 8291)
  • IP > Firewall > Service Ports > Disable ALL
  • Tools > RoMon > Disabled
  • IP > Settings > RP-Filter=strict (Prevents IP Spoofing)

Configure Password

Change the Mikrotik’s password to administer the device

  • System > Password > Select a new password

Disable Winbox Discovery on WAN / Reverse Path Filtering

  • IP > Neighbors > Discovery Interfaces > Ether1: Disabled


VPN Settings Config

VPN Subnet

If you need to connect say, 10+ people via VPN, you might not want to use up IPs in the standard LAN range, gobbling up IPs from your DHCP server, in which case, you should create a separate subnet for VPN users, that is able to communicate with the internal LAN.

To do this, there are four things to modify:

  1. Create a bridge — it does not need to be linked to any interface by port.
    1. Bridge > + (Add) > Name: vpn-bridge.
  2. Assign an IP Address to the VPN Bridge.
    1. IP > Addresses > + (Add) >
  3. Create a NAT rule if not already present — this let’s VPN clients talk to the network
    1. IP > Firewall > NAT > + (Add) > Out-Interface: bridge-vpn > Action: Masquerade.
  4. Enable a DHCP server on the VPN Bridge
    1. IP > DHCP Server > Edit the DHCP entry > Interface: vpn-bridge.
    2. IP > DHCP Server > Networks
      1. Network: — Your VPN Bridge LAN
      2. Gateway: — Your VPN Bridge LAN IP Address
      3. DNS Servers:  IP of Domain Controller/DNS Server + (VPN Bridge)
      4. Domain: your FQDN (company.local, etc).
      5. IP > Pool > Adjust IP range to match DHCP Server.
        1. E.g.

Create User Accounts

  • PPP > Secrets > + (Add)
    • Name: username
    • Password: password
    • Service: any
    • Profile:default

VPN Policy

  • PPP > Profiles > Edit “default”
    • General
      • Local Address: IP of Mikrotik
      • Remote Address: default-dhcp (IP pool)
      • Bridge: vpn-bridge
      • DNS Server(s): IP(s) of DNS servers in the building, usually a Domain Controller.
    • Limits – Rate-Limit — Optional — if you want to rate-limit per-client.
      • XXM/YYM, where XX is download and YY is upload in Mbps. (10M/5M)

L2TP VPN Bare Minimum Firewall Rules

IP > Firewall > Delete all rules possible.

Paste all rules below into New Terminal

VPN Rules

  • /ip firewall filter add chain=input action=accept comment=”VPN L2TP UDP” in-interface=ether1 protocol=udp dst-port=500,1701,4500
  • /ip firewall filter add chain=input action=accept comment=”VPN L2TP ESP” protocol=ipsec-esp
  • /ip firewall filter add chain=input action=accept comment=”VPN L2TP AH” protocol=ipsec-ah

Public Router Security Rules

  • /ip firewall filter add action=drop chain=input comment=”Drop Blacklisted Hosts to Router” in-interface=ether1 src-address-list=BlackList
  • /ip firewall filter add action=drop chain=forward comment=”Drop Blacklisted Hosts through Router” in-interface=ether1 src-address-list=BlackList
  • /ip firewall filter add chain=input comment=”Accept Established / Related Input” connection-state=established,related
  • /ip firewall filter add chain=forward comment=”Accept Established / Related Forward” connection-state=established,related
  • /ip firewall filter add action=add-src-to-address-list address-list=BlackList address-list-timeout=1d chain=input comment=”Detect Port Scanners” dst-port=21-23,53,88,135-139,389,445,1433,3306,3389,5900,6667 in-interface=ether1 protocol=tcp
  • /ip firewall filter add action=add-src-to-address-list address-list=BlackList address-list-timeout=1d chain=input comment=”Detect UDP WAN DNS Lookups to prevent DDoS” dst-port=53 in-interface=ether1 protocol=udp
  • /ip firewall filter add action=accept chain=input comment=”Accept ICMP/Ping” protocol=icmp
  • /ip firewall filter add action=drop chain=input comment=”Drop Input” in-interface=ether1

L2TP Server Enable

  • IP > IPsec > Peers
    • New (+)
      • Address: (for allowing any internet IP to attempt to connect)
      • Auth Method: pre shared key
      • Exchange Mode: main l2tp
      • Secret: “SharedSecret” (Must match the PSK from PPP > L2TP Server)
    • Advanced Tab
      • Policy Template Group: default
      • Send Initial Contact: Enabled
      • NAT Traversal: Enabled
      • My ID type: auto
      • Generate Policy: port strict
      • Proposal Check: obey
    • Encryption Tab
      • Hash Algorithm: sha1, sha256
      • Encryption Algorithm: Check: aes-128, aes-192, aes-256
      • DH Group: Check: modp1024
  • IP > IPsec > Proposals: Default
      • Auth Algorithms: sha1, sha256
      • Encr Algorithms: aes-128 cbc, aes-192 cbc, aes-256 cbc
      • PFS Group: modp1024

Allow VPN to Local Routing

  • Interface > ether2 (LAN port) > ARP > Change from “Enabled” to “Proxy-Arp”

L2TP Server Config

  • PPP > Interface > L2TP Server
    • Enabled: Yes
    • Use IPsec: Yes
    • Default Profile: Change from “Default-encryption” to “default”
    • Authentication: MSCHAP2 ONLY
    • IPsec Secret: “SharedSecret” (match what was in the IPsec Peer)

Now you can connect from a Windows or Mac client.

Note about DNS lookups

If you try performing a NETBIOS broadcast, for example: “ping server01”, it will time out.

NETBIOS broadcast does not work through the VPN — but FQDNs do.

For example, server01 will not resolve.

Server01.domain.local will resolve

If you need to connect to an internal terminal server but don’t want to use an IP for hostname, you should create an A record on the internal DNS server to match, this would help internal clients resolve directly as well. E.g. remote.company.com on their DNS server.

Additional Steps – Run once

New Terminal Button, copy/paste

#Set the device to reboot every month at 4AM, can’t hurt 🙂

/system scheduler add interval=30d name=”Reboot Router Monthly” on-event=”/system reboot” start-date=jan/01/1970 start-time=4:00:00

#Set the clock time zone

/system clock set time-zone-name=America/Los_Angeles

#Set the time servers

/system ntp client set enabled=yes primary-ntp= secondary-ntp= server-dns-names=time1.google.com,time2.google.com


Multiple Clients — Same Source IP Problem

This is an issue for ANY L2TP VPN appliance, not just Mikrotik gear. The L2TP protocol always initiated connections on the same port, UDP1701. Carried inside of the header is an identifier — usually including the source IP address of the connecting client. If you have a single computer connecting, no issues. If you have a second computer in the same network (e.g. two laptops at a hotel trying to VPN in), the most recent connection will kick off the previous, pre-established connection.

As a note, there is an optional setting in the L2TP VPN protocol, that using a Strict Port setting, allows clients to select a different UDP port once a connection is established, rather than being hard-coded to UDP1701. In practice, it works on Macs/Linux, and does not work on Windows clients. I’ve had 5x OSX devices connect from the same source IP without issue. I’ve had 1x Windows, and 5x OSX devices connect without issue. The moment you have a second Windows L2TP client attempt to connection, the previous connection will be kicked.

What’s the fix if you’ve got a lot of Windows clients sharing the same Source IP? — use different source IPs (cell-phone hotspot), or configure an IKEv2 VPN Server, rather than a L2TP VPN Server. I am currently writing a detailed IKEv2 Mikrotik VPN guide at the moment.


  • System > Logging
    • New (+)
    • Create Three Topics: l2tp, ppp, and ipsec
    • Action: Memory
    • From here you will be able to see logs under “Log” and google your solution where something may need adjusting.
  • For Windows 10, make sure you enter the preshared key twice — once when creating the VPN connection, and then editing the connection after Windows had made it — it isn’t saved automatically.

Windows error for no client saved pre-shared key: “The L2TP Connection failed because the security layer encountered a processing error during initial negotiations.

Mikrotik error for no client saved pre-shared key. Log: “no peer config” or “failed to get valid proposal” or “failed to pre-process ph1”


  • For MacOS

Make sure you configure “tunnel all” mode in advanced under System Preferences > Networking when adding a L2TP IPSec connection. Without tunnel all, you will only be able to ping the gateway (, rather than other devices in the network.

Convert UEFI Win7/2008 R2/SBS2011 Physical Machine to HyperV Gen 1 VM

Wow, what a special case this is. This is the third time I’ve run into this issue, having to convert a workstation or server installed as a physical machine, into a HyperV VM. When installed from the factory, often techs will use UEFI — which makes for a nightmare on converting to a HyperV VM.


For newest OS, like Win8/10/2012, it isn’t much of an issue, for older OS, like Win7/2008R2/2011, it’s a problem, because HyperV only supports UEFI booting in Gen2. There are two parts:

  1. Converting the physical machine into a VHDX — this is easily accomplished with Disk2VHD.
  2. Converting the exported machine from a UEFI/GPT machine (Gen 2), to a BIOS/MBR machine (Gen1).


If you simply try loading the VHDX into a Gen 2 VM, you’ll just get a black screen with an underscore blinking and no progress. If you boot into a Gen1 VM, expect it to freeze.

This guide will cover part 2, as Disk2VHD is so simple to use it doesn’t need to be in this guide.



Disk2VHD – Converts Physical machines to VHDXs on a network share

AOMEI Partition Assistant Server/Technician/Unlimited – Converts VHDXs from GPT to MBR

Installation ISO matching your OS and architecture, e.g. Win 7 x32, or Server 2008 R2 x64. Once the ISO has booted, you can hit Shift+F10 at any point to open a command prompt.



From your HyperV host, with the exported VHDX stored on your host, mount the VHDX – Right Click > Mount.

Browse to My Computer, look in the disk, make sure your content appears.

Disk Management > Detach VHD > this releases your Windows explorer file lock that would require a reboot from AOMEI.

Mount the VHDX again.

AOMEI > Select Disk > Tools > Convert GPT to MBR > Apply > Wait….

Create a Gen 1 VM in HyperV, give it enough CPU/RAM to be decent, and add a DVD drive and mount your installation disc.

Boot to CD, repair menu, nothing should be detected, or if it is, it’s at 0MB. Choose Recovery Tools > Command Prompt, or if recovery tools do not appear, hit Shift+F10 to open a command prompt.


Finding and Repairing the Boot Partition

We need to find the disk holding your content. Go through the drive letters until you find it, starting at C:. X: is the boot DVD.

example: C: > DIR > not Windows…. move on to D: > DIR > not Windows … G: > DIR > list populates, showing G:\Windows and G:\Users and other root folders.



list disk
#Where X is the number if your disk
Select Disk X

list volume

#Where Y is the number of your volume containing Windows
select Volume Y

list partition

#Where Z is the number of your partition containing Windows
select partition Z

#This makes the partition active -- able to be booted from and repaired by tools.


Reboot into CD, return to repair menu, if Windows offers to repair, don’t let it, just a waste of time. Open Command prompt again:

Change to your drive letter, it is most likely now C:


bootrec /fixmbr

bootrec /fixboot

bootrec /rebuildbcd

Even if rebuildbcd doesn’t find an installation, “0 Windows installations found”, somehow it still seems to have an effect on the boot process succeeding, I’ve seen “0 installations found” machines become bootable. Other times, you need to create the BCD store.


Reboot, return to repair > command prompt

browse to your drive again, most likely C:

#if Windows shows up..... run
bcdboot C:\Windows

Your boot information will be rebuilt. Remove the CD, start the VM, watch in amazement as the Gen1 boot turns on. You will likely need to use the HyperV Integration Services disc for drivers to work, allowing for network connectivity and higher resolutions.


Hoping that gets you on the right track, good luck!

Task Scheduler – Mount VHD and Mark Online Read/Write Mode – Powershell

Some helpful code. I needed to mount a VHDX on System Startup with a Scheduled Task, and have it automatically mount the drive into a writable state, since by default,  Mount-VHD mounts in read-only mode, and with disk status offline.

Save the code into a .PS1 file, call it upon system startup.

Code below.

#######Mount a VHDX and mark as online writable via Powershell#######

##Mount the VHDX
Mount-VHD -Path "D:\Folder\VHD-Disk.vhdx"

#Obtain Details about the VHDX, look for the UniqueID Field
Get-Disk | FL

##Replace the UniqueID field below, set properties of default offline status, and default read-only status, to off/false.
##The -IsReadOnly command needs to be run separately from the -IsOffline command, or else you'll get the error, "Parameter set cannot be resolved using the specified named parameters."
##Drive will auto-map with the last drive-letter specified through Disk Management.
##If you want to specify a Partition Letter for newly created disks, you'll need to use DiskPart or another Partition-related tool, rather than a disk-specific tool like "Mount-VHD"
Get-Disk | Where-Object UniqueID -eq 12345678901234567891234567890123 | Set-Disk -IsOffline $False
Get-Disk | Where-Object UniqueID -eq 12345678901234567891234567890123 | Set-Disk -IsReadOnly $False

Create a Scheduled Task via Command Line to automount the drive on boot.

::Creates a Scheduled Task.
::TN = Task Name
::SC = Schedule/Time
::RU = Run User
::TR = Task Run
::Format for command is "'EXE' paramters"
schtasks /create /TN "AutoMount VHD" /SC ONSTART /RU "NT AUTHORITY\SYSTEM" /TR "'%systemroot%\System32\WindowsPowerShell\v1.0\powershell.exe' C:\scripts\AutoMountVHDX.ps1"



DigitalSignage – Free Video Slideshow – FFMPEG – Batch Script to Export JPG or PNG to MP4

The goal: take 100 .JPG or .PNG images, and export them to a video-slideshow as a MP4 container on a Windows computer.

This was way harder than I expected it to be without spending $60-100 on complex video editing software.  So many of the conversion guides require Linux or OSX to use the Blob (wildcard) feature for inputting file-names, but it doesn’t work on Windows.

I needed something simple enough I could give it to a common user, and get them creating video slideshows.


Here is my solution, hoping someone out there finds it helpful.

Get the binary for ffmpeg.exe from: https://www.ffmpeg.org/download.html and click the Windows Build download link.

The only file you will need from this ZIP is ffmpeg.exe.

Create a new folder on your desktop, copy in your images (.PNG or .JPG, whatever you’re converting), and copy in ffmpeg.exe.

Create a new text file and change the file extension to .BAT (Batch Script).

Pop in the following code.

::Import screenshots/photos, and export them into a MP4 to be uploaded for digital signage displays or other uses.

::This creates a "short-format" list of any .PNG files in a list by listing the files in a loop, and outputting to a text file called images.txt. If you need to adjust to .JPG or .GIF, edit below.
::The images.txt file will be fed into ffmpeg for processing of video files.
::If you ever need "long-format" (C:\Folder\image1.png vs image2.png) you can put /r after the "for" command.
for %%a in (*.PNG) do (
    echo file '%%a' >> images.txt
::This requires the file "ffmpeg.exe" be in the same directory as the photos
::Input Frame Rate - 0.1 frames per second = 1 image per 10 seconds. 
::File -- Add together the Input of images.txt
::Video Format - libx264 inside of a .mp4 container
::Output Video Frame Rate - 30fps (required for a lot of digital signage systems to actually process the video, don't worry, size doesn't increase very much)
::Name - File Name (NewVideo.mp4)
::Yes - Overwrite Prompt
ffmpeg.exe -r .1 -f concat -i images.txt -c:v libx264 -pix_fmt yuv420p -r 30 NewVideo.mp4 -y

::Deletes the images.txt format so images don't double-up.
del /q images.txt

::Waits for user input before closing the command prompt, to make sure everything runs propertly.


RemoteApp – Auto Configure and Setup Shortcuts

RemoteApp Auto-Configure on Logon for Domain Joined Computers

Tired of having to train users to configure RemoteApp? Tired of doing it for them? Use the following script to automatically deploy RemoteApp on Windows 7 and Windows 10.


Note: This procedure expects your users to be using a domain logon that the credentials match the RemoteApp server. If local creds are different from Domain Credentials, you may want to remove the “WorkspaceSilentSetup” argument later.


WSX File Prep

Take the following code in Notepad, replace bold with your RemoteApp server, and save to a filename “SetupRemoteApp.wsx”. Place this file in your NETLOGON directory (e.g. \\domain.local\NETLGOON)

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<workspace name="Work Resources" xmlns="http://schemas.microsoft.com/ts/2008/09/tswcx" xmlns:xs="http://www.w3.org/2001/XMLSchema">

 <defaultFeed url="https:/remote.company.com/RDWeb/Feed/webfeed.aspx" />




GPO Deploy Script

Create a GPO to install a shortcut in the Startup Folder. After a single login of any domain user, all future domain user’s who log in to that computer will have the .WSX automatically execute, setting up their RemoteApp config.

User Configuration > Preferences > Windows Setttings > Shortcuts

Name: Setup RemoteApp


Target Type: File System Object:

Location: All Users Startup (%allusersprofile%\Microsoft\Windows\Start Menu\Programs\StartUp)

Target Path:C:\Windows\System32\rundll32.exe

Arguments:tsworkspace,WorkspaceSilentSetup \\domain.local\NETLOGON\SetupRemoteApp.wsx

Icon Index: Pick one, I like 12, a computer chip 🙂

Common Tab > Remove this item when it is no longer applied: CHECK


GPO Shortcut to Work Resources Script

Create another shortcut, this one really is a shortcut — to the Work Resources folder that contains all of that user’s programs. You can put both in if you want, the shortcut will only apply if the directory exists.


Windows 7 Path: %appdata%\Microsoft\Windows\Start Menu\Programs\RemoteApp and Desktop Connections\Work Resources

Windows 10 Path:%appdata%\Microsoft\Windows\Start Menu\Programs\Work Resources (RADC)


User Configuration > Preferences > Windows Setttings > Shortcuts

Name: Remote Apps


Target Type: File System Object

Location: All Users Desktop

Target Path:%appdata%\Microsoft\Windows\Start Menu\Programs\Work Resources (RADC)

Icon Index: Pick one, I like 3, a standard folder

Common Tab > Remove this item when it is no longer applied: CHECK



Office 365 – Hard Linking Azure AD Connect Users to Office 365 Accounts

Wow, now talk about a niche issue!

You’ve setup Microsoft Azure Active Directory Connect, to sync the usernames/passwords with your Office 365 accounts. However, some of the O365 accounts were already in use when you created your Active Directory domain.

There are two major reasons to do this:

  1. Your staff user accounts are linked with their Office 365 account — one password synced between accounts, change one, you change the other.
  2. Your users don’t have to activate their Office 365 ProPlus every time on a terminal server, this requires Password Syncing + Seamless Single Sign-On (a checkbox really…).
    1. This previously used to require Active Directory Federated Services, a god-awful nightmare of configuration and server setup that doesn’t make sense for a small business.

During the initial setup of Azure AD Connect, it will auto-sync, creating some users that are very close in name, but completely different in account (GUID). Your goal is to get the Local Active Directory account to be directly linked to the Office 365 account (with email and other goodies already active that you don’t want to lose).


The process of using Powershell to directly tap into O365 and link the two accounts is called Hard-Linking. There is also Soft-Linking, which only happens when a local AD user is first created, or when AD Connect is initially setup — the email field in Active Directory is matched to the email field in Office 365. There is an IDFix tool provided by Microsoft, in my experience it’s worthless. If both accounts are already live, you have to do hard-linking.

For starters, add the UPN (User Principle Name) suffix of your O365 domain. For example, if your internal AD domain is: cn.company.com, but your O365 domain is company.com, go into Active Directory Sites & Trusts > Right-Click Server > Properties > Add UPN Suffix: company.com.

This will give you the option in Active Directory Users and Computers to change your account names from user@cn.company.com, or even main\user, into an email address format: user@company.com. Edit the properties of any account you want synced to match your email domain.


The goal is to take the Active Directory Object GUID, and over-write the O365 Immuatable ID with the AD GUID. This will force them to link on their next Delta sync (generally 2-10 minutes). However, you can’t have a single GUID on two different accounts… So you have to blow away one of the 365 accounts — the duplicate that was unnecessarily created.

This gets slightly messy, and sort of dangerous — make damn sure you know what you are deleting through Powershell! Screw up and *poof* goes a user’s O365 email and file storage.


The code:

#Dan Kruse
#October 6th 2017
#How to hard-link a mismatched Active Directory Account to an Office 365 account.
#Run this on Powershell on the Active Directory Server running Azure AD Connect.

#Allow Remote Scripts To Run 
Set-ExecutionPolicy RemoteSigned

#Store Office 365 Global Admin Creds and connect to MS online 
$credential = Get-Credential 
#You will be prompted to enter a login, use a 365 Global Admin account.
Import-Module MsOnline 
Connect-MsolService -Credential $credential

#After adding the UPN Suffix of the email domain, change the user's Account Tab in Active Directory to match their email (e.g. jsmith@company.com)

#Obtain the ObjectGUID of the Active Directory account and load it into a variable
$guid = (Get-ADUser -Identity johns).ObjectGUID

#Attempt to write the GUID to the valid 365 Account, it should fail...
Set-MsolUser -UserPrincipalName jsmith@company.com -ImmutableId $immutableid

#If/When you get a uniqueness violation/SourceAnchor
#Make **absolutely sure** this user doesn't have any email (Exchange Online Plan 1) license associated with them.... For duplicate accounts ONLY
#Delete the empty/unnecessary O365 account recently created by the sync.
Remove-MsolUser -UserPrincipalName johns@cn.companyname.com

#The GUID is still active until you purge the user from the Office 365 recycle bin, this perma-deletes the account, no going back.
Remove-MsolUser -UserPrincipalName johns@cn.companyname.com -RemoveFromRecycleBin

#Now Hard-Link the user with the Set-MsolUser command from before (again, this time it should go through with no message, just a successful command run)
(Previous Set-MsolUser command above)

#Sync Active Directory to O365, deletions are immediate, password syncs are 2-10 minutes.
Start-ADSyncSyncCycle -PolicyType Delta


Mikrotik VPN – L2TP/IPSec Server for Remote Clients (Windows/Android/iOS)

Mikrotik VPN – L2TP/IPSec Server for Remote Clients

If you’re looking for a quick guide for configuring a Mikrotik VPN Server, allowing remote clients to connect into your building controlled by a Mikrotik Router, you’ve come to the right place.

This guide was written for Mikrotik RouterOS v6.41  in September 2017. It presumes you have your main (edge) router as a Mikrotik device, and are NOT behind a double-NAT.

Single-Nat: Modem > Router > Devices.

Double-Nat: Modem > Router > Router > Devices. If your Mikrotik Router has a WAN IP in the ranges of: 192.168.X, 10.X, or 172.16.X, it’s a double-NAT.


Alrighty, let’s get started!

There are two parts of a L2TP Server:

  1. L2TP VPN Protocol – Creates the link between two locations
  2. IPSec Encryption – Secures and protects the link

Configure L2TP Server, under PPP (Point-to-Point Protocol)

PPP > Interface > L2TP Server
  Check "Enabled" to turn on the L2TP Server
  Default Profile: default
  Authentication: Check only "mschap2"
  Use IPsec: Yes
  IPsec Secret: YourPreSharedKey
  Caller ID Type: IP Address
PPP > Profiles > Default (Create your rules for users)
##If you have multiple bridges to separate your network, create a profile for each and specify the bridge, otherwise ignore.
  Local Address: IP of your local Mikrotik Router (e.g. or
  Remote Address: DHCP pool
  DNS Server: IP of your DNS server/router or (Google DNS)
PPP > Secrets (Create your users)
  New (+)
  Name: Username
  Password: UsersPassword
  Profile: default


Configure IPSec Encryption

IP > IPsec > Peers
  New (+)
  Address: (for allowing any internet IP to attempt to connect)
  Port: 500
  Auth Method: pre shared key
  Exchange Mode: main l2tp
  Secret: YourPreSharedKey (Must match the PSK from PPP > L2TP Server)
  Advanced Tab
    Policy Template Group: default
    Send Initial Contact: Enabled
    NAT Traversal: Enabled
    My ID type: auto
    Generate Policy: port override
    Proposal Check: obey
  Encryption Tab
    Hash Algorithm: sha1
    Encryption Algorithm: Check: 3des, aes-128
    DH Group: Check: modp1024
IP > IPSec > Proposals
  Edit Default
  Auth Algorithms: Check: sha1
  Encryption Algorithms: CVheck: 3des, aes-128 cbc
  PFS Group: modp1024

Configure Firewall

IP > Firewall > Filter Rules
  New (+)
  VPN Rule
    Chain: input
    Protocol: 17 (udp)
    Dst. Port: 500,1701,4500
    Action: Accept
  Move rule higher up in the list (above any WAN block rules)
IP > Firewall > NAT
  New (+)
  Chain: srcnat
  Out. Interface: bridge (Your internal network bridge)
  Action: Masquerade


Configure Client Connection

There are an infinite number of devices that can be configured. I’m going to configure the most common — A Windows 10 L2TP VPN Client, built into the Operating System.


Start > Network and Sharing Center
Setup a new connection or network > Connect to a workplace (VPN)
No > Create a new connection

Use my internet connection (VPN)
Internet Address: Your Routers WAN IP (e.g. vpn.company.com, or static IP (e.g.
Destination Name: Your name for this connection
Remember my credentials: Checked

Go to Adapter Settings > Right-Click VPN Connection > Properties
Security > Type of VPN: L2TP/IPSec
Advanced Settings> Use Preshared Key for Authentication: Enter your Pre-Shared Key from the your L2TP IPsec Secret (under PPP > Interfaces > L2TP Server).
Allow these protocols: Check Only: Microsoft CHAP version 2

In Windows 10 - You have to manually re-enter the PSK and saved credentials in a separate menu....

Right-Click VPN Connection > Connect
Select in list > Advanced Option > Edit
VPN Type: L2TP/IPSec with Pre-Shared Key: Enter Pre-Shared Key
Type of Sign-in Info
Username (From PPP > Secrets)
Password (From PPP > Secrets)


You should now be connected to the internal LAN of your Mikrotik network. Attempt pinging devices by IP to confirm connectivity.


NETBIOS does not work through the VPN — but FQDNs do.

For example, server1 will not resolve.

Server1.domain.local will resolve

If you absolutely need to resolve by local name, create a WINS server, and assign its IP within the PPP Profile for the WINS Server field.


If you need help diagnosing your VPN connection:

System > Logging
New (+)
Create Three Topics: l2tp, ppp, and ipsec
Action: Memory

From here you will be able to see logs under "Log" and google your solution where something may need adjusting.