kls0e grüess Dich.

add AirPrint to a Brother MFC-7360N

With all the recent corona changes, we are in need of a home printer. Of course, b/w laser is the way to go, cheap inkjet printers are a scam and tend to break right after the warranty period. So I decided to buy a 4-in-1 Brother MFP, the MFC-7360N. It can print, scan, copy and fax and I got it from eBay kleinanzeigen for 20.- € with an empty toner cartridge.

I am really happy with this machine and can recommend it to anyone, 3rd party toners are very affordable (around 12.- €) and last for thousands of pages.

I also like to print scanned developed analog b/w photos with it as they look like photocopies, but that is a matter of taste I guess.

So the machine works well and performs great, and there is an iOS app for it which allows you to scan to your phone. You can also print with this app but I was looking for AirPrint support to integrate directly with iOS devices on the same network. The printer does not feature this relatively new protocol but if you have a linux machine on the network, maybe a raspberry pi, install CUPS properly and use the brlaser v4 ppd with it by Peter De Wachter, thanks! Presto, there’s your AirPrint, works like a charm.

Another reason I recommend Brother is that there is an undocumented “toner empty”-reset command which will just let you print along until the toner is physically used up:

1. Schalten Sie Ihr Brother MFC Gerät an
2. Öffnen Sie die Frontklappe -lassen Sie den Toner im Drucker
3. Drücken Sie die Taste STORNO 1x -nur einmal
4. Es erscheint die Anzeige "Trommel ersetzen?" 1. JA 2. NEIN -hier nichts auswählen, weiter mit
5. Drücken Sie die STERN-Taste *
6. Drücken Sie die Taste 0 zweimal nacheinander
7. Schließen Sie die Frontklappe
8. fertig

found in a german video review by VideoP, thanks.

So it turns out that the toner cartridge I got with the printer is far from empty and the Brother continues to print just fine :)

Dynamically adjusting bandwidth limits

Full quote by Perry:

“I got a request from a refugee center to set up qos so that in the evenings and on weekends the bandwidth-limit gets raised from 35Mbit to 45Mbit, and back down to 35Mbit Mon-Fri 7:00 to 20:00. To do this, I did the following. It’s a hack, which could be improved (like storing up slow speed and fast speed in a config file somewhere).

So this is what I did…. I wrote the following script (/root/qos-schedule.sh)


. /lib/functions.sh



#check to see if it's the weekend
if [[ $(date +%u) -gt 5 ]]; then
  # check to see if it's not between 7:00 and 20:00
  if [[ $(date +%H) -lt 7 ]] || [[ $(date +%H) -ge 20 ]]; then

#compare the speed to the current settings.
OLDSPEED=$(uci get qos.ffuplink.download)
if [[ $OLDSPEED -ne $SPEED ]]; then
  logger -t qos-schedule.sh "setting time-based qos to $SPEED"
  uci set qos.ffuplink.download=$SPEED
  uci commit qos
  /etc/init.d/qos reload

I added it to crontab to run every hour

Additionally I added the script to /etc/rc.local (so that the correct speed is set at startup)

Additionally I created a hotplug script /etc/hotplug.d/ntp/50-qos-schedule


#logger -t hotplug-ntp-qos-schedule "Action is $ACTION, stratum is $stratum"
[ "$ACTION" = stratum ] || exit 0

logger -t hotplug-ntp-qos-schedule "Running qos-schedule from ntp hotplug event"

Lastly, I added /root/qos-schedule.sh and /etc/hotplug.d/ntp/50-qos-schedule to /etc/sysupgrade.conf

kls0e Would you like to add that to your list of super cool tutorials?”


iPerf on Fritzbox stock firmware

iPerf is a great cli tool to measure raw network throughput between two devices. I often use it with OpenWrt and while talking about AVMs Fritzbox routers during a Freifunk Berlin meeting, Nicolas mentioned that there is a little-known support interface with their stock firmware at https://fritz.box/support.lua that offers starting an iPerf server – look for Durchsatzmessungen. Very handy.
Note that on client side, parameter -p 4711 is required for the non-standard port.

How to host a (small) website on your Freifunk node

Due to the versatility of OpenWrt, being a fully equipped Linux distribution itself, there are all tools already installed on your Freifunk node that are required turn it into a small web server. In fact its web gui LuCI is a website served by the node already. I suggest starting with static html+css and I can recommend Hugo as a Framework to generate it. So let’s use the existing infrastructure to host our own website:

selecting the best storage option for your webroot

  1. First think about where you would like to store your web files aka your webroot. This can be anywhere accessible by your nodes’ file system. Essentially, we have three options: ramdisk, external usb storage and router flash memory.
    Check out your options and the free available space with its corresponding mount points with df -h.

  2. I decided to use the routers’ ramdisk, already available at /tmp using tmpfs. If you have a device with at least 128 MB of RAM and your website is not too large, I think this is a good way to go since ram is blazing fast and tmpfs size is configured as 50% spare by default, i.e. it grows with the content it holds, up to a size of 64 MB. Rest of RAM is available to the system.
    As we know, RAM gets zapped on every boot so I set up a small script to run with /etc/rc.local. The script pulls a tarball using wget every time the router boots and extracts it to /tmp/wwwroot which is the path to my webroot.
    Of course you can also mount external usb storage and use it as a webroot, it will be slower than tmpfs but persistent. Although technically possible, I would not use the routers’ own flash chips to store a webroot if the device has NOR flash because there might be no error correction and the blocks wear out after a certain amount of write cycles.
    If your device sports a NAND flash chip, such as the Fritzbox 3370 or the GL.iNet AR-300-M, using NAND as webroot is fine.

configuring the webserver

  1. Let’s use uhttpd, which already serves LuCI on your freifunk node, as the webserver. It actually performs very well. Edit the config at /etc/config/uhttpd:

Just copy the config uhttpd ‘main' block, insert it at the end of the file and rename the new section. also adjust the path at home to your webroot, raise max_requests and max_connections a bit and, if you want to leave LuCI enabled, choose some other ports for the listen_http and listen_https entries.
Here’s my sample config:

config uhttpd 'kls0e'                      
        list listen_http ''   
        list listen_http '[::]:10178'      
        list listen_https ''  
        list listen_https '[::]:10785'     
        option home '/tmp/wwwroot'
        option max_requests '48'                
        option max_connections '400'            
        option cert '/etc/uhttpd.crt'           
        option key '/etc/uhttpd.key'            
        option cgi_prefix '/cgi-bin'            
        list lua_prefix '/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua'
        option script_timeout '60'                                      
        option network_timeout '30'                                     
        option http_keepalive '20'                                      
        option tcp_keepalive '1'                                        
        option ubus_prefix '/ubus'                                      
        option rfc1918_filter '0'                                       
        option redirect_https '0'

As you can see, this website is served at port 10178. Maybe you can guess from looking at the config that I am planning to get proper SSL running as well, so the website is reachable using https:// without certificate warnings, as every website should be, to avoid plain-text MitM manipulation.
There is a tutorial on how to do that: LE-HTTPS on OpenWRT with uhttpd by stokito
If you have an idea on how to fully automate the Let’s Encrypt certbot renewal process directly on an OpenWrt device, please let me know.

manually downgrading mesh links using olsr Link Quality Multipliers (LinkQM)

Let’s say you have a node that sees two other nodes in the mesh with a fairly good connection but you want to shape the traffic flow because there are reasons to do so. To achieve this, we can apply link quality multipliers to certain routes. The router will multiply the routes’ priority by this factor and thus downgrade it if we choose a number lower than 1, e.g. 0.5.

  1. Find out which ip your mesh interface and the other nodes’ mesh interface has:
    The left column consists of mesh interface ips of the router you are logged into, the right column consists of remote mesh interface ips. If you are lucky, a third column to the right will appear, showing the remote olsr hostnames.
    Note your mesh ip and the remote mesh ip.

  2. You need to know your local mesh interface name you want to apply the LinkQM rule to. In the following command, insert your mesh ip (left column from step 0) that sees the other node you want to downgrade the link to:
    ip a | grep <your mesh ip from neigh.sh>

The last phrase of the output is the local interface mesh name, common results include wlan0-mesh-2, wlan1-adhoc-5, fflan, … - depending on your setup.
Important: If it is a wireless mesh interface, we need to know the network name assigned to it. You can find this information in /etc/config/wireless. Everything that starts with wlan0- is most probably wireless0, everything that starts with wlan1- is most probably wireless1.

  1. With this information, we can edit the olsr config at /etc/config/olsrd. We need to scroll down to the appropriate interface section with the local mesh interface network name we have found out in step 1.
    We can now add a new option for it:

option LinkQualityMult ‘<remote mesh ip> <multiplier>'

So as an example, my result for step 1 was fflan, because the link I want to downgrade is reachable through a lan mesh interface. The remote mesh ip from step 0 in my example is and I would like to downgrade the link by factor 2, so my multiplier is 0.5. So I am scrolling down to where the olsr config says option interface ‘fflan' and I add the corresponding LinkQM option like so:

config Interface                                 
        option ignore '0'                    
        option interface 'fflan'             
        option Mode 'ether'        
        option LinkQualityMult ' 0.5'

Keep in mind, for wireless mesh interfaces, you need to look for wireless0 or wireless1 instead of fflan. To apply the changes, restart olsrd by issuing /etc/init.d/olsr restart. Wait some minutes before testing the new routing until the router reworks its routing priorities.

Freifunk Berlin can be complicated sometimes but you can learn a lot.

Measuring network throughput between two nodes with iPerf

In mesh networks, throughput between nodes that are supposed to talk to each other is the key performance factor. There is a handy tool called iPerf already pre-installed with our Freifunk images that can measure the actual bandwidth between two nodes. It is client-server based, so to benchmark, run
iperf -s on one of the nodes, this will start an iperf server listening to connections, and on the second node, run
iperf -c <server> -d -t 15 -i 1 -P 2, this will connect the iperf client to the server and will run a heavy raw network throughput benchmark for 15 seconds. It is always good to play around with the options a bit to get the idea and maybe fine-tune the command.
If you are about to reposition an antenna and would like to check out a continuous iperf feed while doing so, I suggest using
iperf -c <server> -d -t 360 -i 1, this will be a bit easier to lift for the tcp stack of the device.

By the way, there is iPerf3, which has been around for a couple of years now, and I hope we will include it in our future Freifunk images, so have a look at this newer version, too.

How to run your own Freifunk Berlin service

Martin, a fellow Freifunker from Freifunk Fürstenwalde asked me to publish a tutorial on how to set up your own service in the Freifunk Berlin network. It is actually quite easy once you know how.

Note: Your service has to have an ip reachable from within Freifunk Berlin, you can configure a static ip for it from your Freifunk dhcp pool. If you use the first dhcp ip your Freifunk router would issue to a client, edit its /etc/config/dhcp and raise option start ‘2' to option start ‘3' in the lower dhcp config block. This reserves the ip for your static configured service host and avoids duplicate ip delegation via dhcp.

How to announce your service in the Freifunk Berlin network:

  1. log in to your router via ssh

  2. edit the olsr config of your router:
    vim /etc/config/olsrd

  3. scroll down to the section that starts with

config LoadPlugin
     option library 'olsrd_nameservice'
  1. press i to insert text

  2. add

list hosts '<freifunk-ip> <hostname without .olsr>'
list service 'http://<freifunk-IP:port>|tcp|<name of service>'

example: let’s say my service has and I would like the host to be known as kls0e.olsr, and let’s say there is a web server up at port 10178, and every router at Freifunk Berlin should show a link named kls0e to this server under Services on its web gui, then my nameservice plugin section would look like so:

config LoadPlugin
        option library 'olsrd_nameservice'
        option suffix '.olsr'
        option hosts_file '/tmp/hosts/olsr'
        option latlon_file '/var/run/latlon.js'
        option services_file '/var/etc/services.olsr'
        list hosts ' kls0e'
        list service '|tcp|kls0e'

udp protocol is also an option instead of tcp. Port info is mandatory, even if it is port 80.

Give it 5-15 minutes to propagate your service announcement across the network.

From my experience, sometimes not all nodes can resolve the hosts entry, so I have chosen to publish the service with its direct Freifunk ip instead of an OLSR host name. The latter would be cooler but form follows function, I am glad if it works for you tho, please try.

Freifunk Berlin mesh protocol snippets

We are moving from IBSS to 802.11s as the main mesh protocol used for our meshes in the Freifunk Berlin network.

I think the easiest way to adjust the mesh protocol of a freifunk router is to edit /etc/config/wireless and insert or replace the config blocks accordingly.

Please pay attention to the interface names of dual-band devices, the majority of routers call their 2.4 ghz module radio0 and their 5 ghz module radio1, but a Ubiquiti UAP Pro flying saucer frisbee for that matter keeps it vice versa.

If your router only has one radio (radio0), just use the radio0 snippet.

# 802.11s for 2.4 ghz                         
config wifi-iface                   
        option network 'wireless0' 
        option device 'radio0'     
        option ifname 'wlan0-mesh-2'
        option mode 'mesh'               
        option encryption 'none'             
        option mesh_fwding '0'               
        option mesh_id 'Mesh-Freifunk-Berlin'
        option mcast_rate '12000'

# 802.11s for 5 ghz                                   
config wifi-iface                             
        option network 'wireless1'            
        option device 'radio1'                
        option ifname 'wlan1-mesh-5'          
        option mode 'mesh'                    
        option encryption 'none'              
        option mesh_fwding '0'                
        option mesh_id 'Mesh-Freifunk-Berlin'
        option mcast_rate '12000'
# Ad-Hoc / IBSS  for 2.4 ghz         
config wifi-iface                            
       option ssid 'intern-ch13.freifunk.net'
       option ifname 'wlan0-adhoc-2'
       option network 'wireless0'
       option encryption 'none'
       option device 'radio0'          
       option bssid 'D2:CA:FF:EE:BA:BE'
       option mcast_rate '6000'
       option mode 'adhoc'

# Ad-Hoc / IBSS for 5 ghz         
config wifi-iface                           
       option bssid '02:36:CA:FF:EE:EE'     
       option ifname 'wlan1-adhoc-5'        
       option network 'wireless1'           
       option ssid 'intern-ch36.freifunk.net'
       option mcast_rate '12000'             
       option mode 'adhoc'                   
       option device 'radio1'

You can apply all changes made to /etc/config/wireless simply by issuing wifi. There is no need to reboot. If you want the new set mesh interfaces to be monitored with the stats monitor, edit /etc/config/luci_statistics and replace or adjust the interface names in the corresponding sections. To apply these changes, run /etc/init.d/luci_statistics restart.
Bonus: If you have made changes to /etc/config/network, just run service network reload to apply.

24h auto rebooting a router with cron

There is an old WDR3600 we have had donated by some kind soul and its 2.4 ghz radio every now and then would conk out, but it is just not broken enough to throw it away. Rebooting it every 24 hours does the trick:

  1. crontab -e

  2. press shift+G to go to the end of the cron job table

  3. press i for text insert mode

  4. insert this line to reboot the router every night at 3:42 AM:

42 3 * * * sleep 70 && touch /etc/banner && reboot >/dev/null 2>&1

This was initially posted by Jan at Freifunk Winterberg and I thought the line is worth sharing as there is a simple fail-safe option included which essentially prevents the router from accidentally entering a continuous boot-loop caused by a wrong date / time set on the machine. This is a common issue since most routers do not sport an embedded buffered clock and sync their time and date by ntp every once in a while.

compiling Falter Images for Freifunk Berlin

For various reasons, I am glad that Nick has made some efforts to flange our precious Freifunk Berlin Firmware onto Vanilla OpenWrt. The results are in the Falter Github Repo.

Update: The following tutorial is now deprecated as it might contain an outdated diffconfig. Things just got easier: Martin was so kind as to create a build script for Falter images, please find it here and use it instead.
Here is a quick tutorial on how to build working Freifunk Berlin tunneldigger Images using Falter on a linux box:
  1. install OpenWrt build prerequisites aka needed packages as described here.

  2. clone OpenWrt

git clone https://git.openwrt.org/openwrt/openwrt.git falter

  1. change into falter folder by

cd falter

  1. copy feeds.conf.default to feeds.conf

cp feeds.conf.default feeds.conf

  1. add the following line to feeds.conf

src-git falter https://github.com/Freifunk-Spalter/packages.git

  1. run the following two scripts
./scripts/feeds update -a
./scripts/feeds install -a

  1. select your platform and router with the following command. if you do not know where to find it, have a look at the OpenWrt wiki (I’d just google openwrt <routername>) for the router you want to build for, and look at the URLs of the downloadable images, you can get the info from the path, e.g. “ath79” and such

make menuconfig

save + exit.

  1. create a plain-text file called diffconfig and insert this with your favourite text editor:

The diffconfig essentially tells the OpenWrt build system to include our Freifunk Berlin packages as well

  1. merge the diffconfig into the OpenWrt .config file
    cat diffconfig >> .config

  2. Sync the edited OpenWrt config, important, don’t forget:
    make defconfig

  3. finally: Build the whole thing. The first build will take some time, roughly 1h or so, after that the consecutive builds will be much faster
    make -jX V=s important: replace the X with cpu threads of your machine +1, for example I have 4 cpu cores that can do 8 threads via Hyperthreading, so I compile using make -j9 V=s

The resulting image will be in bin/targets and is ready to flash. Of course it can be used for plain-mesh nodes as well. You can also sysupgrade from 18.06-based and 19.07-based nodes preserving their config.

Enjoy your falters! Many thanks to everyone who contributed to this and to the Freifunk Berlin Firmware.

PS: Whenever you want to update your buildroot with the latest patches and code, run
git pull
./scripts/feeds update -a
./scripts/feeds install -a

and continue from step 6.