Filter traffic from and to Tor IP addresses automatically with Mikrotik RouterOS

November 30, 2014

Some newer malware communicates with their command and control servers via the Tor network, in a typical enterprise network no system should connect the Tor network. A other scenario is that you’re providing services which don’t need to be accessed via the Tor network but your servers get attacked from Tor Exit Nodes. In both cases it may be a good defence to filter/log/redirect the traffic on your router. With Mikrotiks RouterOS this is possible. You need also a small Linux/Unix server to help. This server needs to be trustworthy one as the router executes a script this server generates. This is required as RouterOS is only able to parse text files up to 4096 by itself, and the Tor IP address list is longer.

Linux Part

So first we create the script /usr/local/sbin/ on the Linux server with following content:
# the full path of the file we create

# remove the comment  if you want to use the List of All Current Tor Server IP Addresses
# remove the comment  if you want to use the List of All Current Tor Server Exit Node IP Addresses

echo "# This scrip adds Tor IP addresses to an address-list (list created: $(date))" > $filename
echo "/ip firewall address-list" >> $filename

/usr/bin/wget -q -O - $url | sort -u | /bin/awk --posix '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ { print "add list=addressListTor dynamic=yes address="$1" " ;}' >> $filename

The filename path works on CentOS, on Ubuntu you need to remove the html directory. Now make the file executable

chmod 755 /usr/local/sbin/

and execute it


No output is good. Make sure that the file is reachable via HTTP  (e.g. install httpd on CentOS) from the router. If everything works make sure that the script is called once a day to update the list. e.g. place a symlink in /etc/cron.daily:

ln -s /usr/local/sbin/ /etc/cron.daily/

Mikrotik part

Copy and pasted following to get the script onto the router:

/system script
add name=scriptUpdateTorIPs policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive source="# Script which will download a script which adds the Tor IP addresses to an address-list\
\n# Using a script to add this is required as RouterOS can only parse 4096 byte files, and the list is longer\
\n# Written by Robert Penz <[email protected]> \
\n# Released under GPL version 3\
\n# get the \"add script\"\
\n/tool fetch url=\"\" mode=http\
\n:log info \"Downloaded addTorIPs.rsc\"\
\n# remove the old entries\
\n/ip firewall address-list remove [/ip firewall address-list find list=addressListTor]\
\n# import the new entries\
\n/import file-name=addTorIPs.rsc\
\n:log info \"Removed old IP addresses and added new ones\"\

To make the first try run use following command

/system script run scriptUpdateTorIPs

if you didn’t get an error

/ip firewall address-list print

should show many entries. Now you only need to run the script once a day which following command does:

/system scheduler add interval=1d name=schedulerUpdateTorIPs on-event=scriptUpdateTorIPs start-date=nov/30/2014 start-time=00:05:00

You can use this address list now in various ways .. the simplest is following

/ip firewall filter
add chain=forward comment="just the answer packets --> pass" connection-state=established
add chain=forward comment="just the answer packets --> pass" connection-state=related
add action=reject chain=forward comment="no internal system is allowed to connect to Tor IP addresses" dst-address-list=addressListTor
add chain=forward comment="everything from internal is ok --> pass" in-interface=InternalInterface

Google services seems to be down if you’re accessing them via an IPv6 tunnel provider [Update 2]

November 8, 2014

For one of my Internet connections I use Hurricane Electric as IPv6 tunnel broker and the Google services (also Youtube) seems to be not accessable over it. I searched through the Internet and it seems that this is a more wide spread problem also with other tunnel brokers and other users. It is also interesting that following works.

first the dns request:
$ host has address has address has address has address has address has address has address has address has IPv6 address 2a00:1450:4014:80b::1013

the ping to the IPv6 address works too:
$ ping6 2a00:1450:4014:80b::1013
PING 2a00:1450:4014:80b::1013(2a00:1450:4014:80b::1013) 56 data bytes
64 bytes from 2a00:1450:4014:80b::1013: icmp_seq=1 ttl=57 time=82.5 ms
64 bytes from 2a00:1450:4014:80b::1013: icmp_seq=2 ttl=57 time=93.3 ms
64 bytes from 2a00:1450:4014:80b::1013: icmp_seq=3 ttl=57 time=68.3 ms
64 bytes from 2a00:1450:4014:80b::1013: icmp_seq=4 ttl=57 time=75.5 ms

but a HTTP request runs into a timeout:
$ wget
--2014-11-08 11:42:29--
Resolving ( 2a00:1450:4014:80b::1013,,, ...
Connecting to (|2a00:1450:4014:80b::1013|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: [following]
--2014-11-08 11:42:29--
Resolving ( 2a00:1450:4014:80b::1017,,, ...
Connecting to (|2a00:1450:4014:80b::1017|:80... connected.
HTTP request sent, awaiting response...

after the initial redirect … so small packets seem to go through but big not .. that looks like an MTU problem.

ps: yes
$ ping6 2a00:1450:4014:80b::1017
PING 2a00:1450:4014:80b::1017(2a00:1450:4014:80b::1017) 56 data bytes
64 bytes from 2a00:1450:4014:80b::1017: icmp_seq=1 ttl=57 time=100 ms
64 bytes from 2a00:1450:4014:80b::1017: icmp_seq=2 ttl=57 time=63.6 ms

works too. ;-)


Take also a look at following links:


Update 2:

The PMTUD seems to be not working .. Details on PMTUD und MTU and MSS can be found here.  Workaround seems to be to set the MTU size to 1480 – it works for me and in IPv6 that’s MSS 1420 (60byte instead of 40 in IPv4). On a Mikrotik RouterOs it works like this:

/ipv6 firewall mangle add action=change-mss chain=forward new-mss=1420 protocol=tcp tcp-flags=syn tcp-mss=!0-1420 comment="max MTU size in Tunnel 1480 .. workaround for google bug"

On Linux it is similar with iptables:
ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1420

Mikrotik changed the update policy in their license agreement

October 13, 2014

Just as information for you guys using Mikrotik’s RouterOS but who don’t monitor the wiki for changes or are regular readers of the forum. Mikrotik changed its license concerning the updates. Before this summer following paragraph was on their license wiki page:


You can take a look at the full old version here. Anyway this whole paragraph has been removed. Also with RouterOS 6.20 the following got removed when typing /system license print on the router:


So what does that mean now? jarda from the forums put it nicely:

Updates and upgrades will be unlimited till the end of the life of each device type. It means until the new versions will support your hardware, you can upgrade for free. But expect the problems like some mipsbe devices with 32MB ram are sometimes poorly running RouterOS 6.x. And old 1xx devices are not supported by 6.x. So actually moving upgradable-to field forward or keeping support to old hw in new versions is one like other. No certainty anyway.

My first IPv6 problem – multihoming my home network without NAT

August 10, 2014

Today I ran into my first IPv6 problem … all was easy so far for some years .. just configured it and it worked … but this weekend I deployed a second Internet connection for my home. With IPv4 and masquerading the internal IP addresses to the one provider-given IP addresses I was able on the router to configure which traffic goes out over which provider. If one provider fails the route is withdrawn and all goes over the other link. But now comes IPv6 and it is not that easy anymore, as my router does not support IPv6 NAT. The problem is described in detail in this nice blog post by Ivan Pepelnjak.

My router is able to do VRF (Virtual Routing and Forwarding) also for IPv6 (at least the documentation says so .. didn’t try it so far). So the “best” option for me seems to advertise both subnets the providers gave me to the clients  and route source based to the providers. Without VRF I would be depended that the providers don’t do a RPF (Reverse Path Forwarding) check, which is also not a good idea. But this leads to the problem that the end device decides which uplink it uses, which is most likely not the one I would choose ….

An other idea was to use one of my servers in a data center to tunnel the traffic through. Basically running two IP tunnels from my router to the server (one via each provider) and using IP addresses that are routed from the Internet to the server. But this is also not a good solution.

Anyway I don’t have good solution so far, maybe one of my readers does.


Slow DNS resolving with Linux systems against Windows DNS server

August 1, 2014

In the last days I encountered a problem with the DNS resolution by our Linux systems – must be there for a long time but it took a deep look into a different performance problem to get this one figured out. I did a simple wget to a HTTP site in the same data center and it took sometimes 5 seconds to get DNS name resolved to an IP address. As a network guy I launched tcpdump at once and did see following packets:

10:59:19.264987 IP LinuxClient.51463 > WindowsDnsServer.domain: 57223+ A? (35)
10:59:19.265056 IP LinuxClient.51463 > WindowsDnsServer.domain: 26702+ AAAA? (35)
10:59:19.265700 IP WindowsDnsServer.domain > LinuxClient.51463: 26702* 0/1/0 (103)

10:59:24.269981 IP LinuxClient.51463 > WindowsDnsServer.domain: 57223+ A? (35)
10:59:24.270303 IP WindowsDnsServer.domain > LinuxClient.51463: 57223* 1/0/0 A (51)
10:59:24.270370 IP LinuxClient.51463 > WindowsDnsServer.domain: 26702+ AAAA? (35)
10:59:24.270557 IP WindowsDnsServer.domain > LinuxClient.51463: 26702* 0/1/0 (103)

As you see the first A query gets not answered but the AAAA does. I changed to an other DNS server (first Windows 2008 R2 and the second Windows 2012 R2)  but with the same results. I did tests with RHEL6/Centos6 and Ubuntu 14.04 .. no difference. As a next step I talked with the Windows guys to look at the Windows 2012 R2 DNS server. They did a packet capture and saw that the Windows server did not send that packet, but a DNS Debug log showed that the DNS server it self did answer it. I than called wget with the “–inet4-only” option, which made sure that only a A query was sent and I was not able to reproduce the problem. So it must be something with the second packet.

Getting a tip from a fellow network admin who said I should look at the source port of the packets I did so. The UDP source ports of the A and AAAA were the same and it looked like that the Linux system gets an answer if the A query is answered before the AAAA arrives on the Windows Server. The next step was to look for a way to change that behavior on the Linux side, which looked to me easier than to change something on the Windows site. ;-)

Following resolv.conf option looked promising:

single-request-reopen (since glibc 2.9)
The resolver uses the same socket for the A and AAAA requests. Some hardware mistakenly sends back only one reply. When that happens the client system will sit and wait for the second reply. Turning this option on changes this behavior so
that if two requests from the same port are not handled correctly it will close the socket and open a new one before sending the second request.

And yes – that was the solution. On every system I added

options single-request-reopen

to the /etc/resolv.conf the problem went away. For systems which generate the resolv.conf automatically (like Ubuntu 14.04), which you can check by

ll /etc/resolv.conf
lrwxrwxrwx 1 root root 29 Mai 26 12:35 /etc/resolv.conf -> ../run/resolvconf/resolv.conf

you should add the line to /etc/resolvconf/resolv.conf.d/base instead and call sudo resolvconf -u afterwards.

All together this problem took me many hours to find and I didn’t find anything on the net .. so I thought a post may help other poor admins. ;-)

Access Mikrotik Router OS via SSH Public Key authentication

July 12, 2014

Sometimes you need to execute various commands on a Mikrotik automatically from a Server. Surely it is possible to store the password in the script, but there is a better way – it is called Public Key authentication for SSH. Basically a pair of files is generated and the public one is copied to the Mikrotik and the private key stays on the PC. If you encrypt this key on the PC (which is useful if not a script does use  it but a person) you get a 2-factor authentication. An attacker needs that private file and the password to decrypt it to administer the router. There are two types supported by SSH RSA and DSA. RSA is more commonly used but Mikrotik does only support DSA so we need to create a DSA key pair.

The first step is to generate the key pair as the user on the Linux system which is than used to access it. If it is a script it maybe a separate user just for this purpose is a good idea.

$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/<user>/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_dsa.
Your public key has been saved in
The key fingerprint is:

If you just press enter on the file question, the default one will be used. If you want to use some separate directory that’s fine, you just need to provide the location later at the ssh call. If you press just enter for the passphrase the private key will not be encrypted. Now we copy the public key (.pub extension) to the Mikrotik:

scp /home/<user>/.ssh/ [email protected]:

And after that we need to import the key. If we choose the user admin, which we use our self to login, no password login will be possible anymore for that user. So if you don’t like that you should create a special user for the script. As my script needs only to read stuff I’m okay with the group “read” and create a user like this:

/user add name=scriptUser group=read comment="user for our readonly scripts" disabled=no

Now we import that public key to the scriptUser with following command:

/user ssh-keys import user=scriptUser

We’re done .. just testing is open …. if you used not the default directory to store the key files you need to provide them via the -i parameter, if its the default location you don’t need to provide it. This command logs into the router and gets you some basic data without entering a password.

$ ssh -i <pathTo/id_dsa> “/system resource print”

You should also try to login as this user without the key file (e.g. from an other computer) and it should not be possible.

How to configure SNMPv3 securely on Extreme Networks XOS

July 11, 2014

In two of the last posts I wrote about configuring SNMPv3 securely for Linux and Mikrotik RouterOS. This time I’ll show the configuration for Extreme Networks XOS. Its quite easy and supports more encryption algorithm and options than e.g. Mikrotiks RouterOS. To allow SNMPv3 access we only need these commands – as I use SNMP only for reading, I’ll create a readonly user:

config snmpv3 add user snmpv3ro authentication sha XXXXXXXXXX privacy aes XXXXXXXXXX
config snmpv3 add group snmpv3group user snmpv3ro sec-model usm
configure snmpv3 add access snmpv3group sec-model usm sec-level priv read-view defaultAdminView write-view None notify-view None

If we want to disable a previously configured SNMPv1 or v2c access type following:

disable snmp access snmp-v1v2c

If you want also SNMPv3 traps you need this command:

configure snmpv3 add target-addr snmpv3Target param snmpv3Params ipaddress transport-port 162 tag-list defaultNotify

Hint: You can/should also add from or vr entries depending on your switch config

Some addition ways so secure your SNMP:

  1. You can specify in which virtual router instance the SNMP is reachable with following commands:
    disable snmp access vr all
    enable snmp access vr vrMgmt

  2. And you can also configure ACLs which defines from which IP addresses it is possible to access the SNMP service with following command:configure snmp access-profile snmpACL readwrite

    You need to create following file first with vi snmpACL.pol:

    entry allow_subnet_1 {
    if match all {
    source-address 10.x.x.0/24;
    then {
    entry allow_subnet_2 {
    if match all {
    source-address 10.y.y.0/24;
    then {

Android Devices send many Multicast Packets per Second for Chromecast – How to disable it?

June 28, 2014

While tracing/sniffing for something, I mirrored all packets of my mobile phone to Wireshark and I was was really astonished  to see many multicast DNS requests (_googlecast._tcp.local) from my mobile …


As you see, these are more than 15 packets per second, which leaded at once to following 3 thoughts:

  • That can’t be good for the battery
  • The mobile is sending this surely not only in my home network but also in hotspot networks … I don’t like that for security/privacy reasons (specially what happens if the phone gets an answer and maybe sends more info about itself)
  • I’m not using Chromecast anywhere

Which leaded at once to the question:

  • How can I disable this?

So I went on a search trough the Internet …. but I was not able to find a solution. So the question to the community .. has someone an idea how I can disable that?

ps: I found only one guy asking the same question in the xda developers forum


Howto filter “No VR found on VLAN xxx with VR Id xxx” on Extreme XOS switches

May 25, 2014

If your Extreme Networks switches are using VRRP and other devices are using it also in the same VLAN, the Exterme XOS switches will complain loudly about that … one log line per broadcast. In my case it were two per second and as the switch stores only 1000 log lines .. the log soon contained only these entries:

05/22/2014 17:29:41.11 Slot-1: No VR found on VLAN xxx with VR Id xxx
05/22/2014 17:29:40.48 Slot-2: No VR found on VLAN xxx with VR Id xxx
05/22/2014 17:29:40.11 Slot-1: No VR found on VLAN xxx with VR Id xxx
05/22/2014 17:29:39.48 Slot-2: No VR found on VLAN xxx with VR Id xxx
05/22/2014 17:29:39.11 Slot-1: No VR found on VLAN xxx with VR Id xxx

The one pitfall with using the exclude match string variable is that the VRIDs must not be treated as string variable. This does not work because Extreme XOS does not treat the VRID as a string variable, but rather as a integer. To determine the valid variables available for the specific event you’ll need to type following:

Slot-1 xxxxxxx.1 # show log events "VRRP.UnkVR" details
Component   SubComponent Condition               Severity      Parameters
----------- ------------ ----------------------- ------------- ----------
VRRP                     UnkVR                   Warning        2 Total
0 - string
1 - number (32-bit unsigned int)
No VR found on VLAN %0% with VR Id %1%

This tells us that to filter on the VRRP.UnkVR messages, there is a string variable (%0%) equal to the VLAN name, and a integer (%1%) equal to the VRID itself. Because Extreme XOS interprets the VRID itself as a number and not a string, doing an exclude match string will not work. You must use the number variable as follows:

configure log filter "DefaultFilter" add exclude events "VRRP.UnkVR" match number xxx

From the Concept Guide:

The filter can be associated with one or more targets using the command to control the messages sent to those targets. The system has one built-in filter named DefaultFilter, which itself may be customized. Therefore, the if a filter other than DefaultFilter is desired. As its name implies, DefaultFilter initially contains the default level of logging in which every Extreme XOS component and subcomponent has a pre-assigned severity level.

PS: You can use this solution to filter out any other event, just check with show log events "xxxx" details

Why doesn’t the Ubiquiti Unifi DNS based controller location function work with Mikrotik RouterOS DNS? [Update]

May 18, 2014

Last week I ran into a problem with my Unifi UAPs after I switched the central router to Mikrotik RouterOS and also used the DNS server of the RouterOS. If the Unifi UAPs are in the same subnet as the controller, the UAPs find it via a broadcast but if there is no layer 2 connection they need a special DHCP Option or the DNS name unifi.xxxxx (xxx in this case is the domain name specified via DHCP) needs to resolve to the IP address of the controller. My setup was using the DNS variant but after I switched to the Mikrotik DNS server the UAPs stopped to connecting to the controller. I logged into the one of them via SSH and saw following in /var/log/messages.

ace_reporter.reporter_fail(): Unable to resolve (http://unifi:8080/inform)

I did at once a ping unifi, which worked so I started to sniff the traffic and saw following:


The DNS resolution is working at first glance but it seems to be funny that the requests are always different, as the case changes all the time.  So I did a closer look into a requesting packet and the corresponding answer packet. The request looks this way:



And the answer looks this way:



The DNS server is lower casing the answers. This seams to break it. So I searched more into the topic why the Unifi UAPs are using the case randomizing in the first place and where the blame lies for this not working. Unifi UAPs started to use randomize-case in the DNS lookup with Version 2.4.6 (the current stable version) as a security feature, which is named dns0x20 and described in this RFC draft (called Use of Bit 0x20 in DNS Labels to Improve Transaction Identity). From the abstract:

The small (16-bit) size of the DNS transaction ID has made it a frequent target for forgery, with the unhappy result of many cache pollution vulnerabilities demonstrated throughout Internet history. Even with perfectly and unpredictably random transaction ID’s, random and birthday attacks are still theoretically feasible. This document describes a method by which an initiator can improve transaction identity using the 0x20 bit in DNS labels.

The RFC draft states that further:

In practice, all question sections in responses are exact copies of question sections from requests, even if the zone data and answer section owner names differ in their uppercase/lowercase attributes from the question section. So while it is theoretically possible for a request’s question section to contain the name “” and a response’s question section to contain the name “WWW.IETF.ORG”, this has not been observed, and might not even work reliably.

I guess we found one DNS server, which handles that differently. So Unifi UAPs are using a draft version of a RFC to make it more secure and Mikrotik RouterOS is one of the few it does not work with. It works with the Linux standard DNS server bind. So who to blame? its not that easy. Anyway I made a feature request to Mikrotik because returning the correct query does not break anything and more security with DNS is always good idea.

ps: I switched to the DHCP option for getting the UAPs to work with the RouterOS DNS.


Just got following back from the Mikrotik support:

that will be possible in RouterOS v7
Janis Krumins

Powered by WordPress
Entries and comments feeds. Valid XHTML and CSS. 76 queries. 0.271 seconds.