Archive for the ‘TheInternet’ Category

Compiling a kernel module on and for the raspberry pi

Wednesday, May 18th, 2016

So in order to compile a module for a precompiled version of the raspberry pi linux kernel, some quirks were necessary. The goal was to not build the kernel fully (which is also possible after these steps) but to rebuild a module for the currently running kernel after modifying its source.

If you have seen

Error: could not insert module drivers/w1/slaves/w1_therm.ko: Invalid module format

while trying to insmod and

[ 5697.914596] w1_therm: no symbol version for module_layout

in dmesg or

ERROR: could not insert 'w1_therm': Exec format error

after modprobe, then stick around.

My script with explanations is available over at

https://github.com/x29a/kernel/blob/master/rpi/prepare.sh

so hopefully all that needs to be done on the rpi is (as root, sudo -i)

# mkdir -p /root/kernel
# cd /root/kernel
# wget https://raw.githubusercontent.com/x29a/kernel/master/rpi/prepare.sh

then check if the defaults in the script are fine for you, like location for source and kernel branch, then execute

# bash prepare.sh

and follow the instructions. Each new message expects a keypress to continue.

Following is some additional info i found handy on my journey to a loadable module.

If you have used rpi-update by accident and got on an experimental kernel (remember, new kernels are now installed via apt-get!) you can revert to a stock kernel by forcing a reinstall via

apt-get install --reinstall raspberry-bootloader

When is Module.symvers generated.

How to get the right kernel version for a running setup without recompiling kernel.

Crosscompile a kernel module.

General information on building the rpi kernel and general kernel module building and contribution infos.

Blackberry OS 10 and LetsEncrypt

Saturday, March 19th, 2016

The great service at https://letsencrypt.org offers certificates for everybody to encrypt their websites with (meaning to offer HTTPS).

Unfortunately, the Blackberry OS 10 Browser does not yet ship with the certificates used to sign the websites so you either have to go back to unsecure HTTP or in case of HSTS you are unable to view the webpage.

Hopefully, there will be an update to BBOS 10 soon to fix this issue.

Luckily, one does not have to wait for the update but can manually import the needed certificates.

Head over to https://letsencrypt.org/certificates/ and download the PEM format of:

  • ISRG Root X1
  • Let’s Encrypt Authority X1 (IdenTrust cross-signed) and Signed by ISRG Root X1
  • Let’s Encrypt Authority X2 (IdenTrust cross-signed) and Signed by ISRG Root X1
  • Also get the DST Root CA X3 by copying the text to a textfile, remove the whitespace at the end and surround it by

    -----BEGIN CERTIFICATE-----

    copied text here

    -----END CERTIFICATE-----

    each on a new line. Save that file as dst_root_ca_x3.pem

    After copying all files to the device (e.g. via SD card), go to Settings -> Security and Privacy

    Securiy and Privacy

    -> Certificates

    Certificates

    and Import

    Import

    all 6 files (5 from LetsEncrypt and 1 from IdenTrust).

    Thats it, open your browser and try it out.

    OpenWRT as internet filter for e.g. kids

    Monday, January 18th, 2016

    The internet is for porn.

    Therefor, when some content should to be blocked from somebody (e.g. kids), an internet filter is required. If course, primarily this should be handled by talking to the kids and trust! And im not promoting monitoring!

    A technical filter solution can be implemented with OpenWRT (15.05 and up). It is an open linux plattform for various WLAN routers, e.g. the TP-Link WR841ND or its bigger brother TP-Link WR1043ND (moar power!).

    After following the wiki pages on where to download and how to install the firmware, OpenWRT boots on the router. On first access, the webinterface asks for a password to be set. After setting the password, one can configure the device via ssh as user “root”.

    In the default configuration, the LAN ports and the WLAN is put together into a virtual network called “lan”. The WAN port represents another network called “wan”. The internet filter will be set-up between those two, so that every package from the “lan” is checked against a set of criteria and then allowed (or not) to go into the “wan”. For this to work, the WAN port should be connected to the home network with internet access, the to-be-filtered clients can connect via WLAN or LAN.

    First step after connecting via SSH is to install the required software (note: the WR841ND will be pretty full so if you want to install more software, get a bigger model or do some USB tricks):

    # opkg update && opkg install ipset tinyproxy

    Tinyproxy is used to allow access to some defined HTTP sites. It has to be enabled so /etc/config/tinyproxy has to be changed to contain option enabled 1 and it has to be started via /etc/init.d/tinyproxy start.

    Next is the firewall. I am sticking to the configuration via /etc/config/firewall, although iptables can be used directly. This has the advantage of being able to use the webinterface as well to change the rules.

    The order of the rules is important, as traffic is checked against all traffic until it finds a matching rule. See the attached file for reference. Some pieces are explained in more detail now.

    To turn off the internet at certain times:

    config rule
            option name             'time based morning'
            option src              'lan'
            option dest             'wan'
            option start_time       '00:00'
            option stop_time        '07:00'
            option weekdays         'mon tue wed thu fri'
            option proto            all
            option extra		'--kerneltz'
    	option target           REJECT
            option enabled          '1'
    
    config rule
            option name             'time based evening'
            option src              'lan'
            option dest             'wan'
            option start_time       '21:00'
            option stop_time        '00:00'
            option weekdays         'mon tue wed thu sun'
            option proto            all
            option extra		'--kerneltz'
            option target           REJECT
            option enabled          '1'

    The option “–kerneltz” will make the firewall use the kernel timezone instead of the default, UTC. The kernel timezone is configured in /etc/config/system.

    To redirect all webtraffic (port 80) to tinyproxy running on the router (whose ip is 172.29.0.1 here):

    config redirect
            option name 		'redirect 80 to proxy'
            option src 		'lan'
            option dest 		'wan'
            option src_dport 	'80'
            option dest_ip 		'172.29.0.1'
            option dest_port 	'8888'
    	option proto		'tcp'
    	option target		'DNAT'

    Tinyproxy can than be configured to (see option Filter) to allow certain pages. It is not possible to filter HTTPS (SSL) pages this way (as transparent proxy), recompilation of the packages with SSL support and some more tinkering is required. Squid can also be used.

    For specific services, it is easier to make an ip whitelist:

    config rule
            option name             'whitelist'
            option src              'lan'
            option dest             'wan'
            option proto            'tcpudp'
            option ipset            'wl'
            option target           'ACCEPT'
    	option enabled		'1'
    
    config ipset
            option external         'wl'
            option storage          'hash'
            option match            'dest_net'

    This references an ipset with ips where traffic to is allowed. For this to work, /etc/rc.local should contain the following

    # load the ipset for whitelisting 
    /etc/init.d/firewall stop
    ipset flush
    ipset destroy
    ipset restore < /etc/config/ipset.save
    /etc/init.d/firewall start
    
    exit 0

    This script stops the firewall during startup, loads the list of ips and restarts the firewall. The ips are saved in /etc/config/ipset.save which could look like

    create wl hash:net family inet hashsize 8192 maxelem 165536
    add wl 127.0.0.1
    add wl 172.29.0.1
    add wl ......

    Some companies provide their ip networks for easy addition, e.g. BlackBerry and WhatsApp.

    The last rule should disallow all traffic (or make it the default behaviour).

    Remember, when the “client” has physical access to the router, the failsafe mode can be used to gain access and change the config so disable it (note: be careful not to lock yourself out now).

    Hacking the Withings WiFi Body Scale

    Sunday, April 14th, 2013

    Keeping track of weight development just got a lot easier, now that scales like the “Wifi Body Scale” by Withings (available at e.g. Amazon) can post their measurements via Wifi.

    Unfortunately, the scales post their results to the webpage of the manufacturer, which some people are not comfortable with. Fortunately, the communication is unencrypted and easy understandable (JSON based).

    Other folks have paved the way by analyzing the protocol. The general approach stays the same

    1. Pair the scales via the instructions (need an account at my.withings.com) with the wifi network
    2. Redirect the DNS requests from the scales to your own server
    3. Setup some script which simulates a Withings server
    4. Communicate!
    5. Do something with the data

    1. Pairing
    There are different models that have different pairing approaches, consult the FAQ for additional information. The document also provides information on error codes and how to reset the device (or perform firmware updates).

    UPDATE: Withings now uses Zendesk for support information.

    2. DNS Spoofing
    In order to redirect the requests from the device, many ways lead to Rome. Depending on your network configuration, you could use dnsmasq on your router and configure it to respond with a modified ip via:

    address=/withings.net/10.0.0.5
    address=/withings.com/10.0.0.5

    where 10.0.0.5 is the ip of your own server. While the WebGUI is hosted at withings.com, the scales try to communicate with scalews.withings.net. Both resolve to ‘89.30.121.150’. If you have your own bind service running, configure a zone for the withings domains.

    3. Server
    Now that the scales talk to your webserver at 10.0.0.5, the conversation has to be performed. “Prox” wrote a python script, while “sd” (german) used PHP.

    The configuration of the webserver might have to be changed in order to redirect the requests from

    • /cgi-bin/once
    • /cgi-bin/session
    • /cgi-bin/maint
    • /cgi-bin/measure

    to your own script. Running nginx, add the following to your server configuration

    # allow POST requests to static content
    error_page 405 = $uri;

    # redirect withings scale requests
    location /cgi-bin {
    rewrite ^/cgi-bin/(.*)$ /withings/index.php?s=$1;
    }

    and the requests will be forwared to the PHP script “index.php” at /withings on your webserver.

    4. The communication
    The communication consists of 5 Steps and is handled via POST requests containing JSON data

    1. Request to /cgi-bin/once:

      POST: Array
      (
      [action] => get
      )

      Response:
      {
      "status": 0,
      "body": {
      "once": "87a6549c-93f7bce8"
      }
      }

      Remarks:
      – status 0 means no error (query the withings service to get some error codes like 2554)
      – the once UID can be random 8 chars, dash, 8 chars

    2. Request to /cgi-bin/session:

      POST: Array
      (
      [action] => new
      [auth] => 00:00:be:ef:00:07
      [hash] => e26b6c7dcb05ac46bde912d2bc951d83
      [mfgid] => 114700
      [currentfw] => 79
      [batterylvl] => 100
      [duration] => 30
      [zreboot] => 0
      )

      Response:
      {
      "status": 0,
      "body": {
      "sessionid": "7bf5-382a9b74-183dcfe5",
      "sp": {
      "users": [
      {
      "id": 5555,
      "sn": "BEN",
      "wt": 80,
      "ht": 1.75,
      "agt": 23.4,
      "sx": 0,
      "fm": 131,
      "cr": 1365963066,
      "att": 0
      },
      {
      "id": 6666,
      "sn": "SEN",
      "wt": 80,
      "ht": 1.75,
      "agt": 42,
      "sx": 1,
      "fm": 131,
      "cr": 1365963066,
      "att": 0
      }
      ]
      },
      "ind": {
      "lg": "en_US",
      "imt": 1,
      "stp": 1,
      "f": 2,
      "g": 98124
      },
      "syp": {
      "utc": 1365974415
      },
      "ctp": {
      "goff": 7200,
      "dst": 0,
      "ngoff": 0
      }
      }
      }

      Remarks:
      – auth in request: MAC address of scales (can be found in the battery compartment)
      – response: list of user profiles, scale settings and time information

      “id”: numeric id for user
      “sn”:” three chars displayed in the scales (usernick)
      “wt”: weight in kilograms, used for identification
      “ht”: height of user in meters
      “agt”: age in years
      “sx”: sex of user (0: male, 1: female)
      “fm”: unknown
      “cr”: timestamp of last measurement or account creation
      “att”: unkown
      lg”: language, like “en_US” or “en_GB”
      “imt”: perform induction measurement (0: off, 1: on)
      “stp”: 1 (unknown)
      “f”: autocalibrate mode (0: measure directly, 2: calibrate via tap before measuring)
      “g”: value for gravity (98124). This highly influences the weight result!
      “utc”: current UNIX timestamp}
      goff”: unkown
      “dst”:0 (DST switch?)
      “ngoff”: unkown

    3. Request to /cgi-bin/maint:

      POST: Array
      (
      [action] => store
      [sessionid] => 7bf5-382a9b74-183dcfe5
      [source] => 1
      [type] => 2
      [data] => [WDEBUG] dac: 1419 1508 1638 1791
      [WDEBUG] adc: 21800 21500 21900 21800
      )

      Response:
      {
      "status": 0
      }

      Remarks:
      – Maintenance values (seem like raw values from ADC and DAC)
      – Response from real server is much longer, but since its not needed for now, status: 0 should be enough

    4. Request to /cgi-bin/measure:

      POST: Array
      (
      [action] => store
      [sessionid] => 7bf5-382a9b74-183dcfe5
      [macaddress] => 00:00:be:ef:00:07
      [userid] => 5555
      [meastime] => 1365974385
      [devtype] => 1
      [attribstatus] => 0
      [measures] => {“measures”:[{“value”:80050,”type”:1,”unit”:-3},{“value”:239,”type”:16,”unit”:0}]}
      )

      Response:
      {
      "status": 0
      }

      Remarks:
      – Measurement from scales, type: 1 seems like weight
      – Response from server is just the usual “ACK”

    5. Another request to /cgi-bin/maint, ignored for now.
    6. Request to /cgi-bin/session:

      POST: Array
      (
      [action] => delete
      [sessionid] => 7bf5-382a9b74-183dcfe5
      )

      Response:
      {
      "status": 0
      }

      Remarks:
      – Logoff from service
      – Response from server is just the usual “ACK”

    5. The data
    Since the device can buffer some measurements, it can happen that multiple results are transfered at once.

    Once the data is saved, its up to you how to analyze it. More to come (like my index.php).

    Simple script for changing wallpaper using RSS feed

    Monday, July 16th, 2012

    Just had the idea to change the wallpaper of my desk according to an RSS feed.

    Here’s the shellscript:

    #!/bin/sh
     
    IMGPATH="/home/chris/Pictures/Wallpapers/factsandchicks"
    IMGURL=$(wget -q -O- "http://www.factsandchicks.com/rss" | grep -o 'src="[^"]*' | grep -m 1 -o '[^"]*$')
    LOCALFILENAME=$(echo $IMGPATH/$(date +"%Y%m%d").jpg)
     
    wget -q -O$LOCALFILENAME $IMGURL
     
    gsettings set org.gnome.desktop.background picture-uri file:///$LOCALFILENAME

    For this example, I used the RSS feed from factsandchicks.com (o.O)
    The command in the last line depends on your distribution, this one works for newer Ubuntus. You probably want to run this script via cron or rc.local to get the new wallpapers regularly.

    Have fun!