vRO, Active Directory, converting SID and GUID

I am writing some automation to handle Active Directory objects, mostly managing ServiceConnectionPoints (SCP) and regular Group objects.

If you want to retrieve multiple LDAP Attributes having the same name (like the keywords collection of an SCP), you will have a bad time when using ActiveDirectory.getEntry(), because it has no public Method documented to retrieve a collection of a given Attribute (like for example if you have multiple keywords as an array). You can retrieve the first one, that’s it!

After some search I figured out that there is a lower-level LdapClient, which can be used to retrieve an LdapEntry, that has the magic getAttributes(), that can help you. So that’s good, we like lower level classes if we need to do advanced stuff.

However, when you want to get the objectGUID or the objectGUID, those are binary values…

Binary value for objectGUID

Microsoft Active Directory stores their SID Structures and UUID/GUID in binary hexadecimal byte arrays, instead of string values.

When using VMware vRealize Orchestrator to interface via the Active Directory Plugin, and want to get the string representation, you are mostly stuck with JavaScript and the difficult task to convert the binary value to string. I was definitely stuck. Google resulted in some examples and results, but not all were really usable.

A strange thing I have noticed is that the original code found on those pages was generating very bad SID-s. While debugging I found out that using LdapAttribute.getValueByteArray() will return signed integers, none above 256… For example, these are the last 6 bytes of my SID when using getValueByteArray():

[ ... -27, -20, -44, 21, 9, 0]

And this is what I get when getting the binary representation as hex in a different editor:

[ ... 0xe5, 0xec, 0xd4, 0x15, 0x09, 0x00]

We see from the back, that 0 and 9 are OK, 0x15 is also 21 in decimal, so that’s OK. The issues start with all the negative numbers, those are not good. However, after some math, when you “add” them to 256, the resulting numbers converted to hex now make sense:

256 + (-44) = 212 = 0xd4
256 + (-20) = 236 = 0xec
256 + (-27) = 229 = 0xe5

So, at the end, I managed to get them working, and the patched versions appear to produce the same values as seen in other tools (I am using Apache Directory Studio).

Disclaimer: The code below are modified version of the referenced sources, so I am not taking any claims that I wrote them, nor do I provide any support or responsibility if you use them.

function sidBufferToString(buf) {
    // original> https://gist.github.com/Krizzzn/0ae47f280cca9749c67759a9adedc015
    var asc, end;
    var i;
    if (buf == null) { return null; }

    var version             = buf[0];
    var subAuthorityCount   = buf[1];

    var result = [];
    for (i = 2; i <= 7; i++) {
    var identifierAuthority =  parseInt(result.join(''), 16);
    var sidString = 'S-' + version + '-' + identifierAuthority;

    function _n(s) { 
        if (s < 0) {
            // Some weird f'up where vRO gets the byte array, as some
            //  weird signed int, so we correct negatives into positives
            s = 256 + s;
        s = s.toString(16);
        if (s.length < 2) { 
            s =  "0" + s; 
        return s; 
    for (i = 0, end = subAuthorityCount-1, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
        var subAuthOffset = i * 4;
        var sidpart = parseInt(
            // the SID Part is little-endian, so we build the number from the "right" side
            _n(buf[11 + subAuthOffset]) + _n(buf[10 + subAuthOffset]) + _n(buf[9  + subAuthOffset]) + _n(buf[8  + subAuthOffset])
            , 16
        sidString += "-" + sidpart

    return sidString;

function guidBufferToString(guidValueArr) {
    // original> https://stackoverflow.com/a/59019552
    guidValueArr = attr.getValueByteArray();
    var guid = "", i;

    function _padLeft( obj, len, str ) {
        var s = obj;
        if ( str.length > 0 ) {
            while ( s.length < len ) {
                s = ( str + s );
        return s;
    for ( i = 0; i < guidValueArr.length; i ++ ) {
        // Some weird f'up where vRO gets the byte array as some 
        // weird signed int, so we correct negatives into positives
        guid += _padLeft((guidValueArr[i] < 0 ? 256+guidValueArr[i] : guidValueArr[i]).toString(16), 2,"0");
    return guid.replace(/(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})(.{4})(.{12})/, "$4$3$2$1-$6$5-$8$7-$9-$10");

Have fun, I hope I saved some hours of your life.

Mapping VMware vCenter Disks to Linux SCSI Block Devices

VMware and SCSI

There comes the time you want to automate stuff, or just need the information, which VMware vmdk Disk belongs to which OS Device inside the OS, depending on your architecture, you can be in quite a trouble, when picking the right VMware backing for your OS Devices.

After some google-foo, you might find some easy and shiningly trivial approaches, like counting OS sg Devices and hoping that they correspond to the vmdk files, like in this older blog post here…


From what many people have found out: This is not reliable and should not be depended on to be accurate!

A good start

There is already a quite good base of a Workflow that enumerates all the SCSI Host Adapters for a given VM and also finds out the Unit number of the Disk.

// Source is iiliev
 on the VMware Community Forum:
// https://communities.vmware.com/t5/vRealize-Orchestrator/Get-all-virtual-disk-from-a-VM-in-workflow/m-p/964488/highlight/true#M7429

var devices = vm.config.hardware.device;

for each (controller in devices) {
  var is_scsi = controller instanceof VcVirtualBusLogicController || controller instanceof VcVirtualLsiLogicController
       || controller instanceof VcParaVirtualSCSIController || controller instanceof VcVirtualLsiLogicSASController;
  if (!is_scsi) {
  var controller_label = controller.deviceInfo.label;
  System.log("SCSI controller found: " + controller_label);
  for each (device in devices) {
    if (device.controllerKey == controller.key) {
      var scsi_id = controller.busNumber + ":" + device.unitNumber;
      System.log("    device found:  '" + device.deviceInfo.label + "'  'SCSI (" + scsi_id + ")'");

Unfortunately those numbers do not correlate to anything of what is inside the VM, and are not really of any use, but we have a vRO skeleton to work with (I am lazy and don’t want to reinvent the wheel if not necessary).

VMware To The Rescue!

Well, VMware provides an answer on how to handle this and has published this KB article, one should be able to resolve which Disk SCSI Host is which inside the Guest.


This basically uses the vmx configuration file and pull out the pciSlotNumbers of the devices and looks it up for each device, mixing in the bridges as well.

In the Example VMware uses some esoteric number-shenanigans to maps the Slot ID “1216” to “00h:16h:01h at Dev.Func 00h:0h“. Fortunately they also provide an example python implementation, which does the heavy listing on a code level and is not too far from JavaScript.

Now in vRO

Now, this is all fine and nice, but mostly you have a vRO or a vRA that handles things for you, so you want it automated in JavaScript.

Good news is, that all the necessary inputs are available for vRO from the vCenter, you just have to look for it.

// This script maps the PV SCSI Devices to SCSI ID-s inside the PCI Root of the VM Container
// Logic is a derivate work of the official VMware-provided python Script based on the Article
// on https://kb.vmware.com/s/article/2047927

// Input: <vm> of type <Vc:VirtualMachine>
// Output: whatever you'd like to use with the given data.

var dev2slot = {};
var scsidevs = [];
var slot2id = new Properties(); 

// Unfortunately we need to access all the config items via extraConfig because 
// the devices does not contain the necessary information, but using that we can
// build the mapping table for all devices.

for each (cfg in vm.config.extraConfig) {
	var found = cfg.key.match(/^([^.]*)\.pciSlotNumber/i);
	if (!found) { continue; }
	var devname = found[1];
	if (!devname.match(/^pci|^scsi/) ) { continue; }
	dev2slot[devname.toLowerCase()] = cfg.value;
	if (devname.match(/scsi/)) { scsidevs.push(devname); }

// This logic is taken from the python Script, without the sanity checks
function getGuestPCIPath(dev) {
	var func = 0;
	var origdev = dev;
	var origslot = dev2slot[dev];
	while (true) {
		var slot = dev2slot[dev];
		var bus = slot >> 5;
		var devNum = slot & 0x1F;
		var bridgeNr = bus & 0x1F;
		if (bridgeNr == 0) { break; }
		func = bus >> 5;
		dev = ('pcibridge' + parseInt(bridgeNr - 1)).toLowerCase();
	devNumHex = parseInt(devNum).toString(16);
	funcHex = parseInt(func).toString(16);
	var loc = devNumHex + "." + funcHex;
	slot2id.put(origslot, loc);

for (var i = 0; i < scsidevs.length; i++) {
	var dev = scsidevs[i];

var out = [];

var devices = vm.config.hardware.device;
for each (controller in devices) {
	var is_scsi = controller instanceof VcParaVirtualSCSIController;
	if (!is_scsi) { continue; }
	var label = controller.deviceInfo.label;
	var slot = controller.slotInfo.pciSlotNumber;
	System.log("SCSI controller found: label='" + label + "' slot=" + slot + " pci_id=" + slot2id.get(slot));

    for each (device in devices) {
      if (device.controllerKey == controller.key) {
        var scsi_id = controller.busNumber + ":" + device.unitNumber;
        var sizeGB = device.capacityInBytes / 1024 / 1024 / 1024;
        System.log(" - device found:  '" + device.deviceInfo.label + "': pci_id=" + slot2id.get(slot) + " unit=" + device.unitNumber  + "' " + sizeGB + " GB");
		out.push({ pciid: slot2id.get(slot), unit: device.unitNumber , sizeGB: sizeGB, label: device.deviceInfo.label, ctrl: label });


This gives us an output JSON mapping that looks like this, which you could use on the VM itself to map this to a Block device (output formatted to ease parsing by humanoids)

  { "pciid": "15.0", "unit": 1,  "sizeGB": 50, "label": "Hard disk 2" },
  { "pciid": "18.0", "unit": 0,  "sizeGB": 16, "label": "Hard disk 3" },
  { "pciid": "18.0", "unit": 19, "sizeGB": 19, "label": "Hard disk 6" },
  { "pciid": "15.1", "unit": 3,  "sizeGB": 3,  "label": "Hard disk 7" }

Note: you don’t really need the sizeGB field, I just included it to have an additional sanity check during development and did not bother to remove it.

How to map inside a Linux VM

Now that we have this information, we want to get what device this is, we need to resolve this to a block device. I have found that the easiest way is to simply look in the /sys tree with some very heave bash-style star-globbing to find the proper device directory:

linux:~ $ basename -a /sys/devices/pci0000:00/0000:00:15.0/*/*/target*/*:*:1:*/block/sd*

linux:~ $ basename -a /sys/devices/pci0000:00/0000:00:18.0/*/*/target*/*:*:0:*/block/sd*

linux:~ $ basename -a /sys/devices/pci0000:00/0000:00:18.0/*/*/target*/*:*:19:*/block/sd*

linux:~ $ basename -a /sys/devices/pci0000:00/0000:00:15.1/*/*/target*/*:*:3:*/block/sd*

Note: I am using a Linux System with Kernel 4.12.14, depending on kernel versions, your paths can be different.

This shows us that Hard Disks 2,3,6,7 correspond to OS devices sdb,sdd,sdf,sdg.

Easy like Sunday morning, isn’t it?


The code is provided on an only a Proof-of-Concept and comes “AS IS”, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. It does not include any of the safety checks that are present in Python, and should only be used as a base.

I have not found any copyright notes on the original Python Script, so I am also only including this footer text. It is a derivate work based on a referenced VMware KB Article, and no copyright infringements were intended.

The vRO Script also just handles PVSCSI Host based devices because I just needed them. Adjusting it to other devices is given as homework if required.

Using ProtonVPN on pfsense

Privacy is hard

If you are concerned about your privacy, and happen to have access to ProtonVPN‘s beta test and are using a pfsense firewall as router, then this might be in your interest.

The rough how to is not intended as a step-by-step howto, and I assume you have a little more than basic knowledge of networking, so not all of the steps will be demonstrated with screenshots. It might be applied to other firewalls (which give you similar options) as well, but that is not detailed.

Disclaimer: I am not affiliated in any way with ProtonVPN, ProtonMail or pfsense, other than using their services with a paid account. This blog entry is a review of my first impressions after a “hackfull” evening, playing around and learning a lot about pfsense as well (Linux as a secure firewall got shaky lately).

Know your threats!

Why do you actually need a VPN?

Why do you need a VPN in the first place? Who/what are you going against? Do you need to fake the Country you want to appear in, or is your life depending on it? Remember, the path to your browser does not matter if you have a cookie in your Browser that tells them who you are.

Having VPN is a nice thing, but it only keeps your ISP out of the loop, ALL the websites tracking you will still keep tracking you, just like they did yesterday without a VPN.

Decide which VPN provider you trust!


Trust is something that has to be earned, but initially you need a basis on which you can start. A good thing to look up is where the company’s seat is located in, since for example not so long ago a court in the US ruled that Google has to hand over information that is in its posession, but physically not in the country, so take your time to research these things.

Research the technology and the security they are providing

Are they using up-to-date technology? Forget PPTP, it is just a joke about security. Also a lot of providers’ Settings pages or How to’s are like someone googled about VPN and copy-pasted together something from 2003, where MD5 and PSKs were still valid setups. If you see “our own crypto”, better Ctrl+W that Tab ASAP.

Decide what traffic to run through your VPN tunnel.

How important is it for you to run ALL traffic through the VPN Tunnel? Is it worth to not run some dedicated traffic through the VPN? VOIP for example is quite sensitive to latency, and forcing it over a VPN jump could distort the voice quality dramatically.

How about always-encrypted traffic that is always authenticated and tracked anyway? The VPN Tunnel does (almost certainly) not provide you the same bandwidth as your native speed is. Talking about streaming providers like Netflix or similar: is streaming your movies worth having it streamed over a VPN? Yes is still a valid answer, but keep the question in mind.

Another important question is if your internet should go black if the VPN tunnel is down, or do you want to fall back to your default, un-VPN-ed gateway until the connection can be re-established? Ask your wife / your husband as well :-), she/he might have a strong opinion about not having internet during the day. If it’s so important, do not rely on one sole provider but use multiple ones!


Get an account

You need access to the closed beta, which is available for Visionary and Plus customers of ProtonMail, or have to wait until it will be available to the public (?), which is currently advertised as “Coming in Spring 2017”.

For those having access to it, there should be a new icon in Settings, just right below “Keys”, which takes you to a page where you can generate a random username and set a new password for it.


Get the config

They have also a fancy Windows Download-Next-Next-Finish clicky-bunty Native-Client, which can be used directly with your ProtonMail login credentials, and the random username and dedicated password are only required if you plan to use a third-party client, like openvpn.

Well, for native OpenVPN clients they actually provide a downloadable zipped collection of .ovpn files, which we will make use of to set up our pfsense. You can find them on their support page for linux at Additional resources.

The Security in a nutshell

The quality of a VPN Provider can be more or less measured by the technical aspects of how to configure the Tunnel, what crypto it uses and how much bandwidth / latency you need to sacrifice. ProtonVPN uses up-to-date settings, let’s have a quick look at them.

The crypto cipher being used is AES-256-CBC with a HMAC of SHA512, so not the old SHA1 with AES-128 that you tend to see. They also include a 2k static key for tls-auth the packages.

Embedded there is a CA to authenticate the remote side. which was issued by “C=CH, O=ProtonVPN AG, CN=ProtonVPN Root CA” and is a 4k RSA key with SHA-512 signature, which is currently considered “secure”.

All connections use the standard udp/1194 port, so in situations where this outgoing port is filtered, you might hit it’s limits. Some captive portals or firewalls (like at airports) let udp/53 pass without auth and/or are limiting outgoing ports to tcp80/443 even after logged in, so having a listener on those might also be worth to think about…

Secure Core

ProtonVPN presents a feature that is called “Secure Core“. This consist of Servers located either in Sweden or Iceland, but have a second hop at an endpoint in a different location, and your data travels like You->Sweden->France, so your public IP is in a different country than your VPN Server you connect to.


This is quite good for privacy, but relatively bad for latency: it adds about +100ms to +500ms, which has to be considered when choosing a permanent tunnel for a fixed location.

The speedtest with the Secure Core was “acceptable”, my 50/10MBit line measured around 39/6MBit throughput and a latency of +120ms totaling around ~125ms.


Configure pfsense

The current setup will show a random Japanese server being used with one dedicated IP net being routed through the VPN (accessing my workplace’s VPN should be routed directly).

The pfsense box itself is running on a 3-NIC APU2 Board from PC Engines, which has 4core / 4GB RAM with AES-NI in CPU, so it should handle this burden with ease. At the time of writing the latest version was 2.3.3-RELEASE-p1 [I updated to 2.3.4 during writing the blog entry].

Open the .ovpn config file for your favorite VPN Tunnel and keep it within reach, you’ll need it for a lot of copy+paste work.

Import RootCA

First of all, we need to import the ProtonVPN RootCA, so get to:

System => Certificate Manager => CAs => + Add

For the Name, enter something that you know of what this is, using “ProtonVPN RootCA” is probably the best approach for this.

On “Method” you can keep the default of “Import an existing CA“.

The “Certificate Data” Field is where the content of the <ca> … </ca> section goes, including the lines with the many dashes and BEGIN/END CERTIFICATE.

After saving you should have an entry back at CA’s showing you a self-signed certificate like this:

O=ProtonVPN AG, CN=ProtonVPN Root CA, C=CH
Valid From: Wed, 15 Feb 2017 15:38:00 +0100
Valid Until: Mon, 15 Feb 2027 15:38:00 +0100

New OpenVPN Client

Go and create a new OpenVPN Client connection at:

VPN => OpenVPN => Clients => + Add

Now simply follow the fields and use your copy+paste foo:

General Information

Server host or address => IP on "remote" line in .ovpn
Server Port => Keep in on 1194 (or whatever is after the upper IP)

User authentication settings

Username => Random-Generated Username from ProtonMail GUI
Password => Password for Username

Cryptographic Settings

Automatically generate a shared TLS authentication key => uncheck
Key => Paste value from <tls-auth> .. </tls-auth>, excluding comment with #
Peer Certificate Authority => Choose the RootCA we set up earlier
Encryption Algorithm => Choose AES-256-CBC (or whatever is at line "cipher")
Auth digest algorithm => Choose SHA-512 (512 bit) (or whatever is on line "auth")

Tunnel Settings

Compression => Enabled with Adaptive Compression
Don't pull routes => If you want to route ALL your traffic over VPN, keep it unckeced, otherwise check.

Advanced Configuration

Custom options => Add:
 remote-cert-tls server
 tun-mtu 1500
 tun-mtu-extra 32
 mssfix 1450

It should look like this at the end.


Now save it, it should connect automatically if not disabled with the very first checkbox. You can go and check it out on Status => OpenVPN. It should show “up” with a virtual IP address in the IP Range:


All Your Traffic Are Belong To US

The most secure way

If you have chosen to route ALL your traffic over the VPN at the OpenVPN setup, you will need to add additional outgoing NAT rules for the OpenVPN interface, so go to:

Firewall => NAT => Outbound

Here you need to check the radio button telling “Manual Outbound NAT rule generation. (AON)“.

After that, select on each rule one-by-one the icon of “Add a new mapping based on this one” in the column of Action, and duplicate them with just changing the Interface to OpenVPN.

This is required because the remote server pushes routes that will change your routing table to go over their gateway via “redirect-gateway def1“, so you need to allow all traffic to being NAT-ed via OpenVPN.

This step is also nicely illustrated by PIA’s How to:

We decide ourself what to send via VPN

If we chose not to pull the routes, we will need to get a little more configuration and set up our own routing rules, since we don’t get the default routes pushed, but it makes much more fun 🙂

Add a new Interface

 Interfaces => (assign)

Here we create a new interface for our OpenVPN connection we set up earlier. On the “Available network ports” line pick the ovpncX interface. This will create you an OPTX interface, depending on how many interfaces you already have.


Click on its name to open and edit it. Make sure to choose a Description that will match your setup, since after you got it used by a Gateway, pfsense does not allow you to change it. I have chosen PROTONVPN. Make sure to check “Block bogon networks” but do not check to block private Addresses, since the VPN has a subnet of 10/8, which would be blocked otherwise.

Click here to see the whole page. After saving, you should see the new interface being show in the Interfaces drop down menu.

Add a new gateway

Now we need to tell pfsense what traffic we want to use the VPN. For that, we need to defined the PROTONVPN interface we just created as a Gateway, that can be used to send traffic towards The Internet. Just navigate to:

System => Routing

You should see the PROTONVPN_VPNV4 and PROTONVPN_VPNV6 gateways created by default. I have chosen to customize them and set up a ping monitoring against Google’s DNS Server, and have tuned the ping times higher to compensate with possible reconnects and latency introduces by some of the remote vpn servers. You can see the whole config page here.

Depending on if you want to have more VPN tunnels set up to load-balance your traffic, or if you want your Internet not go black if the tunnel is down, you will need to create a Gateway Group. You can skip this part and pay attention at the Firewall rules if you want all your traffic to pass through the tunnel.

I have chosen my traffic to fallback to the default Gateway if the VPN is not available, so you have to add the PROTONVPN with Tier 1 and the WAN with Tier 2, and keep the rest unchanged.


We have created the Gateway called “VPN“, which uses the ProtonVPN Tunnel, but if that is not reachable, falls back to the default WAN route. This is good to have your wife not call you during the day if the VPN tunnel goes down for maintenance 🙂

IP Aliases

Firewall => Aliases

I personally utilize the Aliases of pfsense, which comes handy to define destinations like WORK_VPN or YOUTUBE or NETFLIX, for which you can find IP subnets after some searching. Later I bundle them together in a DIRECT_ACCESS alias, which holds the separate entries, so I don’t have to touch the NAT Rules after editing this list.


NAT Rules

Firewall => NAT => Outbound

Here we need to change “Automatic outbound NAT rule generation” to “Manual Outbound NAT rule generation” to get the freedom to reorder and edit the entries, so they make sense.

I have for VOIP Telephony a Fritz!Box, which is in my DMZ, but it is latency-sensitive, and needs a direct port NAT-SIP protocol is not that big of a mess, so that goes on top.

I have created three additional NAT rules, that define how the translation will happen if the package arrives from my home network (it’s represented by the USG_DMZ alias). The remaining are the default rules for the outgoing WAN packets, which have been generated by the automatic rule generation.


Firewall rules

This is the most challenging part, since you need to design your network routes now. We have set up the proper VPN Gateway with monitoring and fallback to the WAN gateway, defined how the packages need to behave if they are sent out via the PROTONVPN interface, now we only need to ensure the packages actually take the right interfaces on their path. Navigate to the proper interface where your Internet-facing traffic arrives to the pfsense box. For me, this is the DMZ interface, but for you it might be LAN.

Firewall => Rules => <Interface>

These rules are processed from top to bottom, and the first rule that applies is processed, and if none matches, default is to drop the package. In order to allow some dedicated traffic direct access bypassing our VPN Tunnel, we need first to create an entry that matches the destination we have defined in the DIRECT_ACCESS Alias. For the Source, you could choose LAN Net or the gateway your internet flows through, which in USG_DMZ for me. See here the whole config page

The next in the list should be a generic rule that catches all remaining traffic to go through the VPN gateway. To achieve this, we will need to open the Advanced options and scroll way down to Gateway, keeping everything else as it is. Here at Gateway you can choose either the PROTONVPN_VPNV4 for VPN-Only, or our Gateway Group called VPN for WAN fallback.


The whole settings page can be viewed here.

For all this to work, we need to make sure the ordering is correct, so first we add a specific rule, and below it on that catches all remaining traffic.


Fingers crossed

If everything went well, you only have to fire up your command line and run a traceroute against an address included and one not included in the DIRECT_ACCESS rule. You should see something like this if the traffic is flowing over the VPN:

Tracing route to japan.go.jp []
over a maximum of 30 hops:

 1   1 ms    1 ms    1 ms
 2 379 ms  408 ms  408 ms
 3 337 ms  338 ms  339 ms
 4 339 ms  372 ms  403 ms  ae12.dar02.tok02.networklayer.com []
 5 381 ms  397 ms  392 ms  ae9.bbr01.eq01.tok01.networklayer.com []
 6 374 ms  406 ms  409 ms  ae-20.r00.tokyjp03.jp.bb.gin.ntt.net []
 7   *     364 ms  408 ms  ae-14.r30.tokyjp05.jp.bb.gin.ntt.net []
 8 418 ms  409 ms  407 ms  ae-2.r03.tokyjp05.jp.bb.gin.ntt.net []

If you want to choose a different tunnel, just rewrite the IP on the OpenVPN Client settings, it will reconnect and no other changes have to be re-done.

Final words

I have tried to add multiple VPN Tunnels from ProtonVPN, but apparently they provide you with the same IP Subnet, regardless of which VPN tunnel you use, so load balancing between them is currently not possible: having the same IP Subnet with the same Gateway IP of is not something a router can handle.

One could add different VPN Providers and round-robin over the different gateways, but as for example Troy Hunt has also pointed out quite good in his long blogpost, putting all your (and family’s) traffic through a VPN does mean they know A LOT of information about you, even if most of it is encrypted.

So bottom line is, since there is actually no organization overseeing them, the VPN Provides can be initially measured by the technical implementation of their service, but in the very end, it’s the customer’s trust they have to earn by behaving like they care about security and privacy, how they react to events regarding their customers or themselves, and are not just shipping your IP Traffic from A to B.


The screenshots were taken with the Chrome Plugin “Full Page Photo Capture

Secure Facebook emails with PGP

Emails are the postcards of our times, the only difference is, we are not just sending them once a year from our holiday, but multiple times a day, and include conversations that we would not dare to write on a postcard…

Email was designed to be used unencrypted. There are extensions like StartTLS (don’t really use this, it is simply strippable by MITM) or Native TLS to secure the Transport, and since the big mail providers started using them, the usage rate just went up. However, this still does not make sure only you can read your mail, only that it is safe “on the wire”. There are additional extensions to mail like DKIM or SPF, but the adoption is pretty low, and mailing lists tend to mess them up…

There is a pretty good way to ensure real privacy of the Content by using PGP, but this is still not a widely adopted or easy-to-use and idiot-proof method of securing the Content of emails. This basically works by publishing your public key (which is not sensitive) to the sender, so it can be used to encrypt the Content of the email, and only you (or others by having your private key) can read it.

If you happen to poke around your Facebook security settings, you can find a menu entry about having Facebook sending encrypted emails to you. This is pretty awesome! You only need an email client or service that supports receiving encrypted emails.

ProtonMail just happens to use PGP encryption, and has seamlessly integrated it to their core mail service, so every email sent to you encrypted by your public key will transported by End-to-End secured for your eyes only.

You might ask if this is really required, but if you have the opportunity, why not use it? 🙂 Simply go to the Keys section at your Settings Page, where you can use the link in the Download column to get a text file that looks like this:

Version: OpenPGP.js v0.11.0-PM
Comment: http://openpgpjs.org


Just use this text and paste it to Facebook:


After clicking Save Changes, Facebook will send you a validation link, that you really receive their Emails.

Be aware, that after clicking this link and confirming this shift, all your received emails, including any password recovery mail, will be sent encrypted, so loosing access to the PGP private key could also mean loss of the ability to recover lost passwords.

However, this is also why it is actually secure; others cannot intercept emails sent to you, and this can add one small step in securing your Facebook account.


We live in times, where data leaks and information theft is daily business well hidden from your life – until it hits you hard. Each small step counts.