Building a network monitor

As so many of us I’m currently working from home. My internet at home is most of the time pretty ok, but it can get very flaky, as in, speed drops, it can’t connect to certain hosts etc.

However, every time I report this to my ISP, I get the same routine: restart, unplug, hold for 30 seconds, pray to Ubuntu and other ridiculous demands that make no sense because I didn’t change anything in the hardware (I didn’t even move it).

So to prove my point, I decided to refurbish one of my Raspberry Pis as a network monitor using InfluxDB to collect the results and Grafana to spice up the charts

So to do this you obviously need

  • A raspberry PI
  • An internet connection (doh!)
  • A time series database InfluxDB
  • Some python3 scripts to collect the data.
  • A graphing tool Grafana

Setting up the PI

Following one of the many tutorials, I managed to setup a Pi in headless mode. Aka, it’s plugged into power and ethernet and using my router it’s configured to always be at a certain IP address. It has SSH running so I can connect to it from my laptop. This is the basic setup and requires the minimal amount of wires.

I didn’t set it up wireless as I want to be as close as possible to the router so it literally sits next to the router plugged in in one of the available ethernet ports of the router. This should give me the optimal network so they can’t blame my wifi.

First thing you do obviously is to change the password for the pi user to something other than raspberry. The thing will be hooked to the internet and you can never be safe enough.

Once I log into it using ssh, I first upgrade it to the latest versions, so I need to run a few commands: 

sudo apt update
sudp apt upgrade

Go grab a cup of coffee as this might take a while if you haven’t been updating that Pi regularly. You have to be on at least Stretch or Buster for InfluxDB. You can’t go from Jesse to Buster in one go, so if you want to do that, you have some time to waste.

If you want to be quick about this and you don’t care about your existing image, it’s faster to just grab the latest image using the imager from https://www.raspberrypi.org/downloads/

If you want a graphical UI, you can enable VNC simply by typing sudo raspi-config and select the Interfacing Options, VNC, enable. This should install the vncserver and configure it. When it’s done, it should be running on port 5900. Obviously, I have ssh enabled as that’s the main way to connect to it.

Installing InfluxDB

InfluxDB is not a standard install so we will need to get it from another source than the default apt repositories. I took my cue from https://pimylifeup.com/raspberry-pi-influxdb/

wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -

All on one line. This will download the key and pass it into apt-key for further use. As I am on buster, I can use:

echo "deb https://repos.influxdata.com/debian buster stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

Obviously, replace buster with stretch for stretch. Now we’ve added a new repo, we can again do ‘sudo apt-get update’ and then ‘sudo apt install influxdb

And to make sure influxdb runs on boot:

sudo systemctl unmask influxdb
sudo systemctl enable influxdb
sudo systemctl start influxdb

our next step here is to setup a database in influx, so we must be able to login, for that, we need the client.

sudo apt install influxdb-client

And then you can just type `influx`. First we’ll be setting up authentication (replace your password with what you want)

CREATE USER admin WITH PASSWORD '<password>' WITH ALL PRIVILEGES

And then we’re going to make this user the only admin by setting up authentication by editing the influxdb.conf file:

so exit out of the client and back on console, type ‘sudo nano /etc/influxdb/influxdb.conf‘ and Find the [http] section and under there add:

auth-enabled = true
pprof-enabled = true
pprof-auth-enabled = true
ping-auth-enabled = true

Then we need to restart the database by typing ‘sudo systemctl restart influxdb

Now, if we want to connect we need to type:

Influx -username admin -password ‘’

By passing in the empty string influx will prompt for the password. This keeps it out of your history file. Though, I doubt that your pi will be setup to host many users so you might just not give much for this.

Ok, so now we’re going to setup another user for it’s own database, I called mine netmonitor and the database the same.

create database netmonitor
create user “netmonitor” with password ‘<again your choice>’
grant all on “netmonitor” to “netmonitor”

Take note that the password requires single quotes!

Great, InfluxDB is installed. Now it’s time to collect the data

 

The Python bits

At first I started out with two scripts, one that used speedtest-cli (I based this one on prior art from https://pimylifeup.com/raspberry-pi-internet-speed-monitor/) and another one that simply connects to Google’s DNS server at 8.8.8.8 with a 3 seconds timeout to monitor if the internet is up or down. Later I added a 3rd that captures the output of pings to various sites I was interested in (at some point I will probably make that configurable)

Obviously it’s fun to paste a lot of Python code here, but you can also just check out the repository here: https://github.com/siriousje/speedtest because over time I will probably add some more scripts.

So, the easiest way to get the code is to login to your Pi, and if for some reason you don’t want to type sudo before each command, do some root magic like 'sudo su -‘ and become root.

Clone this repository under /opt so that it creates /opt/speedtest Then make sure to install all requirements: sudo pip3 install -r requirements.txt\

Copy config.yml.sample to config.yml and update the values for your installation, then add the scripts to crontab using sudo crontab -e

it should look something like

*/5 * * * * python3 /opt/speedtest/speedtest-influx.py
*/1 * * * * python3 /opt/speedtest/internet-influx.py
*/1 * * * * python3 /opt/speedtest/latency-influx.py

Change the numbers to what you want, I run the speedtest only once per 5 minutes.

You can also use environment variables to override your config, but I wouldn’t really bother 🙂

Anyway, this is it, it should now be adding data to your InfluxDB. You can check this by logging into Influx as the netmonitor user by typing

influx -database "netmonitor" -username "netmonitor" -password "what you did"

and then as a normal database, `select * from internet_latency` to see the data flowing in.

Setting up Grafana

Congratulations! You made it to the sexy bits, graphs! This is what we came here for! Let’s go!

Depending on your PI, you may need to find the correct version of Grafana for your architecture. There is a difference between the Pi v1 and Pi Zero v.s. the Pi 2 and up. I use a pi3, so I go with 

wget https://dl.grafana.com/oss/release/grafana_6.6.1_armhf.deb
sudo dpkg -i grafana_6.6.1_armhf.deb

If you were using a pi-zero you should use this:

wget https://dl.grafana.com/oss/release/grafana-rpi_6.6.1_armhf.deb
sudo dpkg -i grafana-rpi_6.6.1_armhf.deb

The small difference there is the -rpi. And again we want this up and running after boot, so here we go:

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable grafana-server
sudo /bin/systemctl start grafana-server

And then we go to the webinterface (as my pi is fixed to 192.168.1.199, the service is running on port 3000) so for me it is at http://192.168.1.199:3000/login and change the password to something you fancy

Next step is to configure the datasources!

Grafana already suggest the defaults for InfluxDB, but you still have to type it in the field (it’s a placeholder…) You want to keep localhost because it’s all on that same Pi.

Then obviously, fill out the login details for the datasource. So you need to setup the basic auth and the InfluxDB details:

And then you can test and save your datasource. If it’s green it’s good to go. Great, now we’re going to create a dashboard and add our statistics. So click on the plus, then add dashboard and then we choose add Query

Then we can basically select from (I started with internet_speed), selected field pin, changed mean() to distinct() by clicking on the plus behind it and selecting Aggregate/distinct() and then we can give it an alias whatever you want:

Now if you are using tags, like for the internet_latency stat where we use the tags to collect the hosts, you can add tag(host) to the group by setting and it will plot all hosts over each other

Anyway, configure your dashboard anyway you want. Mine ended up looking like this:

Which gives me a clear view that my internet is capped on the top, but also has a lot of drops in speed and even regular timeouts getting connected to the nameserver.

Anyway, with this data at least I have something to tell my ISP that it’s not just me 🙂

 

Writing your own Google Apps Plugins

So I am currently between jobs and I like to use that time to learn new programming languages as I believe that you should try to think outside your day to day experiences. Especially in this world of microservices, it makes sense to broaden your horizon to see if you’re not always applying your favorite lawnmower to a problem that requires a hammer.

Given that I have about 4 weeks, I figure I can do more than one so I started with Erlang and I used Google docs to keep track of the notes. I quickly ran into a huge issue: there is no ‘format as code’ block functionality in standard Google Docs! Being used to Atlassian’s Confluence and even WordPress I was a bit undone. What next? Obviously I looked for plugins but they always want all the rights (like, run while you’re not around, access to your bookmarks and browser history, credit card details, you name it)

I also didn’t feel much for applying the same styles over and over again. So, what is a good procrastinator to do? Right! take a small break from his endeavours into Erlang and write a plugin for Google Docs! The API is pretty well documented and there are some samples online. But basically, if you go to Tools/Script Editor you’re already halfway there.

In the editor that popped up I wrote the following script (probably still buggy enough but it does the trick):

function onOpen() {
  DocumentApp.getUi()
  .createMenu('Custom')
  .addItem('Format As Code', 'formatAsCode')
  .addToUi();
}
 
// Define code styling
var style = {};
style[DocumentApp.Attribute.FONT_FAMILY] = "Courier New";
style[DocumentApp.Attribute.FONT_SIZE] = 10;
style[DocumentApp.Attribute.BACKGROUND_COLOR] = "#000000";
style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FFFFFF";
style[DocumentApp.Attribute.BOLD] = false;
 
// Apply code formatting
function formatAsCode() {
  var selection = DocumentApp.getActiveDocument().getSelection();
 
  if (selection) {
    var body = DocumentApp.getActiveDocument().getBody();
 
    var insert = null;
    var table = null;
    var cell = null;
 
    var elements = selection.getRangeElements();
    for (var i = 0; i < elements.length; i++) {
      var element = elements[i];
      if (element.getElement().editAsText) {
        if (insert == null) {
          insert = element.getElement().getParent().getChildIndex(element.getElement());
          var detached = element.getElement().removeFromParent();
          var table = body.insertTable(insert);
          var cell = table.appendTableRow().appendTableCell();
          cell.setAttributes(style);
          cell.appendParagraph(detached.asText().getText()).setAttributes(style);
          // for some reason there is an empty text element now
          cell.getChild(0).removeFromParent();
        }
        else {
          cell.appendParagraph(element.getElement().removeFromParent().asText().getText()).setAttributes(style);
        }
 
      }
    }
  }
}

And it allows you to save and immediately try the effects.

So, now I can finally get back to what I was doing, learning Erlang 🙂

 

Your arguments are invalid.

Because it’s enough to have just one. See, thanks to scope and something called currying, any multi-argument function can be rewritten as a unary chained function. A simple example is this Javascript function to add two arguments:

  1. function add(x, y) {
  2.    return x + y;
  3. }

it’s easy to see what that function would do, you pass in two arguments and they get added:

  1. var sum = add(2, 3); // 5

now, in a functional world, you want to have unary functions that take only one argument. How can you achieve a simple add function if you’re not allowed to take more than one argument? This can be done by currying (and it requires scope)

  1. function add(x) {
  2.    return function (y) {
  3.       return x + y;
  4.    }
  5. }

now the call to this method would be different because it just takes one argument. Thanks to the scope, the inner function can see the x, so you call this method like so:

  1. var sum = add(2)(3); // 5

And that’s how you can decompose a multi-argument function into many, nested unary functions.

I needed a TriFunction

Since Java 8 you can do such nice functional things, I love it. But, for some reason it has Functions and BiFunctions, but no TriFunctions! So, it was time to add the TriFunction interface. And yes, I’m very immature 😛

  1. import java.util.Objects;
  2. import java.util.function.Function;
  3.  
  4. @FunctionalInterface
  5. public interface TriFunction<S, U, C, K> {
  6.  
  7.   /**
  8.    * Applies this function to the given arguments
  9.    * @param s the first argument
  10.    * @param u the second arguments
  11.    * @param c the third argument
  12.    * @return K
  13.    */
  14.    K apply(S s, U u, C c);
  15.  
  16.   /**
  17.    * Returns a composed function that first applies this function to its input
  18.    * and then applies the {@code after} function to the result.
  19.    * 
  20.    * If evaluation of either function throws an exception, it is relayed to
  21.    * the caller of the composed function.
  22.    * @param <T>
  23.    * @param after
  24.    * @return 
  25.    */
  26.    default <T> TriFunction<S, U, C, T> andThen(Function<? super K, ? extends T> after) {
  27.        Objects.requireNonNull(after);
  28.        return (S s, U u, C c) -> after.apply(apply(s, u, c));
  29.    }
  30. }

 

Now, you can build functions that take 3 arguments and do something with them to return one result, like:

  1.  TriFunction<Boolean, Boolean, Boolean, Boolean> sucks = (s, u, c) 
  2.      -> Stream.of(s, u, c)
  3.           .allMatch(t -> Boolean.TRUE.equals(t));
  4.  
  5.  boolean f = sucks.apply(true, false, true); // f is false

Guess it doesn’t suck after all!

You are more likely to be killed by an asteroid than by a terrorist.

Though what happened in Berlin today is still ‘most likely’ an attack (by a lone wolf, not by an army of asylum seekers) we can’t generalise and blame this on asylum seekers in general. That’s just what our nationalistic leaders want, what the news papers want because it sells more papers.
 
By these rules of generalisation, all men are rapists, all fathers are incestuous, all mothers are whores, all white people trade slaves and basically all human beings are monsters. You cannot blame anything like this on entire groups of people. The fact is that only one person was driving that truck. Not a nation, not a group, not anyone else but that guy.
 
The chances that you are going to be killed in the next ‘terror attack’ are much smaller than the chances that you are getting killed by a drunk driver, by crossing a road, by actually driving a car and for some reason, in the USA, by having your toddler grab your gun from your purse.
 
The media loves to make these things bigger than they are, because this kind of fear makes their sales go up. The chances of you dying in a terrorist attack are pretty slim if you are living in a western society like most of Europe, the USA and here in Australia. It’s practically non-existent.
 
You are about 10 times more likely to die from SUICIDE than from murder. You are about 5 times more likely to die from DIABETES than from a traffic accident. You stand a better chance at winning the lottery than getting killed in a terror attack.
 
Let’s look at a quote from one of the sources below:
 
“The chances of being killed in a terrorist attack are about 1 in 20 million. A person is as likely to be killed by his or her own furniture, and more likely to die in a car accident, drown in a bathtub, or in a building fire than from a terrorist attack.”
 
ok, 1:20,000,000, should be able to handle that. Let’s compare it to something else:
 
“The chances a person will be killed by an asteroid are 1 in 200,000, which is much higher than the odds of being killed by hail, which is 1 in 734,400,000.”
 
Let that sink in people. You run a 100x (a hundred times) bigger chance to be hit by an asteroid than be killed in a terrorist attack!!! Why the fuck aren’t we walking around with titanium umbrellas!?
 
for crying out loud, let’s stop giving the media what they want: attention. Let’s stop giving away our privacy over this bloated sense of insecurity. And the great thing with ‘terror’ is, if you show a complete disregard of the effects, it’s not terrifying at all. They’re just what they really are: sorry excuses for living beings.
  
just some of the sources below.
 
 
 

Fixing ORD fields in Oracle

If you use Hibernate and ordered list, you’re probably familiar with having to add a column to retain the order. If you don’t want nulls in your list, you sometimes need to reorder this (say, for instance, if you manually remove an item from a list via the database).

Of course, you can do an update to “set ord = ord – 1 where ord = <first gap>” and continue doing so until you have the items nicely sequenced again. But if you have Oracle*, you can use the row_number() feature

Say you have a table ‘someTable’ and you removed a few rows from the list that is grouped by a foreign key (some_fk_id) for 123456 and you want to renumber the ORD field based on the order of inserted ID’s, you can do the following:

  1. MERGE INTO someTable T USING (
  2.        SELECT id, (ROW_NUMBER() OVER (ORDER BY id ASC) - 1) rn 
  3.        FROM someTable WHERE some_fk_id = 123456
  4.      ) R ON (T.id = R.id) 
  5.      WHEN MATCHED THEN UPDATE SET T.ord = R.rn;

This will then reorder the list, starting with 0 for that group. I’m pretty sure you can write your cursors to renumber entire groups of lists

* I believe other databases have this feature as well, such as Microsoft SQL Server, however, I don’t use those, so don’t blame me when it doesn’t work there 😉

 

 

Doing Enums with Jackson

Recently I’ve been working on a Jersey 2 application (a JAX-RS REST) using JSON. For the JSON serialization and deserialization I’ve chosen to use the Jackson framework. One of the reasons for this is that prior we’ve been using Freemarker templates, but if you use those, you can easily create invalid JSON which will eventually screw up your clients. Using Jackson & Jersey allow me to skip the entire Object graph to template to output chain and simply use POJOs and use annotations to model the JSON request and responses.

So basically, if I have a request/response that has a “number”, I can use those annotations to expose getter and setter methods, or choose to ignore Jackson adding a default. So in the next fragment, the getter getSomeArbitraryNumber() will be written to “number”, any incoming “number” will be mapped to setSomeArbitraryNumber and when serializing, Jackson will ignore the isNumberSet() method (without the JsonIgnore() it will expose “numberSet”):

  1.     ...
  2.     @JsonProperty("number")
  3.     public Long getSomeArbitraryNumber() {
  4.         return number;
  5.     }
  6.  
  7.     @JsonProperty("number")
  8.     public Long setSomeArbitraryNumber(Long number) {
  9.         this.number = number;
  10.         this.numberSet = true;
  11.     }
  12.  
  13.     @JsonIgnore()
  14.     public boolean isNumberSet() {
  15.        return numberSet;
  16.     }
  17.     ...

Anyway, long story short, I ran into issues with Enums, simply because, well, you can’t instantiate a new Enum. Exposing them as JSON objects wasn’t that hard, you can just add the @JsonFormat(shape=JsonFormat.Shape.OBJECT) annotation to the class and Jackson will serialize the Enum as if it was a simple POJO:

  1. package net.sirious.jackson.enum
  2.  
  3. import com.fasterxml.jackson.annotation.JsonFormat;
  4. import com.fasterxml.jackson.annotation.JsonProperty;
  5.  
  6. @JsonFormat(shape=JsonFormat.Shape.OBJECT)
  7. public enum MyEnumType {
  8.  
  9.     TYPE_ONE("one", "this is basically just type one"),
  10.     TYPE_TWO("two", "and this is type two");
  11.  
  12.     private final String id;
  13.     private final String description;
  14.  
  15.     private MyEnumType(final String id, final String description) {
  16.         this.id = id;
  17.         this.description = description;
  18.     }
  19.  
  20.     @JsonProperty("id")
  21.     public String getId() {
  22.         return id;
  23.     }
  24.  
  25.     @JsonProperty("description")
  26.     public String getDescription() {
  27.         return description;
  28.     }
  29.  
  30.     /**
  31.      * Gets a MyEnumType from id or <tt>null</tt> if the requested type doesn't exist.
  32.      * @param id String
  33.      * @return MyEnumType
  34.      */
  35.     public static MyEnumType fromId(final String id) {
  36.         if (id != null) {
  37.             for (MyEnumType type : MyEnumType.values()) {
  38.                 if (id.equalsIgnoreCase(type.id)) {
  39.                     return type;
  40.                 }
  41.             }
  42.         }
  43.         return null;
  44.     }
  45.  
  46. }

So if I had a pojo with a getter like this:

  1.     ...
  2.     @JsonProperty("myenumtype")
  3.     public MyEnumType getMyEnumType() {
  4.         return myEnumType;
  5.     }
  6.  
  7. }

then Jackson will serialize MyEnumType.TYPE_ONE as follows:

  1.    ...
  2.    "myenumtype": {
  3.       "id":"one", 
  4.       "description":"this is basically just type one"
  5.    }
  6.    ...

However, deserializing is an issue, as normally Jackson expects a no-arg constructor, but you can’t have that with Enums. So you need something that can do this for you, which is a JsonDeserializer:

  1. package package net.sirious.jackson.enum.deserializer;
  2.  
  3. import com.fasterxml.jackson.core.JsonParser;
  4. import com.fasterxml.jackson.core.JsonProcessingException;
  5. import com.fasterxml.jackson.databind.DeserializationContext;
  6. import com.fasterxml.jackson.databind.JsonDeserializer;
  7. import com.fasterxml.jackson.databind.JsonMappingException;
  8. import net.sirious.jackson.enum.MyEnumType;
  9. import java.io.IOException;
  10.  
  11. public class RecurrenceEndTypeDeserializer extends JsonDeserializer {
  12.  
  13.     @Override
  14.     public MyEnumType deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
  15.  
  16.         MyEnumType type = MyEnumType.fromId(jp.getValueAsString());
  17.         if (type != null) {
  18.             return type;
  19.         }
  20.         throw new JsonMappingException("invalid value for type, must be 'one' or 'two'");
  21.     }
  22.  
  23. }

Above deserializer now allows you to accept Strings, either “one” or “two” in the JSON:

  1. {
  2.    ...
  3.    "myenumtype":"one" 
  4.    ...
  5. }

And then you can use this on your POJO as follows:

  1.     ...
  2.     @JsonProperty("myenumtype")
  3.     @JsonDeserialize(using = MyEnumTypeDeserializer.class)
  4.     public void setMyEnumType(MyEnumType value) {
  5.         this.myEnumType = value;
  6.     }
  7.  
  8. }

And that’s it! Jackson will automatically get the String “one”, use the deserializer to get a MyEnumType and then pass that on your POJO. You can use this method to customize any serialization/deserialization with Jackson.

Security and safety

Recently people who use Mac computers have asked me about security. Good question. I’d say they are pretty secure. They didn’t ask me about safety. That is a different question. I will try to explain why:

The only safe operating system is the one that is turned off, disconnected and preferably locked in a safe. And even then, it only takes one human to breach that security. As long as it is not turned on, or plugged into a network, it is still secure, but not safe.

Now, if you understand those rules, you can maneuver pretty safe and secure on the internet.

To do so, there are some simple rules you can follow:

Choose an operating system that is released as open source (why? because everything is transparent, every single bit of your operating system is out there, people know about it, good hackers and bad hackers the like, history has proven this, you are more vulnerable with a Microsoft (closed source) OS than with any obscure linux variant out there). Apple is turning towards the Microsoft side, but is at least based on a BSD unix variant, so, as long as you don’t give out your password to install the next .dmg you download, you are pretty safe (even if history has proven that Mac users are the least computer savvy users out there, you just got lucky that it’s in essence a unix machine)

Choose an operating system that is maintained (what does that mean? simply, the more people that are working on it, the more people who know a lot more than you do about operating systems are working on it) If more people are working on it, it does not mean it is not ready yet, it actually most often means that those good hackers are quite fond of it (pick any popular linux or freebsd version, it’s free and people are actively working on it to make it the most secure system they can think of)

Third, be a user when you can, only change into an administrator if you need to be. The way the unix (and alike) operating systems were designed was about giving users power to do things, but not to disrupt other users. I personally change into my root clothes when I think it’s time to delete a user account that has been compromised, or at least leans towards it or when I’m simply done with it. And since I have the power to become root, I can always create a new user.

Finally, and absolutely not the least, don’t be lazy, don’t reuse that password on website nr1 you used for website nr2, unless you don’t care about either of these (this is a rule I break often, I start out with using a weak password until I think I really want to keep that account).

Don’t use that service name in your password. Cryptology is only as smart as you are. You can have all your keys encoded in (who cares) 8 gigabyte keys, but if you use “-facebook” for facebook and “-twitter” for twitter, the other party already has 50% of your password decoded.

No matter how many bits you use to encrypt it, if they know half the message, it’s pretty useless because knowing what you are looking for makes it easy. (Really don’t want to go into details here, but you can understand that looking for “Hi Mom!” in a decrypt is easier if you are sure it contains “Hi Mom!” then if you don’t know that it should contain that)

A password like ‘IchHateMeinFuckingFriendDieZesBlocksDownWoont’ (normal words, but 3 different languages) is far more effective than the not so random ‘qwerty123’, especially if you, as a hacker, already know that the password is going to end in the plaintext ‘-facebook’. (and it is easy to remember). As with anything, but especially in cryptoanalysis, if you already know what you are looking for, it is easier to find it.

Coming back to the 3 language 10 words password, it is 46 characters, let’s assume we only use lowercase, that would be 26^42 combinations. Being able to use uppercase makes it 52^42, include numbers, 62^42, giving a resolution of 1.9074403212938070052188251342723e+75 possible combinations.

With this I’d also advice to look at how the password is used. Yes, the iphone number password is actually quite safe, BUT ONLY if you turned on the feature to wipe the phone after 10 misses. If you don’t, it’s just 10000 tries in which case brute force works. And quickly too. Even the hardware of the iphone you are trying to crack is much faster in 0-10000 than you are. Don’t forget, the computing power in your pocket supersedes in many magnitudes the computing power that was used to put a man on the moon.

Don’t underestimate brute force, as a rule, it takes only 1/2 to crack it. Either they get it right at ‘A’ or at the end at ‘ZZZZZZZZZZZ’, on average it is half and brute force is actually one of the ‘cracking algorithms’ that is 100% sure to crack any code, unless it is accompanied by a total wipeout, as the iphone offers. Use it. Objects that completely lock after X tries are much safer than object that use whatever amount of gigabytes for keys. Imagine what luck you need to crack a safe if you have the previously amount of options (1.9074403212938070052188251342723e+75) with only 10 tries. Brute force is completely useless against systems that lock.

But, it’s not completely useless. If it’s a digital safe? it can be copied. You may lock after 10 tries, but if I can make 1.9074403212938070052188251342723e+75 copies, I only need to try 1 combination per copy. So what do you learn from this? If someone wants to crack you, and if they have enough resources, they can and will. The safest place to keep really private information is still locked in your brain. You will never be secure if your brain is not safe.

As per today, 25/04/2012, they haven’t found a way to secure anything that was saved in your brain and as long as you keep it there, it can’t be protected by security

T is for Telecom, where communication goes wrong…

It’s a wonderful day in the world of telecommunications… First, the 3G service on my phone went dead (it still showed wonderful connection, but as soon as you tried anything it said I didn’t have cellular data). Since I recently moved from Vodafone to Virgin Mobile who uses Optus, I thought, how bad can it be. But hey, after a few tests with luckily another phone at hand, it obviously showed that there is probably one flag not set correctly at their end. We can only hope that the morning crew is able to set the flag.

So that one is still on-going. The other problem I have is with Telstra (the fourth telco to mention in this post, however, the biggest here). Anyway, I updated my subscription with them, because, well, hey, after 2 years, times change, you can probably get a better deal. So I first started to use the DIY way via the website.

Since that quickly enough proved not viable, due to the exact combination of switches I wanted, I followed the advice and started a chat session. I really had some fun with a great guy on the other hand and after about 30 minutes we arrived at a new package for the bundle (phone, internet, tv). I would be called the next morning to arrange for the installation guy to do the physical part of the deal (installing the HD box and moving the non-HD box to the second room).

So I waited about a week. Obviously, nobody called. But since there is a store for anything, there are also stores for Telstra. The next week (last week) I go to the T-store and apparently, my previous order could not be found. I think, well, while I’m here, lets do it again. This time however, I also get a T-hub (Telstra’s take on a tablet, connected to your base station etc) thrown in the deal. Who am I to say no to a better deal, so I go home, thinking to have the same order, just this time with some new gadgets for the home.

After installing the T-hub, the base-station and 2 handsets, I start to play around with the new toys and decide to enable sms. Why not. However, to enable that, I first had to enable something else, which I couldn’t enable since it was already enabled (let’s call it voicemail). So, as the device instructed me, I called the helpdesk. Again, easy-peasy, no problemo and the issue was quickly resolved. Except for the fact that the activation code was expired. But, there was a link in the activation email that would allow me to generate a new activation code at any time.

Today I tried to generate that activation code (as my evening was already ruined because of the trouble with the 3G on the mobile phone), I click that link to find that the website is not exactly working as it should. Actually, somewhere halfway, the process advised me to call the corresponding helpdesk (Telstra has many).

Calling the T-Hub helpdesk is not so bad, apparently, not many people do that, so I got connected quickly enough (around 8.45pm). During the conversation, I was asked to install LogMeIn and even though I do know better in most of the cases, I was easy going and a nice customer, so I let them control my Mac for a while, until they discovered that a certain part of the website was not working. (Yes, the same link to get a new activation code)

That kind of brought the nice lady at the other end of the line to the end of her flowchart and the incident was logged and over the next few days, someone will contact me to activate the sms service on the T-Hub (I hope, but I should know better). However, to log the incident, she needed the serial number on the T-hub, which is conveniently stored inside the battery compartment. (note to reader: store this in mind, it will come back later…). So I remove the batter, read the serial number (quite long, but hey, we got through it) and that was about it.

“Anything else I can help you with”, she asks. Sure, why not, while we’re here (9.15pm), I kind of ordered something with you guys about 2 weeks ago, and again a week ago and I was to be contacted within 24 hours, but hey, they kind of didn’t. But, since she was the T-hub helpdesk, no can do. I get put back in hold, this time for the Billing helpdesk.

Billing is a bigger problem as it took a tad bit longer to finally get put through. Yay! I explain my quest (2 weeks ago via chat, last week via the store, no confirmation, no contact, no email, no nothing). She starts up the system after I’ve identified myself (again) and she can see both orders. However, she sees differences in the packages created by both colleagues (who both came to the same final price though, so how that happens, you tell me).

Since I now clearly know what I want and what it will cost me, we can go quickly through the changes and she decides that it is probably best to cancel both previous orders (sure, but, wouldn’t it be nice to just let one go through and keep me, well, informed?) and we create a new one (again, exact same price, but totally different bundle with the same components, really…). Only one thing, she can’t finalise it as that is just something the Bundle Team can do. Incident report number 2, reference number whatever, I’ll get a call on Friday.

“Anything else I can do for you?”. (9.45pm) Well, apparently, when I removed the battery from the T-hub, as your colleague asked me to do, the touch screen on the T-hub has become unresponsive (I noticed this because, well, you have to do something during the time you are put on hold). “Let me just connect you to our T-hub helpdesk”

And so, an hour later, I was back full circle with the T-hub helpdesk. Again, the personal details, my phone number, name, age, first 4 digits of my pin and the ccv code, the works, I am identified (ok, that about the pin and ccv is not true, but come on, 3 times during 1 phone call from a landline supplied by Telstra themselves? really?)

Anyway, after first chewing away the legendary question: “Have you tried turning it off and on again” we again get to the point where I have to remove the battery and read out the serial number. (again, remember this!) Reinsert the battery, try again, the works. At some point during this conversation her flowchart also ended and the T-hub is going to be replaced.

To do so, they also need the serial number that is on the base station as well as on the handset that came with it. So I start with the number on the base station and after 3 digits I get this strange feeling that I know this number. With only one exception. Where the T-Hub had a T, the base station has a convenient B. Where the base station had the B, the handset had a C.

Curious as I am, I ask the nice lady: “Wouldn’t it have been easier for me, instead of removing the battery from the T-hub, simply to lift up the base station and read that serial number?”. “Yes, they are the same, except that T stands for T-hub, B for base station and C for Communicator”…

“So, basically, strictly hypothetical, since it is too late anyway, I could have told the first person the serial number, which is printed on the outside of the base station and she could have concluded the serial number of the T-hub without me having to remove the battery and consequently ruining the device’s touchscreen?”

“Yes, when we replace them, we have to replace all 3”. Anyway, I now have a 3rd incident number and they will send me a replacement set. (it’s now 10.15pm). But, since I got here, I’m not done yet…

“How about the contact list I have stored in the device? I just had all my contacts in there?” (this is not entirely true, I just had my mobile number in there just to test stuff, we didn’t get around to actually transfer any of our other contacts in the system, but hey, at this point, you got to ask).

“I can give you the number of our technical support team who will help you with that”. I thanked the lady. I’ll go a long way playing innocent customer, but I sure won’t spend another 30 minutes on the phone with the next person to explain to me that I can use the extra handset to store the numbers and transmit them to the new base station, as I had already read the manual.

Let’s just wait and see what Friday brings. It can only get better from here I guess…