MikroTik - Guest Wifi with Limited Bandwidth

John Simpson <jms1@jms1.net> 2016-10-14

This documents how I was able to set up my MikroTik router with a "guest wifi" network, and then limit its total bandwidth to 1MBit, so that ifwhen the nosy neighbors' kids find it, they won't be tempted to abuse it.

Planning

Before you begin, you need to plan out a few details.

Firewall Rules

Before we do anything, we need to be sure that the new guest network won't be able to reach your normal internal network, and (to a lesser extent) vice-versa.

I actually have two separate internal networks - a "work" network which supports IPv6, and a "home" network which does not. I get my IPv6 addresses from a Hurricane Electric tunnel, which means that Netflix accuses me of using a proxy if IPv6 is involved... so the streaming boxes are on the "home" network, where they can't use IPv6.

These two networks "trust" each other, but the other non-external networks (the guest network we're setting up in this document, and another network which stays connected to a VPN at work) are not allowed to access the "trusted" networks, or vice-versa.

In my router, these are the rules which allow the "trusted" networks to talk to each other.

/interface list add name=trusted
/interface list member add list=trusted interface=internal
/interface list member add list=trusted interface=home

/ip firewall filter add \
    chain=forward \
    in-interface-list=trusted \
    out-interface-list=trusted \
    action=accept \
    comment="FORWARD: trusted networks may speak with each other"

This rule, which comes right AFTER the rule above, prevents any other non-external networks from sending traffic to any interface other than the external interface, which prevents them from talking to each other.

/ip firewall filter add \
    chain=forward \
    out-interface=!ether1 \
    action=reject \
    reject-with=icmp-network-unreachable \
    log=yes \
    comment="FORWARD: no traffic between non-trusted internal networks"

If you don't have separate "internal" networks which need to trust each other, then this last rule should be all you need.

Create Guest Wifi

Wireless Security Profile

The first step is to create a security profile, which sets the encryption type and password which will be used on the new network(s).

Note that WPA2 keys must be a minimum of eight characters long.

/interface wireless security-profiles
add name=GUEST \
    mode=dynamic-keys \
    authentication-types=wpa2-psk \
    wpa2-pre-shared-key="guest-password"

If you want your new network to not use encryption, and therefore not require a password, the command looks like this:

/interface wireless security-profiles
add name=GUEST \
    mode=none

Be careful if you do this.

Wireless Interface(s)

If you have a single-band router, make sure you know the name of your wifi interface. For a dual-band router, make sure you know which interface is 2.4 GHz and which one is 5 GHz.

/interface wireless print where !master-interface
Flags: X - disabled, R - running
 0  R name="wlan1" ... band=2ghz-b/g/n ...
 1  R name="wlan2" ... band=5ghz-a/n/ac ...

In this example, wlan1 is the 2.4 GHz interface, and wlan2 is the 5 GHz interface.

Create the new Wifi interface. If you have a dual-band router and want your guest SSID to exist on both bands, create an interface for each band. Note that the SSIDs should be different, in order to avoid confusion.

/interface wireless
add name=wlan24-guest \
    master-interface=wlan1 \
    ssid=GUEST-24 \
    security-profile=GUEST
add name=wlan5-guest \
    master-interface=wlan2 \
    ssid=GUEST-5 \
    security-profile=GUEST

Bridge Interface

Now that the wireless interfaces exist, we need to bridge them together so we can manage them as a single interface.

Note that if you have a single-band router, you don't really need a bridge, unless you want to be able to add an ethernet, VPN, or other interface as part of the guest network.

If you're not going to use a bridge, you can skip this step, and wherever you see the guest-bridge interface below (i.e. setting its IP address, setting up the DHCP server, etc.) you should use the name of the guest wifi interface (such as wlan24-guest) instead.

/interface bridge add name=guest-bridge

/interface bridge ports
add bridge=guest-bridge interface=wlan24-guest
add bridge=guest-bridge interface=wlan5-guest

IP Address

Now we can set the router's IP address for the guest network. (Again, if you're not using a bridge, you should use the name of the wireless interface here.)

/ip address
add interface=guest-bridge \
    address=192.168.0.1/24

DNS Server

The router is going to be acting as the DNS server for the guest network, so we should allow queries. The router's DNS server forwards any queries it receives to whatever DNS servers it was told to use by the DHCP server who assigned its external address, and caches those results (so that if the same name is queried multiple times, there's only one query to the "upstream" DNS servers.)

/ip dns set allow-remote-requests=yes

DHCP Server

People connecting to the guest network will need a DHCP server in order to get an IP address and other networking information. The router will provide this service.

First create a pool of IPs which may be assigned to guests. These must be within the guest network's IP space, and must not include the router's IP. (I generally use .100 through .199 within each network for this.)

/ip pool
add name=guest-pool 
    ranges=192.168.0.100-192.168.0.199

Next, set up the options which will be sent to DHCP clients connecting to the new network.

/ip dhcp-server network
add address=192.168.0.0/24 \
    gateway=192.168.0.1 \
    netmask=24 \
    dns-server=192.168.0.1

Finally, we can start the DHCP server for the guest network.

/ip dhcp-server add name=guest \
    interface=guest-bridge \
    address-pool=guest-pool \
    authoritative=yes

Test

At this point, you should be able to use a phone, tablet, laptop, or other device, and see the new Wifi network. You should be able to connect to the guest wifi, and be able to "get out" to the rest of the internet.

Limit the Bandwidth

With a "wide open" guest network, there's a pretty good chance that random people are going to connect to your network. One of the dangers is that "guests" will download or upload a bunch of large files, or stream a bunch of video, or otherwise use up so much bandwidth that it interferes with your use of your network.

One thing you can do to minimize the damage is to limit the speed of the traffic on the guest network. By choosing a limit which makes high-bandwidth usage inconvenient, but allows "normal" use (email, chat, typical web pages), you can make your guest network a less inviting target for random people to use.

Create the queue to limit traffic

RouterOS uses a queueing mechanism to impose limits on traffic. There are a few different ways it can do this, I'm going with the simplest option.

/queue simple add name=guest-queue \
    target=192.168.0.0/24 \
    max-limit=1M/1M

The limits are specified as two numbers, separated by a /. The first number is the upload limit (i.e. how much traffic the guest network can upload to the internet), and the second one is the download limit (i.e. how much the traffic the guest network can download from the internet.)

The numbers are "bits per second", and can be followed by k, M, or G as needed (i.e. 1M is the same as 1048576.)

Bypass fasttrack for guest traffic

Having the queue in place should be enough to work, however RouterOS has this thing called "fasttrack", which is a way to move packets from one interface to another as quickly as possible. It does this by making the routing engine bypass several steps, including the queueing mechanism.

This means that traffic which is fasttrack'ed cannot be controlled by the queueing mechanism.

The fasttrack mechanism is invoked by an /ip firewall filter rule with the clause action=fasttrack-connection. If a packet matches the conditions for a rule before this one, that rule's action will be followed. If the action is one which ends the firewall processing (i.e. accept, drop, reject, etc.) the fasttrack rule will never be reached, and the queueing mechanism will be able to slow down the traffic.

To work around this, we need to first identify the fasttrack-connection rule.

/ip firewall filter print
...
 7    chain=forward action=fasttrack-connection connection-state=established,related log=no log-prefix=""
...

Once you have the ID of the existing action=fasttrack-connection rule, the following commands will insert two new rules just before it, which explicitly accept traffic to and from the guest network before they can be fasttrack'ed, causing them to feed through the queueing mechanism.

Assuming the fasttrack rule's ID is 7...

/ip firewall filter
add place-before=7 copy-from=7 \
    src-address=192.168.0.0/24 \
    action=accept \
    comment="FORWARD: skip fasttrack for traffic from guest network"
add place-before=7 copy-from=7 \
    dst-address=192.168.0.0/24 \
    action=accept \
    comment="FORWARD: skip fasttrack for traffic to guest network"

Thanks

Thanks to mducharme and Whiskey` on the ##mikrotik Freenode IRC channel, for their advice and patience as I worked through this.