Browse Source

Initial commit

Migrated from the old blog, built in Jekyll using the very
same theme. I moved to Hugo since it compiles pages
much faster and it fits my Go ecosystem.
master
Matei-Alexandru Gardus 7 months ago
commit
63fad7a6ad
Signed by: StormFireFox1 <matei@gardus.eu> GPG Key ID: F3D2B830AB9B94AA
52 changed files with 16970 additions and 0 deletions
  1. 46
    0
      .gitignore
  2. 5
    0
      README.md
  3. 10
    0
      archetypes/default.md
  4. 7
    0
      archetypes/posts.md
  5. 34
    0
      config.toml
  6. 30
    0
      content/fixed/about.md
  7. 18
    0
      content/fixed/contact.md
  8. 78
    0
      content/fixed/faq.md
  9. 14
    0
      content/post/2018-09-21-welcome.md
  10. 228
    0
      content/post/2018-09-28-adventures-in-privacy.md
  11. 245
    0
      content/post/2018-10-25-working-with-developers.md
  12. 107
    0
      content/post/2018-11-08-solving-a-rubik-cube.md
  13. 120
    0
      content/post/2019-01-20-the-life-stack.md
  14. 197
    0
      content/post/2019-01-30-around-the-world-in-80-hops.md
  15. 8
    0
      layouts/404.html
  16. 31
    0
      layouts/partials/head.html
  17. 41
    0
      layouts/partials/sidebar.html
  18. BIN
      static/assets/apple-touch-icon-precomposed.png
  19. BIN
      static/assets/favicon.ico
  20. BIN
      static/avatar.jpg
  21. 15647
    0
      static/public/doc/SignalEnvelopeDetectorSoundLatchSwitch.svg
  22. 102
    0
      static/public/doc/storm_firefox1.asc
  23. BIN
      static/public/img/JavaStreamRedundantSorted.gif
  24. BIN
      static/public/img/a-linters-nightmare.jpg
  25. BIN
      static/public/img/activitywatch-report.jpg
  26. BIN
      static/public/img/amazing-marvin.jpg
  27. BIN
      static/public/img/cronometer-daily-entry.jpg
  28. BIN
      static/public/img/cstimer-website-screencap.jpg
  29. BIN
      static/public/img/digispark-hid-source.jpg
  30. BIN
      static/public/img/digispark-purchase.jpg
  31. BIN
      static/public/img/edgerouter-4.jpg
  32. BIN
      static/public/img/gan-air-sm.jpg
  33. BIN
      static/public/img/git-workflow-example.jpg
  34. BIN
      static/public/img/godoc-vianuedu-example.jpg
  35. BIN
      static/public/img/google-archive-screencap.jpg
  36. BIN
      static/public/img/google-takeout-page.jpg
  37. BIN
      static/public/img/javadoc-vianuedu-example.jpg
  38. BIN
      static/public/img/keepass-2-screencap.png
  39. BIN
      static/public/img/me-finding-yubikeys.jpg
  40. BIN
      static/public/img/my-best-cubing-time.jpg
  41. BIN
      static/public/img/my-yubikeys.jpg
  42. BIN
      static/public/img/no-documentation-example.jpg
  43. BIN
      static/public/img/rubiks-cube-2.0.jpg
  44. BIN
      static/public/img/some-documentation-example.jpg
  45. BIN
      static/public/img/sweet-github-badge.jpg
  46. BIN
      static/public/img/twisty-timer-graph.jpg
  47. BIN
      static/public/img/vianuedu-git-network.jpg
  48. BIN
      static/public/img/vianuedu-total-warnings.jpg
  49. BIN
      static/public/img/vpn-representation.jpg
  50. BIN
      static/public/img/yubikey-gpg-pin-entry.jpg
  51. 1
    0
      themes/lanyon-hugo
  52. 1
    0
      themes/m10c

+ 46
- 0
.gitignore View File

@@ -0,0 +1,46 @@
# Created by https://www.gitignore.io/api/go,hugo,visualstudiocode
# Edit at https://www.gitignore.io/?templates=go,hugo,visualstudiocode

### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

### Go Patch ###
/vendor/
/Godeps/

### Hugo ###
# gitginore template for Hugo projects
# website: https://gohugo.io

# generated files by hugo
/public/
/resources/_gen/

# executable may be added to repository
hugo.exe
hugo.darwin
hugo.linux

### VisualStudioCode ###
.vscode/*
.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

### VisualStudioCode Patch ###
# Ignore all local history of files
.history

# End of https://www.gitignore.io/api/go,hugo,visualstudiocode

+ 5
- 0
README.md View File

@@ -0,0 +1,5 @@
# A Procrastinator's Refuge

Welcome to the Git repository for "A Procrastinator's Refuge", my blog.

The site is built using the [Hugo](https://gohugo.io) static site generator and it uses the [Lanyon](https://github.com/tummychow/lanyon-hugo) theme.

+ 10
- 0
archetypes/default.md View File

@@ -0,0 +1,10 @@
+++
title = "{{ replace .TranslationBaseName "-" " " | title }}"
date = {{ .Date }}
draft = true
sidebar = false
weight = 0
tags = []
categories = []
+++


+ 7
- 0
archetypes/posts.md View File

@@ -0,0 +1,7 @@
+++
title = "{{ replace .TranslationBaseName "-" " " | title }}"
date = {{ .Date }}
draft = true
tags = []
categories = []
+++

+ 34
- 0
config.toml View File

@@ -0,0 +1,34 @@
baseURL = "https://blog.stormhub.io"
title = "A Procrastinator's Refuge"
themesDir = "themes/"
contentDir = "content/"
publishDir = "public/"
theme = "lanyon-hugo"

builddrafts = false

paginate = 1
canonifyurls = true
[permalinks]
post = ":year/:month/:day/:title"
fixed = ":title/"

pygmentsuseclasses = true

[params]
title = "A Procrastinator's Refuge"
tagline = "A complete diary"
author = "Matei-Alexandru Gardus"
description = "Coder. Hardware enthusiast. Procrastinator. Here are my adventures in wasting time (or not, I don't know)."
[params.github]
url = "https://git.stormhub.io/StormFireFox1/Refuge"
head = "master"
[[params.social]]
name = "github"
url = "https://github.com/gohugoio"
[[params.social]]
name = "twitter"
url = "https://twitter.com/gohugoio"
[[params.social]]
name = "email"
url = "mailto:matei@gardus.eu"

+ 30
- 0
content/fixed/about.md View File

@@ -0,0 +1,30 @@
+++
title = "About Me"
slug = "about"
date = 2019-02-10T13:01:04+02:00
draft = false
sidebar = true
weight = 1
+++

I'm Matei-Alexandru Gardus. I am a student at "Tudor Vianu" National Computer Science High School, and I have been taking a shot at computer science for a while now. I like coding various gadgets and gizmos for myself, friends or even freelance around with close friends.

I'm a master procrastinator at heart, as this blog suggests. However, I like to consider myself a *productive* procrastinator. In other words, I like to do something related to a topic as a procrastinating activity.

A few examples:

* Got a project from school for CS? Never mind that, I'll read a book on machine learning.
* A friend asked me to make him a Rasperry Pi for push notifications? Oh yeah, no homework for three days!

You get the idea.

Currently I have two big side-projects I'm working on:

* A website to manage the class fund written in Java (I need to learn to write servers in the Java ecosystem, but it's pain)
* A journal of my journey throughout all of the programming languages I've ever used in my life, *HelloWorld*. You can check it out on [GitHub](https://github.com/StormFireFox1/HelloWorld).

Wanna stalk me on social media? I'm not too present there, but I do have a few accounts on some websites. Check out the [Contact](/contact) page.

Wanna know even more about me? Check out the [FAQ](/faq).

This site was built with the m10c theme. You can check it out [here](https://github.com/vaga/hugo-theme-m10c).

+ 18
- 0
content/fixed/contact.md View File

@@ -0,0 +1,18 @@
+++
title = "Contact"
date = 2019-02-10T13:37:14+02:00
draft = false
sidebar = true
weight = 2
tags = ["meta", "contact"]
categories = ["Meta"]
+++

So, you'd like to keep in touch with me? Yay, new friend! Ok, uhh...

I have a [Twitter](https://twitter.com/Storm_FireFox1) account, so I guess that's one.
I also have an [e-mail](mailto:matei@gardus.eu), so that's one as well.

If you're a security nut, I guess you could use [this](/public/doc/storm_firefox1.asc) GPG public key. (ID `AB9B94AA`, Fingerprint `CFD7 5724 2CA6 6E85 F96B 3CDA F3D2 B830 AB9B 94AA`) You could also get the public key from the GPG keyservers, just use the ID above.

Other than that, I'm sure I'll add what more I have as time goes by. If you want my phone number, just e-mail me.

+ 78
- 0
content/fixed/faq.md View File

@@ -0,0 +1,78 @@
+++
title = "FAQ"
date = 2019-02-10T13:41:36+02:00
draft = false
sidebar = true
weight = 3
tags = ["meta", "faq"]
categories = ["Meta"]
+++

Ok, let's just get into it!

# The Refuge

## Why did you get a blog?

I really like helping others, and I have had many people ask me what I'm working on when it comes to side-projects. I also needed a place to sink a lot
of my time in and an excuse to procrastinate. Hence the inspiration for the name of this blog. And since all these things blended together in a blog,
I thought it would be best to just quickly make one! And boy, was it quick. Thank god for static site generators!

## What will you write in here?

I will write about anything on this blog, with one condition: if it's something I'm doing to avoid doing anything else.

## How often will you post?

Honestly, I don't think I'll have a legitimate schedule, which is why I recommend you subscribe to my [RSS feed](../post/index.xml) to find out when I publish
something new on my blog. If you don't know what they are, they're a pretty old, but awesome piece of tech - check out a small introduction
[here](https://www.youneedfeeds.com/).

## What if I have some questions to ask you?

I'm thinking of integrating comments in this blog, but I'll see when I get the time. Until then, just contact me directly one way or the other.

---

# Stuff about me

## How did you start getting into computer science?

I honestly don't really remember, computers have been a part of my life ever since I was like 5. I guess you could chalk it up to "love by proximity and time".

## What are your favorite programming languages?

My favorite languages are numerous, but my absolute favorites and most used are:
* C++
* Go
* Python
* Java
* Rust

I'm thinking about adding Haskell to that list, but I don't know about that just yet.

## What are your favorite things to do in your free time?

There are a few things up there on my list:

* spend time on my side-projects (that was pretty obvious, look around)
* listen to music
* browse Reddit and Hacker News
* filming skits with the boys
* filming stuff with my drone (his name is Batwing)

## Can we get familiar?

Sure we could! Hit me up with an [e-mail](mailto:matei@gardus.eu)!

# Wait, I know that profile picture!

Quite correct, the profile picture is not of my creation. Good catch!

For those unaware, that is the logo of SIVA, a nanovirus that debuts in the game Destiny, in the Rise of Iron expansion. Its Wikipedia entry reads:

> SIVA was once a Golden Age breakthrough in self-assembling, self-replicating nanotechnology, created by Clovis Bray to accelerate humanity's colonization effort. The technology had the ability to create nearly anything that anyone could ever need. It would be used to create new structures and colonies on new worlds faster than regular construction methods. It was considered as an amazing breakthrough in technology.

I consider a technology like SIVA's initial design a dream that humanity would definitely want to achieve. However, as you can probably imagine, SIVA
obviously didn't end up as intended in the game. Most of my projects are just random creations, much to the dismay of those around me. And since SIVA
is pretty much a creator of random things in the game, I (currently) identify with its intentions :)

+ 14
- 0
content/post/2018-09-21-welcome.md View File

@@ -0,0 +1,14 @@
+++
title = "Welcome"
date = 2018-09-21T12:00:00+02:00
draft = false
weight = 0
tags = ["meta"]
categories = ["Meta"]
+++

# Welcome to A Procrastinator's Refuge!

>Procrastination is defined as the avoidance of doing a task that needs to be accomplished. It could be further stated as a habitual/intentional delay of starting or finishing a task despite its negative consequences.

I like to think that that definition fits me, but in a weird little way. I have to do two things at the same time, *at all times*. As such, I commonly look like I procrastinate even though you could say I don't. In this blog, you'll find my various thoughts on whatever topic I have at hand, probably a side-project. Enjoy!

+ 228
- 0
content/post/2018-09-28-adventures-in-privacy.md View File

@@ -0,0 +1,228 @@
+++
title = "Adventures in Privacy - Part 1: Keys everywhere!"
date = 2018-09-28T10:30:00+02:00
draft = false
weight = 0
tags = ["gpg", "software", "tools"]
categories = ["Privacy"]
+++

Ever since the huge [Equifax breach](https://www.theguardian.com/us-news/2017/sep/07/equifax-credit-breach-hack-social-security)
that pretty much spooked the living crap out of over 100 million people in the United States, I have been acutely aware of anything
regarding privacy. It has long been a known fact that corporations not only
[poorly protect our data](https://news.ycombinator.com/item?id=15395946), but also sell all of our information to third parties,
for usages such as [ad targeting](https://mashable.com/2018/02/14/facebook-spam-2fa/). However, if this happens, there is no limit
to what other data corporations may have on us and sell to others, even personally identifiable information, like private conversations
or the places we visit. Even though I am most likely unaffected by most of the aforementioned breaches, I am still rather annoyed that
a company this large and important could be this careless with people's information. As such, since companies can't be bothered to
protect my data, I'll do it myself.

Now, naturally, as you can probably imagine, when I finally had another side-project to do, I instantly took it upon myself to
procrastinate *as much as humanly possible*. And since school had nothing stimulating at the time (except do everyone else's
homework), it was the perfect opportunity to start securing my life.

So, what do we deal with first?

---

# Passwords

By far the easiest thing to take control of are your own passwords. Commonly, people use Firefox's [Password Manager](https://support.mozilla.org/en-US/kb/password-manager-remember-delete-change-and-import)
or Google Chrome's not so safe [alternative](https://support.google.com/chrome/answer/95606), which are easily integrated
in the browsers to keep your life "secure". While I don't personally blame you for using these, I can assure you that
Google gets all of your password information for all your accounts. If you don't believe me, allow me to present to you
Google Takeout.

![A screenshot of the Google Takeout web page.](/public/img/google-takeout-page.jpg)

Google Takeout is a rather useful (and ethical) service that Google offers in order for you to request a backup for all of the
data that you Google account possesses, from YouTube subscriptions to Google Drive files.

![The archive is fucking massive, 38GB for my measly little Google account!](/public/img/google-archive-screencap.jpg)
> Holy shit, 38GB! That's massive!

This way you can get all the information that Google has on you, while also getting some nice organized files to boot! For instance,
I used this service to create vCard files of all my Google contacts to import in my personal e-mail client, Thunderbird
(if you don't like Outlook and your browser's slow, [check it out](https://www.thunderbird.net)). Lo and behold, right there you can
find all your sweet password information that Google has on you. (More specifically, in the "Chrome" folder, under AutoFill)

There are many ways to store your passwords locally and securely, and by far the two most popular ones are [KeePass](https://keepass.info/) for Windows and
[pass](https://www.passwordstore.org/) for Linux. Both are really powerful, but different in functionality. KeePass uses a .kdbx file that contains all the
passwords, while "pass" just has a Git repository containing GPG-encrypted files. I personally use KeePass since it also has some cross-platform
functionality, such as [Keepass2Android](https://play.google.com/store/apps/details?id=keepass2android.keepass2android&hl=en) for Android and
[MyKeePass](https://itunes.apple.com/us/app/minikeepass/id451661808?mt=8) for iPhone.

![A screencap of the KeePass interface. Not mine, but I won't show that one!](/public/img/keepass-2-screencap.png)

Both work surprisingly well and allow for some pretty neat features. "pass" just has a text-file, so you can write whatever you want with it, which is
very flexible, and KeePass has many features such as auto-expiring keys, URL entries, auto-typing etc.

So now, I have all my passwords locally saved, safely locked. However, my master password was 256 characters long, something I couldn't remember. Now I couldn't
just have a plain text file going around with my password. So I had to improvise...

## A little detour from passwords to DigiSparks

> The easiest way to remember a password is to have some other device remember it for you.
>
> -Me, when too lazy to remember a password

I mean, I had a point. But not too much of one. In hindsight, it would've been better if I just never did this, but you never know.
I very quickly had my eyes set on a particular device that could solved my problem, called [DigiSpark](http://digistump.com/products/1).
A DigiSpark is a little ATTiny85 circuit with a USB on it that you can program just like an Arduino. It's *super cheap* (just $8) and you can use
for some pretty fun stuff. For instance, you can program it to act like a Human Interface Device, which can *send keystrokes to the computer*. You can
*script a specific string of characters for the DigiSpark to send to a computer* on demand. Sound familiar?

And they're just 8 bucks...uuhhh...

![Buy!](/public/img/digispark-purchase.jpg)
> Instant buy!

Yeah, I got two. I'm filthy rich, deal with it. Anyway, I quickly programmed them to quickly output the 256-character master password on any computer after
plugged in for 3 seconds. Put in, pull out, logged in. Easy enough for cheap, right?

![This is me coding both, I kept one for backup.](/public/img/digispark-hid-source.jpg)

And up top you have the source code, which you would find anyway under "File" > "Examples" > "DigiSpark" > "Keyboard".

So now that's done. What next can I secure?

---

# Encrypting files

Well, this ain't fun.

Let me tell you how fun it is to try and keep all your files encrypted safely (it's not).
In fact, it's *so* fun that I literally quit procrastinating on that.
Nah, just kidding, why would I do that?

Anyway, I wanted to encrypt some files because I had a few surprises I didn't want anyone to see beforehand, particularly some birthday cards.
After that, I started realizing the full value of keeping your files safe. It's much like keeping your files on the cloud, but far less likelihood
of someone stealing your information, which is always good.

The best way to encrypt files, by far, is to keep them encrypted where they always stay in anyway, and the solution to that problem is GPG.

## GPG

GNU Privacy Guard is known to be the top free open-source program for encrypting and decrypting files for either storage or e-mail communication.

If you don't know how GPG works, it's pretty simple. Essentially, there are two files that you have GPG:
- a private key, that you keep to yourself and use to decrypt or sign files, e-mails, etc.
- a public key, that you share with others and use to encrypt or verify files, e-mails, etc.

You need both to have a *GPG keypair*, but you **don't share the private key with anyone!** Once you have both, you can use them to encrypt and decrypt files,
e-mails or just short messages, maybe even streams of data! The concept essentially works using asymmetric encryption, which is generated when creating the keypair. Using GPG is simple, but configuring it is the hard part. So, let's get started on that!

### Configuration hell

First off, I had to make some keys. Now there are *too many* tutorials online on how to do that, but by far the best one (and the one I used) is
[this one](https://www.digitalocean.com/community/tutorials/how-to-use-gpg-to-encrypt-and-sign-messages). However, the tutorial does not have an
alternative for Windows. To get GPG for Windows, you'll need [GPG4Win](https://www.gpg4win.org/) (very original name). After the installation
process, both versions of GPG are pretty much the same, except for maybe filepaths.

When you finish generating your keypair, you'll get a nice little key with a key ID. Note that down, you'll need it. It's a 8-character string, like mine:

`AB9B94AA`

After that, I also added a passphrase of 64 characters, with these commands:

```bash
~$ gpg --edit-key [KEY ID HERE]
gpg> passwd

# Add password here

gpg> save
```

I (obviously, because why not) kept the passphrase in the password database (I realized later that
might be a bad idea, but I'll fix that later, don't worry).

Now this worked for quite a while, and I would either use GPG4Win's UI, Kleopatra, to encrypt keys, or use the command-line (the superior choice):

```bash
~$ gpg --output someDocument.gpg --encrypt \
--recipient [YOUR E-MAIL HERE] \
someDocument.docx
```

I also put my public key on the MIT PGP keyserver, so that anyone can download and use it if they want to send me something.
```bash
~$ gpg --keyserver pgp.mit.edu --send-key [YOUR E-MAIL HERE]
```

If I wanted to send encrypted documents to others, I'd use their recipient e-mail address, provided my GPG installation has their public key in the
keyring. You need to ask your friend for it, and you can either get it from a keyserver like this:

```bash
~$ gpg --keyserver pgp.mit.edu --recv [THE KEY ID YOU WANT HERE]
```

Or just get it from a public keyfile they might have sent you, like this:
```bash
~$ gpg --import publicKey.asc
```

Make sure to backup all of your important keys somewhere safe:
```bash
gpg -a --export [YOUR KEY ID HERE] > my-public-gpg.key
gpg -a --export-secret-keys [YOUR KEY ID HERE] > my-secret-gpg.key
gpg --export-ownertrust > my-ownertrust-gpg.txt
```

Once you got the basics down, you're pretty much set!

So, now I'm done with that. I need something else to waste my time with. Uh, let's see...

Hold up, I need a Google search.

![True story.](/public/img/me-finding-yubikeys.jpg)

Oh, nice! Let's get them!

---

# Security keys

The pinnacle of online security: a physical security key!

A security key can be used to lock many different service behind a physical device that you keep on you. There are many DIY versions of this
(technically my DigiSparks are a kind of security key), but by far the most reliable and popular are the [YubiKeys](https://www.yubico.com/product/yubikey-5-nfc/).
I personally bought the Yubikey 4 and YubiKey NEO, since I wanted one to use for my phone and one for the computer as backup. I know, they're not
Series 5, but I bought them before those were released by 3 days. Just my luck.

![Here they are. They're kinda high-tech.](/public/img/my-yubikeys.jpg)

Now, the YubiKeys can be used for a ton of stuff. They support FIDO U2F, so you can use them to have 2-factor authentication for Google, Twitter,
Facebook, GitHub, Dropbox, etc. This is already pretty useful instead of typing the same codes all the time, right? Additionally, they can store
different security standards for other programs, including GPG and KeePass ;)

So you can guess what comes next...

## Integrating YubiKey 4 with GPG

This is obviously pretty annoying and hard, so I won't pad this article much more. A good tutorial I found is by [@ageis](https://github.com/ageis) and
you can find it [here](https://gist.github.com/ageis/14adc308087859e199912b4c79c4aaa4). It's pretty damn comprehensive, but you need to remember
a few things. YubiKey NEO only supports 2048-bit GPG keys, so if you did those, then you're fine, but if you generated 4096-bit GPG keys (like I did),
then you need to use the YubiKey 4 for that.

After using the GitHub gist above, I can just plug the YubiKey in my computer whenever I use GPG and I get
a sweet prompt for the PIN to use the YubiKey. I just input the PIN, and done!

![It's a cool PIN.](/public/img/yubikey-gpg-pin-entry.jpg)

*And* I get a shiny green "verified" badge on every GitHub commit. Sweet!
But that's a bit more work, which I'll explain in a future blog post, probably.

![Check out that sweet verified badge!](/public/img/sweet-github-badge.jpg)

---

# What next?

There are many things that I still want to do in order to have more privacy and security on the Internet. A few of the next projects will be to:
- get a personal cloud drive
- integrate my devices with push notifications between each other
- ...who knows what else?

I hope you enjoyed my little trip through needless additional encryption of my life. If you want any help with the items above, just [contact](/contact) me.

+ 245
- 0
content/post/2018-10-25-working-with-developers.md View File

@@ -0,0 +1,245 @@
+++
title = "Coding With Others Is Hard"
date = 2018-10-25T11:47:00+02:00
draft = false
weight = 0
tags = ["development", "stories", "intellij", "java", "coding", "practices", "git"]
categories = ["Development"]
+++

> "If it ain't broke, don't fix it. And trust me, you'd code it worse without me!"
>
> -Chad, a fellow coder

I've coded a decent amount of things in my life, and to be honest, it's been fun. The freedom and the feeling you get when
you code a program to do your bidding is addicting. It feels as if you're a blacksmith, smelting the raw ore of standard
libraries and algorithms and casting it into a mold of your design, to create a tool or weapon for the task at hand. And
when you're alone, you have complete freedom of the mold. But alas, *we are all only human*. We can't do everything alone,
we need company. So imagine my surprise when, as soon as I had this realization, an opportunity arose.

---

# A commission

For the purposes of privacy, I'll keep everyone's name as secret as I can in this post. Last year, one of the teachers at
my school approached me with a little project: an educational software for the school, in order for said teacher to use to
quickly and efficiently administer tests to her students on computers at any time, anywhere. I agreed, under the pretense that
I'd learn how to code something of this scale. That was more of a secondary reason, I wanted to procrastinate! **Wahoo!**

I dubbed the project [VianuEdu](http://vianuedu.lbi.ro) in the idea that it would perhaps end up used by the whole school, not
just the teacher mentioned before. You can find the source code for it [here](https://github.com/CNITV/VianuEdu) to follow along
with my story. It's written in Java, along with a [server](https://github.com/CNITV/VianuEdu-Server) written in Go, which is
entirely written by me. I picked Java because it was the quickest way to get a cross-platform GUI native program running without
much of a hassle or making a website instead. I picked Go for the server because I wanted to try the language out with a nice
server and make something new and exciting.

---

# This is where the *fun* begins (ha)

Obviously, I realized a true educational software for the purposes that my teacher asked for was not something I could do alone, so
I decided to take someone else along for the ride. Now the recruit very specifically asked I don't mention his name in this post, so I'll
just call him Chad, even though he isn't one.

Chad was a relatively passionate graphic designer, so I thought he would be fun to tag along to help with the client side of VianuEdu,
which I was certain I'd screw up since I suck at designing UIs. He also had some experience coding Java GUIs (at least according to him)
so I thought he'd be a good addition. It started off pretty well, he was eager to work, and I was excited to work together with others.

I started explaining to him the goals of the project, what he should do, started splitting our tasks, etc. and he agreed with most of
what I gave him. I coded the backend (the server and the database handler) and he coded the frontend (UI and some small amounts of data
handling). That was the plan. Soon, the plan instantly fell to pieces when I asked him:

> "Hey, do you know Git?"

You know what he said?

> "What's Git?"

---

# ...

It is absolutely insane how many developers have worked on projects and have never used at least one type of version control. There is so
many: [Git](https://git-scm.com/), [Subversion](https://subversion.apache.org/), [Mercurial](https://www.mercurial-scm.org/) and all of
them are immensely useful (the most used one is Git, though) and are *critical* for an easier developer workflow. Git's branching features
and the ability to maintain commit history is crucial for whenever a developer messes up and they *will* mess up. And then Chad asks what
Git is.

I was wrong before, *this* is where the fun begins.

I soon came to the realization that Chad didn't have an idea of what it meant to work with other people. In hindsight, I didn't either, but
I was at least willing to research the matter beforehand. I made a few notes, set up some foundations for ease of use, like Git and a style
guide, and so on. But he just assumed we'd be fine.

In the end, I had to teach Chad everything he would have to know to properly code with others, now and in the future.

We started off nice and simple.

---

# Git

> Git is a free and open source distributed version control system designed to handle everything from small to very large projects
> with speed and efficiency.
>
> Git is easy to learn and has a tiny footprint with lightning fast performance. It outclasses SCM tools like Subversion,
> CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.
>
> -[https://git-scm.com](https://git-scm.com)

![An example of a Git repository workflow.](/public/img/git-workflow-example.jpg)

That description might be very difficult to grasp. But the concept of Git is pretty simple.

Picture a text file you're working on that contains a playlist you have on your phone. You can use Git to not only save
the current version of the text file, you can use it to:

* experiment with different versions of the same playlist and never lose the original one
* review previous versions of the playlist
* work on two versions of the same playlist separately
* revert to a previous version of the playlist if the current one is bad or you accidentally deleted some songs
* do the same thing while more people work on the playlist

Git essentially holds in its special folder ".git" all the changes you make to files and keeps them in *commits* (a change to the project)
and *branches* (different workspaces for the same project). Git is pretty damn important to work with in a multi-developer environment since
it is the easiest way to manage lots of code without breaking any of the code you already have.

A very sweet tutorial for Git would be [the one I used](https://www.atlassian.com/git) from Atlassian, and there is another pretty good one
from GitHub, which you can find [here](https://try.github.io/).

Once I gave the same resources to Chad, he reluctantly ended up agreeing to use them, but even though Chad read most of the tutorials,
he still didn't use Git to its full advantage.

![Notice how the network has literally no branches now, since I quit making them](/public/img/vianuedu-git-network.jpg)

As you can tell, we eventually reached the point where branches were non-existent (notice the black "master" branch being the only one that
appears towards the end) simply because Chad found it difficult to collaborate with me if we worked on different branches.

Alas, that was the least of my problems.

---

# Documentation

By far the most important thing to do when working with others is to write documentation for your code. Documentation allows for you to not
only clear your mind by explaining what your code does, but also help other coders, now or in the future, to understand your code. This is
crucial when working with other fellow coders since you'll be working on a *lot* of code, and it will be inevitable that you eventually
forget what you did. Documentation refreshes your memory and makes it easier for you to see what a function does.

Many languages have different ways of dealing with documentation. Java, for instance, reads specific types of comments called JavaDoc comments
and can automatically generate HTML pages of documentation for your project! VianuEdu's JavaDoc can be found [here](http://vianuedu.lbi.ro/docs/).

JavaDoc comments look something like this:

![This is what the Student constructor's JavaDoc looks like.](/public/img/javadoc-vianuedu-example.jpg)

They contain information about the method (that's a constructor), the parameters, and perhaps even more, such as exceptions, or some other stuff.
A good JavaDoc comment allows for everyone to understand what a function does, and JavaDoc comments should accompany every method, every variable
to help anyone else understand what is happening in the code they have in front of them.

I like to think my code for the project was relatively well documented, what with every method having documentation, including internal ones, such
as this one:

![This is what a Godoc comment looks like.](/public/img/godoc-vianuedu-example.jpg)

The Godoc comment at the top of the method allows for the Go toolchain to automatically generate documentation as well, much like JavaDoc does.
You can find the generated documentation for the server of VianuEdu [here](https://godoc.org/github.com/CNITV/VianuEdu-Server).
And as you can see, I thoroughly documented my code. In fact, I can assure you that all of it is documented, at least on the server side.

Compare that with fellow Chad's code:

![I'm fucking screwed.](/public/img/no-documentation-example.jpg)

His code has almost *no* documentation at all. And if there is any documentation, it doesn't really explain anything. It's mostly just added there
so that I can stop annoying him:

![Here's some documentation.](/public/img/some-documentation-example.jpg)

Yeah, no shit, I figured that out by myself, it's literally in the method's name!

Anyway, this has rendered Chad's code unmaintainable, not only by me, but even by himself, since not even *he* remembers what he wrote in some
sleepless night with 3 pots of coffee desperately chugged.

Of course, this wasn't even the bad news' final form!

---

# Linter warnings

When I started the project, I urged Chad to use the IntelliJ IDEA IDE to work on our project. It's a pretty damn good IDE that I wholly
recommend you use when working on big Java projects. The reason why I urged him to use it is because it comes with an automatic linter
built in with some relatively sane defaults. It makes sure your code is idiomatic and also comes with its own improvements to perhaps
other perfectly fine code. It's a good thing to have, especially when it brings up some awesome little improvements, like lambda replacements
or even stream API linting:

![An example of the linter in IntelliJ Java IDE.](/public/img/JavaStreamRedundantSorted.gif)

This one in particular is straight from the IntelliJ website's ["What's New"](https://www.jetbrains.com/idea/whatsnew/#v2018-2-java) section.

Now I told Chad all about IntelliJ's features and that he should use them. He said he would.

I was wrong to believe him.

After about a month of work, I decided to check up on his side of the code and see what it looked like, see if he followed my advice:

![He didn't.](/public/img/a-linters-nightmare.jpg)
He didn't.

See that? That's IntelliJ's scrollbar. It shows you the warnings in yellow from the current file, for you to conveniently find and fix them.
Chad's scrollbar was ***piss yellow.***

The grey parts of the scrollbar also shows you duplicate code, for you to refactor and put in a little function to call later.
Literally 25% of one of his source files was duplicate code. Now *that* is an achievement.
In total, Chad had 51 instances of duplicate code and 875 typos. Now the typos kind of don't count, primarily because Romanian isn't a default
language for IntelliJ and also because Chad didn't use camelCase variable naming, which is needed if you want IntelliJ to read typos right.
However, none of that saves him.

He had ***918 warnings***, 55 of which were probable bugs, and 532 of which were declaration redundancies!

![This is chaos.](/public/img/vianuedu-total-warnings.jpg)
This is chaos.

But wait! There's more!

When I asked him to fix all the warnings as the final brush-up on our project, you know what he said?

> "If it ain't broke, don't fix it. And trust me, you'd code it worse without me!"

---

# The End of the Journey

In the end, I finished my parts of the project and we released version 1.0 of VianuEdu. It was fine, it worked, albeit with a few GUI bugs we ironed
out pretty quick (I wonder why there were any, Chad. Maybe the warnings were trying to tell you something). However, the experience taught me many things.

A lot of people are unaware of how to write clean code and also help others in the process of coding together with them. And you know why?

**Because coding with others is hard.**

When you're alone, you can do whatever you want, no one judges you, you are free to write code in any way you like. But we are rarely truly alone when coding.
You never know when you want someone new to join your project or when you have to join someone else's project. You'd want to have the easiest time learning
the new codebase, right? Well, that doesn't happen just like that. You need to work in order to make your code accessible, easy to read, easy to refactor
and modify.

I'll admit that I did some wrongs in my project as well. We didn't spend time training on using the IDE, I didn't stay with Chad for a while to make sure
he uses IntelliJ to the fullest extent, and I also didn't take too much time to teach him Git, I just handed him some websites to read (much like I did with
you), but the truth in the end is the same.

Learning to code with others is not easy, but it can be done. You have to:

- write **clean code**
- use **proper version control**
- have **good documentation**
- adhere to the project's **style guide**
- have a common **linter configuration** to reduce warnings, errors and bugs
- **communicate** with your fellow coders

You need to make sure the code is uniform, cohesive, and easy for others to integrate as well. All of these things can be practiced
but all it requires is the will to do so. Make everyone's life easier when coding with others, lest you end up with an unmaintainable codebase. And who knows?
Maybe the person you'll be helping is you in the future, who will be a completely different person and end up hating your own code because you didn't
do it right.

I hope that you will at least learn from my experience and perhaps integrate some of these good practices in your code and development teams as well.

If you need any help to use Git, advice for clean code or just want to ask what else you can do to make coding with others easier, don't hesitate to
[contact](/contact) me with questions.

+ 107
- 0
content/post/2018-11-08-solving-a-rubik-cube.md View File

@@ -0,0 +1,107 @@
+++
title = "Solving a Rubik's Cube is fun!"
date = 2018-11-08T14:12:43+02:00
draft = false
weight = 0
tags = ["Rubik", "cube", "speedcubing"]
categories = ["Entertainment"]
+++

School has started to pick up fairly reasonably, what with all the exams and homework and whatnot, and since work hasn't been
slowing down either, I've found myself with a very sudden need to relax with something other than Reddit and whatever other
time-wasting activity I could find on the web. So guess what? I replaced those with yet *another* time-wasting activity. Except
this one is at least slightly more useful (but still pretty useless in the long run).

---

# Solving the Rubik's Cube

Ever since I saw one of my colleagues in 9th grade solve a Rubik's Cube I've felt pretty bad having to use online solver websites
to solve a Rubik's cube but I've never gotten around to finding the time to learning all the algorithms. Besides, as far as I
was concerned, in the beginning, I thought it would take too long to figure out how to do it.

That is, until I got bored.

Ah, of course, my ultimate motivator! As I was laying in my bed studying for the SATs, I figured *"what better way to solve this lack of motivation than by procrastinating?"*
It didn't take too long until I found something to mess with: my *very old* Rubik's Cube 2.0 straight from the original brand.

![Here it is, although kind of battered.](/public/img/rubiks-cube-2.0.jpg)

As I took it off the stand it resided in for almost 3 years completely untouched, I began turning it around, trying to figure out how
to solve it until I figured it was absolutely useless. I mean, to be honest, I had no idea what I was doing. I figured the best way to
solve it is to actually learn how to solve it from another more reliable source than my haphazard attempt at trial and error.

Meet [CubeSkills](https://cubeskills.com)! Turns out this a training website made by the Rubik's Cube World Champion Felix Zemdegs! I
thought that meant it was good, right? Definitely is. Honestly, I just used the website for free, along with the Training PDFs placed
at your disposal there. I used the Beginner's Method first, because I was a beginner after all.

Guess what? After viewing the videos, I was able to solve the Rubik's Cube in a record time of 6 minutes! Wahoo, I did it! But I wanted
to be faster. *A lot faster.*

---

# Picking up the pace

It didn't take too long for me to decide to keep practicing the Beginner's Method in my spare time. Turns out in just about day, I ended up
consistently hitting around 1 minutes and 10 seconds worth of solve time. At this point, I realized a stopwatch was ruining my chances at
measuring my times, so I decided to get a timer app on my phone and PC. I found one for each respective platform.

For my PC, I found the pretty good [CSTimer](https://cstimer.net), which hosts a ton of features, like solve exporting, stats and some cool themes.
It also works with official speedsolving timers, apparently, so that's pretty cool.

![This is what CSTimer looks like.](/public/img/cstimer-website-screencap.jpg)
> Pretty high-end for a simple timer.

I also use [Twisty Timer](https://play.google.com/store/apps/details?id=com.aricneto.twistytimer) on my Android phone if I don't have my laptop handy,
which happens a lot during rides on the subway. It also comes with a neat graph system to make me feel good about my improving times.

![Nice graph!](/public/img/twisty-timer-graph.jpg)

However, even so, I ended up hitting a dead-end on my times. It was almost as if I was limited by something. Even after learning legitimate CFOP (the general
method of solving a 3x3 Rubik's Cube) with intuitive F2L (**F**irst **2** **L**ayers) and 4LL (**4**-**L**ook **L**ast Layer), my times were still over 1
minute, which should not happen physically, because I was technically faster than before. I then figured out the problem

---

# My cube sucks!

My 3-year-old, *unlubricated* and *chipped* Rubik's Cube 2.0 moved **really** badly. It would lock up on any turn faster than 1 a second, it would have its corners
twist all the time, it was a complete and total mess. Its screws would get loose once every 20 solves as well. It made me incredibly annoyed that I would get bad
times not because of my lack of skill, but because of the cube's incapability to perform. As such, I decided to upgrade.

Honestly, I didn't know what to go to. I wanted the best speedcube I could find on the market, but there were too many choices. Eventually I thought I should buy
the one that most people seem to use, which is the GAN 356 Air SM.

After ordering it from Amazon, waiting for it to arrive, getting my money back, ordering it again from a Romanian shop and waiting an entire month for it, I finally
got it!

![It's beautiful.](/public/img/gan-air-sm.jpg)
> It's beautiful.

Of course, as you can imagine, precisely 3 days after ordering it, the next generation of the cube I got, the GAN 356 X, is released, much like with my YubiKeys.
Every time.

Regardless, the new cube moves beautifully, with no defects. It's smooth, doesn't twist, and now I move even faster than before. In fact, I even beat my old
colleague's personal best, 27 seconds, with my time of 26.69 seconds!

![I'm the best (cuber)...around!](/public/img/my-best-cubing-time.jpg)

---

# What next?

After getting the personal best of 26 seconds, I took a short break from practicing to get back to legitimate work, but I am still cubing to this day. Ever since
my little rushed escapade with cubing, my entire class has been taken by storm by the cubing movement. My friends keep bringing extra cubes at school to have fun
and improve, I've been teaching my friends some new techniques that they might not know, and in addition, we got cubing competitions in my classroom (I keep losing
to one of my colleagues, he's been doing it a lot more than me). Even McDonald's started their Rubik's Happy Meal campaign after me!

In all honesty, this has been incredibly satisfying, but I won't stop now. I'll keep going until I can get times under 10 seconds on solves, and who knows? Maybe I'll
even try more complicated cubes then. I am happy with my new hobby, let's hope it lasts.

Want to try this whole cubing thing out yourself? Want some tips from a complete noob? [PM](/contact) me.

---

*UPDATE (2019-01-07):* Since then, yours truly has managed to be a smart-ass and buy two other cubes, the MoYu Weilong GTS3LM and the GAN 356 X,
so I did get the elusive cube eventually. The MoYu is incredibly nimble, while the GAN X is insanely smooth, much smoother than even the Gan Air
SM. I also improved my time to have an average of 25 seconds and a personal best of 18.64 seconds, so that's great!

+ 120
- 0
content/post/2019-01-20-the-life-stack.md View File

@@ -0,0 +1,120 @@
+++
title = "The L.I.F.E Stack"
date = 2019-01-20T11:30:12+02:00
draft = false
weight = 0
tags = ["life", "stack", "software", "productivity", "tools"]
categories = ["Lifestyle"]
+++

Happy New Year to you all! I certainly hope you all have a great new year filled with productivity and good memories!

Now of course, with the New Year, I always set up some new resolutions that I have always filled ever since I've started assigning
them to myself 5 years ago. This year, I decided to make sure I'd ensure myself a way to always be able to reduce my procrastination.

*Gasp*, I know! What's the point of this place, then?

Believe it or not, I may be a huge procrastinator, but I still enjoy when I actually do a lot of work every couple of days.
It is an amazing feeling to sit down, grind all of my work away off of my to-do list, then sit down on my bed, exhausted,
but satisfied of all the hard work I did that day. Even if this feeling creeps up every once in a while, I still had a hard
time getting into the rhythm of work, and so I needed assistance. Much like Linus Torvalds, I consider tooling to be the solution
to all problems someone may have. I just needed to find the right one...

---

# An idea

There was an idea to improve my life using tools. I was not optimal at taking care of my time and myself sometimes, so
I needed a system. I realized that, to have a good life, one must:

* manage their work and social life equally, and do work in both
* manage their health (particularly fitness, nutrition and sleep)
* manage their time, to make sure you work on what you need to work
* manage the money that they have going into their life and out
* write everything down to remember the current day for years to come (a journal)

This way, I can pretty much guarantee my life to be as managed as possible. Now that I figured this out, I needed a way to get it done
in an efficient way, preferably using some open-source tools. Let's take them down one by one.

---

# Work and social life

The best way to fulfill aspects of both social life and work is to simply compartmentalize each of these into tasks and complete them in
a balanced and efficient manner. For instance, you could take all of those tasks and simply try to alternate between categories. You could
do so with a list of "tasks" and simply take one from each list every time. i.e. Do some work first, chat with someone else second, work on
something else again, and so on and so forth. How did I manage this with tools? Well, you guessed it... a to-do list.

Nothing impressive, but it did wonders for me to be able to differentiate between what I needed to do. At first, I used
[Trello](https://trello.com/), and I used a Kanban-style board to organize my tasks in 5 lists: "Inbox", "To Do", "In Progress", "Done" and "Later".
I found quickly, however, that the little cards weren't good for differentiating the tasks in a way I wanted to. Ergo, I started looking for another
solution.

I tried to use the [todo.txt](http://todotxt.org/) approach for a while, but I quickly found that it was a bit too simplistic for my use, and not
integrated enough with my tools to work really well. I never checked it because I couldn't remember to.
I found quickly that I needed something that could be a bit more complex than a simple todo.txt.
And then I went around on Reddit, finding some posts about a nice little site called [Amazing Marvin](https://amazingmarvin.com). While it's not
open-source, it's absolutely **amazing** because it has many ways to manage my procrastination, particularly its difference between due dates and
"do" dates, which allows you to just schedule whenever you want to complete a task, which is incredibly useful for me, since that is what I always
needed in order to get over my procrastination: just getting started. Now, I know, I know, why would I want to do that? I would end up with no
material for my blog, but I'll find a way to procrastinate in a good way.

![Amazing Marvin, woo!](/public/img/amazing-marvin.jpg)

> "!" means a day procrastinated, so you can see where I'm going with this.

---

# Health

I find it tough to eat right and sleep at the same times during a really busy week, so I think it'd be good to get some alarms, but it'd be a lot
better if I could handle it in a much more min-maxing kind of way. In the end, I settled with two good apps: [Sleep as Android](https://sleep.urbandroid.org/) and
[Cronometer](http://cronometer.com/). Sleep as Android is useful for getting some statistics on sleep and some techniques to wake up quick, such as a two-factor alarm,
which is *awesome*. Cronometer allows you to track your food intake, and it can even suggest what you should eat next. Pretty good stuff.
I just spend around 15 minutes a day to make sure I input all the food into Cronometer and check my sleep, and we're done.

![Cronometer daily entry and stuff.](/public/img/cronometer-daily-entry.jpg)

---

# Time

To be frank, I've found that, even if I'm at my laptop working, I waste time by drifting off on Reddit or YouTube or even working on other things.
So, the best way to handle that is to take the 15 minutes a day I spend inserting food entries in Cronometer and also check on my activity for the day.
This way, I can make sure I'm staying on track with completing all the tasks I have on hand during the day. The best way to do that is with timetables,
and the best automated time-tracking application is [RescueTime](http://rescuetime.com/), but to be frank, it's not open-source and there's been some
data privacy scandals with them, so I went the open-source approach and picked [ActivityWatch](https://github.com/ActivityWatch/activitywatch), which
is essentially local RescueTime on PC, which works quite well. It pulls time entries by reading the active window's title and saving the time spent on it.
At some point I will definitely contribute to the project, since it's quite well-done and the developers need the help.

![ActivityWatch report](/public/img/activitywatch-report.jpg)

---

# Money

Managing my money will be incredibly important, especially when I get to college and I won't have any safety nets, so I need to find a way to track what
goes in and out. The best open-source tool for this is [GNUCash](http://gnucash.org/), which is actually pretty good when it comes to tracking money. While
it is certainly difficult to use at first, the amount of new windows quickly gets processed once you read the User Manual a tiny bit, which helps *a lot* with
understanding how double-entry accounting works, which is essentially how GNUCash works. I really like the way I can also use it to generate customized reports
that can quickly tell me how I'm doing with the allowance I have.

---

# The Journal

I have long since forgot the details of many of my vacations, friends and other people from my childhood simply because my brain couldn't keep all that information
readily available. As such, I've decided that I will make sure that I will never forget another day of my life. How so? By writing it down. I've simply created a
little journal that contains an entry discussing the intricacies of literally every day of my life. I've been writing in it every day since the New Year, and I've
already been remembering a lot more than before!

---

# How's it working?

It's working out amazingly. Now, I have taken control of my life by making sure I'm accountable for every part of it, no matter how small. Every single action I
do is written down, analyzed and improved in order to make me a better and better person. The only thing I need to do is write everything down.

...

But that can wait until tomorrow, you know? ;)

+ 197
- 0
content/post/2019-01-30-around-the-world-in-80-hops.md View File

@@ -0,0 +1,197 @@
+++
title = "Around The World in 80 (VPN) hops"
date = 2019-02-07T11:30:12+02:00
publishDate = 2019-02-20T12:00:00+02:00
draft = false
weight = 0
tags = ["networking", "vpn", "privacy"]
categories = ["Privacy"]
+++

*This is a verbatim copy of the article written for Stempathy, a STEM-oriented teen magazine, with the exact*
*same title. Anything that might seem out of context is most likely explained by reading this article directly*
*from the magazine itself.*

---

Hello everyone! I'm Matei Gardus, a programmer with a knack for side-projects and insane complications
and min-maxing over every aspect of my life. I hope you enjoy this first issue of Stempathy.
Today I'm going to be telling you about one of my ongoing adventures in the world of networking, and it
starts around three years ago.

There was once a time when Netflix wasn't available in Romania, along with all the other streaming services
we've all come to know and love, such as Spotify. However as you can imagine, for a guy like me who knew of
their benefits, I couldn't idly stay being complacent; I wanted to find a way to get all those services in
Romania legally and in an efficient way.
Luckily for me, I had a lead on how to do just that.

---

## A friend

Whenever we get the chance, my family and I go to the United States to not only see new landmarks and get
new experiences, but also to visit my Mon's childhood friend who moved there. Her husband and her are very
nice people and we all enjoy the time when we're there. They welcome us into their home every time we visit,
almost like a home away from the home across the world. Whenever we go there, my father and I also fix whatever
problems they may have with computers, phones and the like, so it makes for a interesting time in that domain
as well (my most interesting tech support stories come from there, you can e-mail me anytime about them).
However, last year, they were also in need of a new Internet configuration, so we helped with that as well.
When we asked what limitations do we have, they said:

> "Go wild! We just want it to work well and fast!"

It was at that moment that my father and I exchanged some knowing glances and asked our friends if they
would be so kind as to allow us to use their Internet connection ourselves from anywhere in the world.
They allowed us, and so the lead was ready to be followed.

We have an US-based IP available to us, so we could theoretically access all the available streaming
services using it. But how could we do that from Romania? Well, that took a *lot* of work and quite
a bit of tinkering.

---

## VPNs everywhere

Obviously, firstly, we would need a **VPN** to access the local network from our friend's house from Romania.
You've probably heard of VPNs as a way to access geo-locked websites from anywhere in the world (what you've
probably used some VPNs for already, although I do not recommend using free ones) but that's not what they
were originally intended for, really.

VPN stands for "**V**irtual **P**rivate **N**etwork and they were initially designed to be used in order
to access a local network through an encrypted tunnel and act like a member of said local network. That
way, you could establish a tunnel to a VPN server that might be installed at, let's say, your workplace,
and once you connected to it, your computer would act as a legitimate device connected to that network,
without any third party being able to extract confidential information from this very public connection.
There is also the option to connect two separate local networks together, and have them act as one
cohesive network (this is called a **site-to-site** VPN, as opposed to the **remote-access** VPN previously
discussed). I used this type to link two separate networks together, one in my house and one at my
friends' house.

![A graphical representation of a VPN.](/public/img/vpn-representation.jpg)

To set up a VPN server anywhere is not inherently complicated, most routers actually do come with the option
to connect to a VPN server. Unfortunately for me, however, my friend's router could not host a VPN server
normally, so we decided to ship our own solution there, an EdgeRouter 4 from Ubiquiti, which looks something
like this:

![Picture of the EdgeRouter 4.](/public/img/edgerouter-4.jpg)

After getting it in there, I configured the VPN server, along with a few clients configured for my iPad, my PC,
my dad's PC, etc. We had two Wi-Fi networks in our home, "Rares" and "Rares_us", one that was a simple access point
to our normal Internet, the other being an access point attached to a switch which kept the VPN tunnel running.
We finally solved our problem elegantly, and now we could watch Netflix using a VPN tunnel to the US that always
worked...

Except when it didn't.

---

## Meet The Problems

As is always the case in the world of computer science, nothing *ever* works on the first try, but that is because
we delude ourselves with the idea that what we are working on is as simple or complicated as we think it is,
when in reality, it never is. And the problems started showing up very soon.

For starters, our VPN tunnel would frequently drop due to unnatural circumstances (i.e. power outages, random person
tripping over a plug, as is often the case in my house), so I had to find a way to automatically restart the VPN
tunnel whenever I needed to. I did so by essentially adding **cron jobs** (scheduled tasks in Linux) that would run
periodically to check whether our VPN tunnel was still up and running, and if not, to reenable it and send my father
an e-mail telling him of the outage so we know if something went wrong.

```bash
#!/bin/bash
# Ping tunnel, make sure it's open
/bin/ping -c 5 -i 3 -W 3 172.16.100.1 1>/dev/null 2>&1
if [ $? -ne 0 ];
then
echo "Failed ping tunnel! First try"
# We'll give the tunnel the benefit of the doubt, let's try again
sleep 2
/bin/ping -c 5 -i 3 -W 3 172.16.100.1 1>/dev/null 2>&1
if [ $? -ne 0 ];
then
echo "Failed ping tunnel ! Second try"
# Restart the VPN
/bin/vbash -ic 'restart vpn'
# Send e-mail to make sure everyone knows
/bin/vbash -ic 'echo -e "Tunnel down\nRestarted IPSEC VPN\nTimestamp: $(date)" | /config/scripts/notifyemail'
else
# The VPN works after the second try
echo "Ping tunnel success!"
fi
else
echo "Ping tunnel success!"
fi
```

In addition, my home is a bit more special than your average household. We have two internet lines linked to my
house, provided by two different ISPs, both of which were in Romania. This meant we had to use one of the networks
in order to establish a VPN tunnel to the US, but it wouldn't be incredibly stable, since we could have our Internet
connection randomly cut as well. In addition, it would also mean that not all the devices had access to the US network.
In the end, I decided to have *two* VPN tunnels open on two different networks, with both on separate Wi-Fi networks. But now the
question is *"Which network do I use to connect to the US or to Romania?"* I mean, don't get me wrong, I love the
freedom of choice, but having 7 Wi-Fi networks is not fun for me or for any potential guest to our home. So, in the end,
I decided to reduce the number of networks by implementing a **load balancer** between the two separate VPN networks.
Now we only have two Wi-Fi networks: "Rares RO" and "Rares US", and both handle all requests quite nicely.

A load balancer is, essentially, a piece of software that takes requests of a specific internet protocol and redirects
them to whichever server is less overloaded with requests, or even using a specific set of rules that you apply to its
configuration. It is commonly used at all the major websites, like Google, to distribute requests in a region to
multiple servers, not just one, since one server will never be capable of handling everything. Imagine having one PC
handling billions of searches a second. That's not gonna happen.

This becomes even more complicated as we find out a relatively crucial issue with our VPN: as much as it is currently
working on two separate networks, load balanced and all, nothing in our house is stable, and not even at our friend's
house either. Network packets were randomly dropped for no reason and some packets just straight up disappeared, as if
lost through the tunnel. Something was wrong with my tunnel and I didn't know what. After a bit of debugging, though,
I finally figured out the problem: NAT.

---

## NAT: The Final Boss

To explain what NAT really is, one must understand a bit about IP addresses as well, those nifty four numbers with
dots between them you may have found on the Internet (They look like this: xxx.xxx.xxx.xxx). IP addresses are a way
to know where to address a specific packet so that whoever is supposed to receive it can get it correctly. There are
different types of IP addresses:

- Class A, generally assigned to all the external servers of the world (1.1.1.1, for instance, is a DNS server for everyone to use.
If you don't know what a DNS is, that's a story for another time)
- Class B, reserved for medium-sized networks (i.e. huge corporation departments)
- Class C, most commonly found in homes (192.168.1.1, 172.16.0.61)

*(Tech rant: Technically, the reason why there are multiple classes is due to the way that computers handle transforming*
*an IPv4 address to a physical address, since they require specific limitations to the IPs in order to be converted*
*correctly, but this is beyond the scope of this article.)*

There is, however, one problem. Due to the world having way too many computers, and IP addresses being restricted to
very limited amounts (or rather, IPv4 addresses, the ones I'm talking about here, IPv6 addresses could account for
more computers than there are atoms in the observable universe), people have decided to reuse some IP addresses
by having closed networks with the same IP addresses in them (non-routable addresses, of type C) and switching between
network using a method called NAT.

NAT, short for **N**etwork **A**dress **T**ranslation, is a method used to switch the IP addresses I've been talking about
by "modifying network address information in the IP header of packets while they are in transit across a traffic routing device."
(Thanks, Wikipedia!) This way, you can have your phone communicate with any other website as if it were on the same network.
*However*, in a VPN, NAT can be a pain, since it can't really change those encrypted packets that the VPN sends over.
Essentially, you have to find a way to manually change the IP header before it his encryption so that you can redirect
the packet at the right address on the other side of the tunnel (oh, this has to be done on both sides of the tunnel as well,
so you can't shortcut your way out of this). In the end, I managed to fix the problem by configuring the switches on both
sides of the VPN tunnel to modify the IP header on both sides using predefined rules which, while very hardcoded, work well
for our case.

Finally, everything seems fine...right?

---

## Room for improvement

Of course, work is never over, and my father's dream is to reduce those two Wi-Fi networks to one, "Rares", and have the network
automatically figure out through which network you'd actually want to go through when visiting a website by using a DNS whitelist
to route requests through the different networks (netflix.com goes through the US tunnel, for instance), but that is a project for
the future. In the end, if there is one thing that you should really learn from this article is that you should never be daunted
by obstacles that might appear in whatever project you may be working on, since you can definitely get past them and achieve
exactly what you envisioned, provided you put in the effort. And yes, even if your computer might be against you, you will definitely
be able to solve the problem. After all, we made them, we can fix them.
I have plenty of stories I have left to share, and I'm sure you'll all enjoy hearing all about them. I'll give you a hint for next
issue's article here: "tiny PC".

+ 8
- 0
layouts/404.html View File

@@ -0,0 +1,8 @@
{{ partial "default_head.html" . }}

<div class="page">
<h1 class="page-title">404!</h1>
<p>Colossal screwup. This is a non-existent page. I'll try to fix it (someday). <a href="/">Head back home</a> and look around elsewhere.</p>
</div>

{{ partial "default_foot.html" . }}

+ 31
- 0
layouts/partials/head.html View File

@@ -0,0 +1,31 @@
<head>
<link href="http://gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">

<!-- Enable responsiveness on mobile devices-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">

<title>
{{ if eq .URL "/" }}
{{ .Site.Params.Title }} &middot; {{ .Site.Params.Tagline }}
{{ else }}
{{ .Title }} &middot; {{ .Site.Params.Title }}
{{ end }}
</title>

<!-- CSS -->
<link rel="stylesheet" href="/css/poole.css">
<link rel="stylesheet" href="/css/syntax.css">
<link rel="stylesheet" href="/css/lanyon.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700|PT+Sans:400">

<!-- Icons -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/assets/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/assets/favicon.ico">

<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

<!-- RSS -->
<link rel="alternate" type="application/rss+xml" title="RSS" href="/post/index.xml">
</head>

+ 41
- 0
layouts/partials/sidebar.html View File

@@ -0,0 +1,41 @@
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
styles, `#sidebar-checkbox` for behavior. -->
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">

<!-- Toggleable sidebar -->
<div class="sidebar" id="sidebar">
<div class="sidebar-item">
<p>{{ .Site.Params.description }}</p>
</div>

<nav class="sidebar-nav">
<a class="sidebar-nav-item {{ if eq .URL "/" }} active {{ end }}" href="/">Home</a>
<a class="sidebar-nav-item {{ if eq .URL "/post/" }} active {{ end }}" href="/post">Posts</a>

{{ $thisperma := .Permalink }}
{{ range .Site.Pages.ByWeight }}
{{ if isset .Params "sidebar" }}
<a class="sidebar-nav-item {{ if eq .Permalink $thisperma }} active {{ end }}" href="{{ .Permalink }}">{{ .Title }}</a>
{{ end }}
{{ end }}
</nav>

<div class="sidebar-item fa-2x">
<a href="https://twitter.com/Storm_FireFox1">
<i class="fab fa-twitter"></i>
</a>
<a href="https://github.com/StormFireFox1">
<i class="fab fa-github"></i>
</a>
<a href="mailto:matei@gardus.eu">
<i class="far fa-envelope"></i>
</a>
<a href="/post/index.xml">
<i class="fas fa-rss-square"></i>
</a>
</div>

<div class="sidebar-item">
<p>&copy; {{ .Site.LastChange.Year }}. All rights reserved.</p>
</div>
</div>

BIN
static/assets/apple-touch-icon-precomposed.png View File


BIN
static/assets/favicon.ico View File


BIN
static/avatar.jpg View File


+ 15647
- 0
static/public/doc/SignalEnvelopeDetectorSoundLatchSwitch.svg
File diff suppressed because it is too large
View File


+ 102
- 0
static/public/doc/storm_firefox1.asc View File

@@ -0,0 +1,102 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
6B7IrP6Csa2Jdw==
=p/TD
-----END PGP PUBLIC KEY BLOCK-----

BIN
static/public/img/JavaStreamRedundantSorted.gif View File


BIN
static/public/img/a-linters-nightmare.jpg View File


BIN
static/public/img/activitywatch-report.jpg View File


BIN
static/public/img/amazing-marvin.jpg View File


BIN
static/public/img/cronometer-daily-entry.jpg View File


BIN
static/public/img/cstimer-website-screencap.jpg View File


BIN
static/public/img/digispark-hid-source.jpg View File


BIN
static/public/img/digispark-purchase.jpg View File


BIN
static/public/img/edgerouter-4.jpg View File


BIN
static/public/img/gan-air-sm.jpg View File


BIN
static/public/img/git-workflow-example.jpg View File


BIN
static/public/img/godoc-vianuedu-example.jpg View File


BIN
static/public/img/google-archive-screencap.jpg View File


BIN
static/public/img/google-takeout-page.jpg View File


BIN
static/public/img/javadoc-vianuedu-example.jpg View File


BIN
static/public/img/keepass-2-screencap.png View File


BIN
static/public/img/me-finding-yubikeys.jpg View File


BIN
static/public/img/my-best-cubing-time.jpg View File


BIN
static/public/img/my-yubikeys.jpg View File


BIN
static/public/img/no-documentation-example.jpg View File


BIN
static/public/img/rubiks-cube-2.0.jpg View File


BIN
static/public/img/some-documentation-example.jpg View File


BIN
static/public/img/sweet-github-badge.jpg View File


BIN
static/public/img/twisty-timer-graph.jpg View File


BIN
static/public/img/vianuedu-git-network.jpg View File


BIN
static/public/img/vianuedu-total-warnings.jpg View File


BIN
static/public/img/vpn-representation.jpg View File


BIN
static/public/img/yubikey-gpg-pin-entry.jpg View File


+ 1
- 0
themes/lanyon-hugo

@@ -0,0 +1 @@
Subproject commit f9999a56a8cc2dc5ef9ae802a276769d96d14622

+ 1
- 0
themes/m10c

@@ -0,0 +1 @@
Subproject commit 016a12f437c57ccb48427bb7ca0037a06b16e71d

Loading…
Cancel
Save