Jul 242016

Mikrotik WinBox - Fast connectionAs I wanted to have a separate wireless network for few of my IoT experiments and taking into consideration how secure IoT devices are (hint: not secure at all), I decided to go with a mini access point. Securing IoT gets much easier with a separate physical device.

Device had to be 2.4 GHz AP, allow for remote management, and cheap. One beautiful device matching all criteria was MikroTik mAP lite. Mikrotik devices are usually more of an European thing and, compared to other wireless devices, a bit harder to obtain in States. For example, I bought mine from ICD Group because Amazon didn’t carry any.

I haven’t used MikroTik for a while now but I remembered its WinBox interface fast enough. And I remembered how it saves its settings immediately thus punishing you for any error. It is definitely not the most friendly user interface nor I can call it excellent for beginners. But it is powerful enough to be worth learning.

Anyhow, with basic configuration done I wanted to limit upstream bandwidth toward my main router. From Queues menu I just added new queue, set Target to “ether1”, and assigned Max limit for both upload (256 kbit/s) and download (64 kbit/s). Short speed test later and I was confused. Speed wasn’t being restricted at all. And traffic figures were unreasonably low. Something weird was going on.

A bit of troubleshooting and I found the culprit. Once I changed in IP->Firewall the defcon entry from “fasttrack connection” to “accept”, my queue started limiting as it should.

Jul 182016

Josip Medved (2016)A month ago I went to visit some of the Washington state islands; San Juan, Whidbey, Fidalgo, and lot. As we don’t live in the immediate neighborhood and there are quite a few islands to visit, my family and I decided to book a hotel in Mt. Vernon. Best Western it is.

After a day full of boats and hiking we’ve finally arrived to hotel and were informed there is no water available. Frankly, the first idea at that moment was to cancel and go to another hotel. However, pleasant guy working the reception convinced us to stay – water is going to be available in 30 minutes. So we got our stuff to room regardless, went out for a diner, expecting to have shower after we are back. Yep, you’ve guessed it – no such luck.

But we were again assured water return was imminent. Few hours later we gave up on waiting and went for bed refreshed only by some wet towels my wife fortunately always carries. Yes, morning was water-less too with the same “almost there” statements. So we packed and went onto another day of hiking.

Once I got home and got a shower (finally), I’ve decided to tweet Best Western. And surprisingly got a reply pointing me toward e-mail to contact. And so I did.


It has been more than a month since and still there is no reply from Best Western. Not an apology, not an additional question, not saying I’m expecting too much. Absolutely nothing. Full silence.

And frankly that pisses me off. If they didn’t reply to my tweet, I would be ok with it – just another complaint lost in the sea. What they did was masterpiece: they publicly replied to tweet and then just “forgot” to follow up. They made an impression of solving their customer’s issue while doing no work at all. Even better, if somebody calls them on that, they can claim its other department’s fault. Public relations dream – keep appearance of being active while not fixing anything at all. :)

All said, not much changes for me. I wanted to get the story out and I did. I don’t intend to ask Best Western for anything nor will I accept anything. I don’t even want a refund – what’s payed is payed. I am even going to stay in Best Western again – this was the first major issue after staying in quite a few of them over the years. Hell, I still remember one in Vienna as my second home.

Maybe the only thing that will change is me treating words “we’re going to have it fixed in 30 minutes” as a signal to get away as fast as possible.

Jul 122016

My home network pretty much revolves around Asus RT-AC56U with Asuswrt-Merlin firmware. Nice, stable, and full of features. One feature I absolutely love is multiple isolated guests networks. And I do not use it only for guests.

While my computers are all in main network, all my devices (Chromcast, printer, IoT, …) are in guest network without any intranet access. They can get on Internet but they cannot access my internal network. Considering all is done on the same router, it is not ideal, but it does increase security considerably.

Initially one device presented some trouble. You see, to cast YouTube from my computer I had to have it in my main network. But I didn’t want to. I wanted it to be in isolated guest LAN together with all other devices. But I did want to access it from my internal network. Since the whole network isolation for guest networks is done via firewall rules, that meant it was time for some hole poking.

Prerequisite is to have Asus JFFS enabled. This will enable saving scripts so they can be executed upon startup. Yes, you can do it manually every boot but that gets old quite quickly. For the actual firewall setup, the only thing needed is MAC address of Chromecast device and we can make it an exception to the rule. I prefer to do it via script:

echo "#!/bin/sh" > /jffs/scripts/firewall-start
echo "ebtables -I FORWARD -p ARP -o ! eth0 -j ACCEPT" >> /jffs/scripts/firewall-start
echo "ebtables -I FORWARD -s A4:77:33:33:48:85 -o ! eth0 -j ACCEPT" >> /jffs/scripts/firewall-start
echo "ebtables -I FORWARD -d A4:77:33:33:48:85 -i ! eth0 -j ACCEPT" >> /jffs/scripts/firewall-start
echo "logger Poked hole for Chromecast" >> /jffs/scripts/firewall-start
chmod a+x /jffs/scripts/firewall-start

First rule pokes a hole through isolation in order to allow for ARP requests. Second two rules allow everything coming from and to specific MAC address. Everything else is a bit of plumbing making script run on router’s startup.

Of course, this works not only for Chromecast. Exactly the same approach works nicely for any wireless printer – I used Brother MFC-J475DW without any problems.

To make this a bit more secure, one might want to restrict this only to interface where device is actually located. Every router firmware might do things a bit differently but guest networks on mine were setup in a reasonable fashion. They all followed formal wlX.Y where X was 0 for 2.4 GHz guest networks and 1 for 5 GHz. Y was number between 1 and 3 directly corresponding to guest network index.

Since my Chromecast device was first guest network in 5 GHz range, its designation was wl1.1 and thus hole could be made a bit smaller:

echo "#!/bin/sh" > /jffs/scripts/firewall-start
echo "ebtables -I FORWARD -p ARP -i ! eth0 -o wl1.1 -j ACCEPT" >> /jffs/scripts/firewall-start
echo "ebtables -I FORWARD -s A4:77:33:33:48:85 -i wl1.1 -o ! eth0 -j ACCEPT" >> /jffs/scripts/firewall-start
echo "ebtables -I FORWARD -d A4:77:33:33:48:85 -i ! eth0 -o wl1.1 -j ACCEPT" >> /jffs/scripts/firewall-start
echo "logger Poked hole for Chromecast" >> /jffs/scripts/firewall-start
chmod a+x /jffs/scripts/firewall-start

To make these firewall rules even stricter, one can also restrict ARP to allow only certain IPs but I will leave this as an exercise for some other time.

PS: Using pretty much the same basic procedure one can get any device accessible to other isolated guest networks. This is not only nice for Chromecast but really useful for getting printer working too.

Jul 062016

Ages ago, back when I created my first dynamic ASP web pages, they had an ever changing tagline. Some taglines were funny, some were sad, some were crazy, but I enjoyed them as homage to the, now forgotten, BBS era. As I moved from one hand-built platform to another, I kept this feature alive.

I started blogging much later on the Google’s Blogspot and it wasn’t possible to get dynamic taglines there. Later, when I moved the whole blog to WordPress and merged it with my original pages, end result was more of a blog. And thus taglines were no more. They were relegated to manually changing Skype status to entertain a friend or two. Until now.

My goal was to create the simplest and reasonably performant way of selecting a random tagline from flat text file.

One approach fitting with WordPress would be to create plugin but I opted not to. Since I really wanted to change tagline once a day, plugin would be probably a bit of overkill. Instead I opted to (ab)use fact WordPress already has tagline-like field called Blog description and all we need to do is change it to text of our choice.

Of course, before we even come to that step, we have to extract tagline from file. Fortunately Linux offers shuf utility to randomly select one line of many. All needed is to give it a plain text file. Of course, we should escape all single quotes to avoid any SQL issues. If we (hopefully correctly) assume text file with taglines is under your control, simple escaping is sufficient:

TAGLINE=`shuf -n 1 ~/taglines.txt | sed "s/'/''/g"`

With tagline in hand we can go and change blog description directly:

mysql --execute="UPDATE wp_options SET option_value='$TAGLINE' WHERE option_name='blogdescription';"

While this will change description, if you use caching plugin, it won’t be enough. You also need to clean cache. The easiest approach is to simply delete cache folder. As we do it only once per day, this won’t be too much of a hit. Different caches might use different locations, but for W3 Total Cache I use here, following is enough:

rm -R ~/www/wp-content/cache

All left to do is getting this script to be executed daily by either using web interface of your web provider or setting it up in crontab manually.

PS: Instead of using shuf, you can use sort -R ~/taglines.txt | head -1.

PPS: Full script I use is here:


MYSQL_USER=WordPress MySQL user
MYSQL_PASSWORD=WordPress MySQL password
MYSQL_HOST=WordPress MySQL host
MYSQL_DATABASE=WordPress MySQL database

TAGLINE=`shuf -n 1 ~/taglines.txt | sed "s/'/''/g"`

mysql --host=$MYSQL_HOST --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE --execute="UPDATE wp_options SET option_value='$TAGLINE' WHERE option_name='blogdescription';"

rm -R ~/www/wp-content/cache 2> /dev/null