In my new apartment I luckily have a fibre (FTTH) which terminates in the living room. My first excitement was curbed when I investigated about the technology in use. The ISP uses a technique called GPON which is probably smart from a economical point of view but also enables some possible (sniffing) attacks. Additionally the provider seems to do some filtering which is not just DNS blocking. Long story short I decided to route all traffic through a VPN and so I began to config a Mikrotik hex POE router to use a Njal.la Wireguard VPN.

Configuring the router

This is the first time I actually use Mirotik router in non default config so it took quite a while for me to figure out how everything fits together. The requirements are:

  • DHCP Client on Uplink port
  • working Wireguard tunnel
  • default route through the wireguard tunnel
  • forbid traffic to go directly to the uplink (eg. on Wireguard connection loss)
  • DHCP server on all other interfaces
  • working DNS resolver on the router
  • working IPv6

DHCP Client + LAN Bridge

First we setup a standard behaviour: use the ether1 port for uplink as DHCP client and bridge the remaining interfaces together.

/interface list member
add comment=uplink interface=ether1 list=WAN
/ip dhcp-client
add add-default-route=no comment=uplink interface=ether1 use-peer-dns=no \
    use-peer-ntp=no

/interface bridge
add admin-mac=AA:BB:CC:DD:EE:FF auto-mac=no comment=local-bridge name=bridge \
    protocol-mode=none
/interface bridge port
add bridge=bridge comment=defconf interface=ether2
add bridge=bridge comment=defconf interface=ether3
add bridge=bridge comment=defconf interface=ether4
add bridge=bridge comment=defconf interface=ether5
add bridge=bridge comment=defconf interface=sfp1

Be aware, that we do not want to automatically set a default route to the gateway of the uplink network add-default-route=no since we want all traffic go through the VPN at all times.

DHCPv4 Server

DHCPv4 is also a very common configuration which, I think, does not need further explanation. The hex POE router has DHCPv4 on its LAN bridge by default enabled. Anyway here is a configuration example with one static lease:

/ip pool
add name=domainmess-home-dhcp-range ranges=192.168.0.100-192.168.0.200
/ip dhcp-server
add address-pool=domainmess-home-dhcp-range authoritative=yes disabled=no interface=bridge \
    lease-script="" lease-time=10m name=domainmess-home-dhcp-server use-radius=no
/ip dhcp-server lease
add address=192.168.0.200 client-id=\
    aa:bb:cc:ee:ff:aa:bb:cc:ee:f:faa:bb:cc:ee:ff:aa:bb:cc:ee:ff mac-address=\
    AA:BB:CC:DD:EE:FF server=domainmess-home-dhcp-server

DHCPv6 Server

DHCPv6 isn’t really the right term as the Mikrotik RouterOS does prefix delegation. That means it announces a prefix which the client can get and might use for further delegation or address selection. I use it to assign a /64 network to each client which then will configure automatically one address from that.

/ipv6 pool
add name=domainmess-home-ipv6-ula prefix=fc00:99ff:4400::/32 prefix-length=64
/ipv6 dhcp-server
add address-pool=domainmess-home-ipv6-ula dhcp-option="" disabled=no interface=bridge lease-time=3d \
    name=domainmess-home-dhcpv6-pd preference=255 rapid-commit=yes route-distance=1 \
    use-radius=no

Wireguard

Wireguard is new in RouterOS 7 and is integrated quite well into the Mikrotik config. We define a interface of the type „Wireguard” and at least on Peer to which we want to connect to. In our case that is the Njalla VPN server. The other settings come from the Njalla config, but the important one is that we set 0.0.0.0/0 and ::/0 in the AllowedIPs so that we can route all internet traffic through it and not just a specific subnet.

# keys are just examples
/interface wireguard
add disabled=no listen-port=13231 mtu=1280 name=njalla01 private-key=\
    "gDV016J81d9dWkkw7j9MjDcnmt0HhQHnsG7favtiJU8="

/interface wireguard peers
add allowed-address=0.0.0.0/0,::/0 disabled=no endpoint-address=\
    wg235.njalla.no endpoint-port=51820 interface=njalla01 \
    persistent-keepalive=25s public-key=\
    "YAV6HyThvZgLTYD6nDIeMeUNKgwnp6jnLdiYYNb9Bnc="

Hint: Using a hostname instead of an IP as EndPoint is supported since RouterOS 7.6

Routes + DNS

Now Wireguard isn’t able to connect to its remote, since there is no working Routing+DNS. Setting DNS servers is trivial but we need also to route all encrypted Wireguard traffic to the Njalla network via our uplink port. Same goes for at least one DNS server so that Wireguard can lookup its remote.

Be aware: This will make at least some your DNS request bypass the VPN and be victim to censorship or monitoring. To prevent that, use a static IP as Wireguard remote!

As a default gateway we then set the Wireguard Interface instead of a IP address. That is possible since Wireguard is an IP protocol (Layer 3) and creates a TUN device which has no need for a Ethernet header with a gateway MAC address inside it. The traffic must be routed anyway on the other side of the tunnel (on the Njalla routers) and we therefore can just send IP packets into it.

# route to njalla network via uplink
/ip route
    add disabled=no distance=1 dst-address=198.167.192.0/19 gateway=[/ip dhcp-client get [find interface=ether1] gateway]
    pref-src="" routing-table=main suppress-hw-offload=no
# default route via njalla VPN
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=njalla01 pref-src="" \
    routing-table=main suppress-hw-offload=no
# DNS bypass
add disabled=no distance=1 dst-address=9.9.9.9/32 gateway=192.168.1.254 \
    pref-src="" routing-table=main suppress-hw-offload=no

IPv4 NAT

Like on more or less every home route IPv4 source NAT is used to use the IPv4 VPN address for all outgoing traffic. This is also part of the default conf of many Mikrotik router.

/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface-list=WAN

IPv6 NAT

This is definitely the most ugly part. Since Njalla only gives one IPv6 address per VPN connection we have to setup a IPv6 source NAT (yes, that is possible, didn’t believe that either…)

/ipv6 firewall nat
add action=masquerade chain=srcnat ipsec-policy=out,none out-interface=\
    njalla01

Works as designed and is better than no IPv6 at all!

configuring the clients

To use the IPv6 prefix delegation we configured before in the DHCPv6 Server section, we must also ensure that the client is asking for it. For systemd-networkd this is done by adding the following lines to the interface configuration:

[Network]
DHCP=yes
DHCPPrefixDelegation=yes

Additional learnings

During the whole configuration I learned some related stuff which came in quite handy for using and debugging Mikrotik Routers.

Find IPv6 hosts in network

To find IPv6 hosts in the local network one doesn’t need to nmap but one can use multicast packets on which specific hosts will answer. For example to find all routers you can just ping

$ ping -6 ff02::2%wlan0

This way you can find a router even if no DHCP is working in your LAN or if the router has no static IP due to some configuration errors.

Of course you can also use the Link-Local address to access your router. Well at least you can if you don’t want to use the Webinterface because I couldn’t find any browser that properly supports using Link-Local addresses. That is not a new phenomenon and is otherwise documented. However accessing the router via SSH via it’s link local address even works if’s been rebooted with completely network config.