How HTML5 APIs can fingerprint users

If you think that IP address, cookies and HTTP headers are the only factors used to uniquely identify and track users around the web… you are terribly wrong!

New, modern fingerprinting techniques rely on multiple factors:

  • IP address
  • Cookies
  • Language
  • Timezone
  • HTTP headers (User agent, referer, etc)
  • HTML5 APIs (WebRTC, Battery API, etc)
  • HTML5 and CSS3 features detection
  • CSS media queries
  • WebGL
  • Browser plugins (Flash, Silverlight, Java, etc)
  • Browser add-ons
  • Browser options (Do-Not-Track etc)
  • Browser storage
  • System fonts
  • TLS/SSL Session IDs
  • Hardware detection (Camera, Mic, Touch screen, etc)
  • Screen (resolution, color depth, pixel density, etc)
  • Audio and video codecs
  • Accessibility features

Recent W3C additions to HTML standards allow developers to communicate with the user device for enhanced options in websites, apps or games. It is not surprising that many APIs are exploited to actually calculate a more precise user fingerprint.

What is a fingerprint?

Imagine you walk in a shop and at the entrance an advanced camera scans you and saves informations like: body type, height, skin color, clothes, shoes, walk style, tone of voice etc. All this data is then serialized and passed through a hashing function to calculate your unique fingerprint. Next time you visit the shop or a shop of the same franchise, even if you have different dressing style, with a quick analysis your fingerprint is still associable to the one of your previous visit.

The same happens visiting a webpage with a browser (without user explicit cooperation).
Doesn’t matter you are not logged in or you disable cookies. It is still possible to associate a user to a token, it is not 100% accurate technique (yet) but continues to evolve.
Electronic Frontier Foundation researched browser fingerprinting in the publication “How unique is your Web Browser?” (PDF). An accurate description of device fingerprinting is on WebKit Wiki and on Wikipedia.

Client side Javascript

To have a better idea on how fingerprinting currently works you can inspect a javascript library used by web developers: Fingerprintjs2.

To effectively block scripts disable javascript globally or use NoScript or uMatrix extensions. Other factors can still reveal a lot about you and might exist other fingerprinting ways not disclosed yet.


Thanks to new HTML5 standards, developers can access sensible user information or device hardware in some cases without the need to ask for permissions. The following APIs are currently exploited in the wild. The most common way to block this features is to disable javascript or use a specific add-on.


This is a nasty, stealth and (with javascript enabled) almost unstoppable technique, utilized actively since 2012, occasionally embedded in widely used scripts (remember AddThis “research” to find alternatives to cookies).

When the browser visits a webpage with a canvas fingerprinting script, it is instructed to draw a hidden graphic that gets converted to a token. The uniqueness of the token depends by factors like browser, operating system and installed graphics hardware.

To avoid Canvas fingerprinting you can either:

  • disable javascript globally
  • use NoScript, uMatrix or CanvasFingerprintBlock (Chrome only) extensions
  • use Tor Browser


According to researches Battery Status API is able to get level, charging time and discharging time of device battery. All this data combined together is nearly unique for each device and battery status, potentially allowing the tracking of activities on the web.

A paper (PDF) titled “The leaking battery – A privacy analysis of the HTML5 Battery Status API” targets Firefox users on Linux systems. As result of the impressive study: ” We propose minor modications to Battery Status API and its implementation in the Firefox browser to address the privacy issues presented in the study. Our bug report for Firefox was accepted and a fix is deployed.

On Chrome you can install the add-on Battery Info Blocker to prevent websites from accessing your battery info.


You should disable WebRTC if you don’t use it. WebRTC leaks your local IP and might leak your IP on VPN (on Windows) other than be another factor used to fingerprint your system.

To avoid WebRTC leaks you should use Firefox and disable WebRTC opening about:config, find the value media.peerconnection.enabled and set it to false.

On Chrome you can install the add-on WebRTC Block but IP leaks might occur.

Resource Timing

Developers can use this API to collect complete timing information related to resources on a document. Concerns involving privacy are expressed in the Working Draft: “Statistical fingerprinting is a privacy concern where a malicious web site may determine whether a user has visited a third-party web site by measuring the timing of cache hits and misses of resources in the third-party web site. “.

If you use Firefox you can disable this API opening about:config and setting to false the options dom.enable_resource_timing, dom.enable_user_timing and dom.performance.enable_user_timing_logging.

On Chrome the only way to disable it might be to disable javascript.


If enabled can reveal your physical location compromising your privacy. Modern browsers always ask permission to reveal geo location to websites and apps requesting it.

To disable this feature permanently on Firefox you should open about:config in the address bar, look for geo.enabled value and set it to false.

On Chrome go to Settings, then Show advanced settings, find Privacy block and click on Content settings, in this window look for Location and select the option Do not allow any site to track your physical location.

Hardware fingerprinting

A paper (PDF) titled “Hardware Fingerprinting Using HTML5” shows new potential techniques that rely on the ability to communicate with device hardware to get a specific hardware fingerprint in addition to a software based one (browser, Os, etc).

The paper shows that hardware like GPU (modern browsers use hardware acceleration), camera, speakers and micmotion sensors, GPS and battery can all be accessed with HTML5 (not always with user permission) and in particular GPU can effectively be used to fingerprint users.


Device fingerprinting

What is fingerprinting?

EFF: How Unique Is Your Web Browser? (PDF)

EFF: Panopticlick tests your browser to see how unique it is

The Web never forgets: Persistent tracking mechanisms in the wild

A privacy analysis of the HTML5 Battery Status API

Resouces Timing API Working Draft

Hardware Fingerprinting Using HTML5

Browser leaks and web browser fingerprinting

Modern & flexible browser fingerprinting library

Dynamic port forwarding with SSH and SOCKS5

In this article i collected all the necessary information and useful tips to create SSH tunnels between hosts in order to protect internet traffic with an encrypted layer.


  1. What is SSH
  2. Why you need to use a SSH tunnel
  3. Public and private key pair
  4. VPS setup and firewall
  5. Dynamic port forwarding in details
  6. Configure browser, email, instant messages
  7. Optional configurations
  8. Links

What is SSH

SSH stands for Secure Shell and is described on Wikipedia as “a cryptographic (encrypted) network protocol for initiating text-based shell sessions on remote machines in a secure way”.

SSH can do much more than remote shell. For example you can copy files from local to remote host (local forward) or mount a remote file system on your computer (remote forward) or tunnel to internet from a local SOCKS proxy (dynamic forward).

In this article i will explain how to forward and encrypted network traffic between a local SOCKS5 proxy and a VPS (virtual private server).

  • SSH enables port forwarding with encrypted tunnel
  • SOCKS5 (Socket Secure) provides a proxy server to route traffic between client and server using authentication
  • VPS is our remote server that connect us to internet
  • Applications needs to be configured to make use of the tunnel

Why you need a SSH tunnel

The answer is simple: SSH dynamic port forwarding is the fastest and cheapest way to protect your traffic from undesired eyes.

  • An additional layer to protect your identity
  • An encrypted channel of internet traffic
  • A less risky communication environment for your privacy

A few practical examples:

  • You can connect to open networks and no one can read in clear your network packets, assuming you carefully protect your private key
  • You can reach content blocked because of your location
  • You can circumvent firewalls

Private and public key pair

The very first thing you need to setup is a private and public key pair. With this keys you can authenticate the client (your machine) on a remote server.

  • Generate both keys, private and public, on your computer
  • Protect private key with long, possibly complex pass phrase. You need to enter it every time you want to create a SSH connection
  • Copy the public key on the server you want to log in
  • SSH opens a connection only to clients matching the server public key with the right client private key

This process ensures a higher level of security compared to passwords protected accounts vulnerable to brute force attacks.
You need to protect your private key, anyone owning it can authenticate himself as you on every server that can match relative public key.
You can create a different keys pair for every remote host you intend to connect with SSH, this way if one private key gets compromised you have an isolated case.

Let’s create SSH keys. On your computer terminal type:

# ssh-keygen -t rsa


Next step is to choose a name for the keys. If you would just press enter it would assign the default name id_rsa and and those would became your default keys. I prefer instead to define a custom name for a pair used only for SSH tunnel: id_rsa_tunnel as private key and as public one.

# Enter file in which to save the key (/home/user/.ssh/id_rsa): id_rsa_tunnel


Enter two times the pass phrase you want to use for your private key and you are done. Your keys are located in your home directory, /.ssh/ folder: /home/user/.ssh/id_rsa_tunnel (private) and /home/user/.ssh/ (public) where /user/ is the user you are logged in.

VPS setup and firewall

Your remote host, a VPS in this case, is going to route your traffic to internet. Choose the right VPS provider according to your needs. Once you have the remote public IP it’s convenient to change your hosts file, assuming the public IP of your VPS is (i invented it) you can add this line to file /etc/hosts naming it “tunnel”:

# tunnel


Save (you need to be root) and quit. From now on your system will recognize your remote host with the word “tunnel”. Open a terminal and type:

# ssh root@tunnel

You should get a remote shell as root after you type in the password. Once logged in update server:

# apt-get update
# apt-get upgrade


and install new packages if any. Install the tools needed:

# apt-get install sudo ufw


Sudo grants administrative permissions to regular users and Ufw stands for Uncomplicated Firewall, an easy to use front end for iptables.

It’s time to create a regular user account and say goodbye to root. Go for a generic name like “sshuser” and choose a password easy to remember and difficult to brute force, finally add user to sudo:

# useradd -s /bin/bash -m -d /home/sshuser -c "sshuser" sshuser
# passwd sshuser
# usermod -aG sudo sshuser


You can now log out from root session.
It’s now time to SSH into the VPS using the user account you just created but first you have to associate your public key to the account. There is a tool called ssh-copy-id that will help with this. You just have to run:

# ssh-copy-id sshuser@tunnel


and your default public key will be automatically copied securely to remote host (use option -i to define a custom public key). If you created the key pair following the article you have to type:

# ssh-copy-id -i ~/.ssh/ sshuser@tunnel


Now you can log in into your VPS with:

# ssh sshuser@tunnel


Enter the pass phrase and you are in.
It’s time to change the server SSH configuration in /etc/ssh/sshd_config.
Open file with sudo and check the following lines, if not there add them:

Port 5432
Protocol 2
UsePrivilegeSeparation yes
PermitRootLogin no
StrictModes yes
PubkeyAuthentication yes
AuthorizedKeysFile      %h/.ssh/authorized_keys
PasswordAuthentication no
X11Forwarding no
TCPKeepAlive yes
AllowUsers sshuser
AllowTcpForwarding yes


SSH default port is 22 but you can obfuscate a little the traffic setting it to port 5432, usually adopted by PostgreSQL.
With PermitRootLogin and PasswordAuthentication we block possible easy attacks and with AllowUsers you restrict access even more to only your user.

Last step to strengthen your server is to configure the firewall.
All you have to do is allowing connections only to the port you want to connect and limit possible brute force attacks.

# sudo ufw allow 5432/tcp


Opens the TCP port 5432 from outside connections.

# sudo ufw limit 5432/tcp


Limits password log in attempts. Consider the use of SSHguard or fail2ban for a definitive solution to brute force attacks.

# sudo service ufw restart


Restart firewall to enable changes.
Your remote server is now ready.

Dynamic port forwarding in details

You have now everything ready to create a SSH tunnel. Open a terminal on your computer and type:

# ssh -D 8080 -N -p 5432 sshuser@tunnel -vv


If everything works as expected the tunnel is created after you type the pass phrase. That’s it.

The command in details:

  • -D enables dynamic forwarding
  • 8080 is the port of localhost you are going to listen with proxy, can be any port open of your computer
  • -N stops SSH from executing commands
  • -p is the port of the remote host you connect to, you configured the firewall server to keep port 5432 open
  • -vv is very verbose output on console (-v and -vvv are less and more verbose). I suggest to keep this option the very first times to have a better idea of what’s going on with the SSH connection and remove it later on.

You can fork the process in the background and keep SSH quiet with the options -f and -q.

# ssh -D 8080 -fNq -p 5432 sshuser@tunnel


Tunnel is now up. All traffic can now be routed trough your localhost (or from port 8080 to your VPS and then to internet.

Note this will work using your default private key.
To specify the private key you created earlier use the option -i:

# ssh -i ~/.ssh/id_rsa_tunnel -D 8080 -fNq -p 5432 sshuser@tunnel


You SSH connection is now in the background. To close it you have to terminate the process; use htop to find and kill it.

Configure browser, email, instant messages

Every applications not listening on SOCKS proxy will leak packets out of the tunnel. It’s important you configure all applications you normally use for internet to make use of the proxy.


Tunnel is created so let’s open a browser to access internet. You can open Chromium from terminal typing:

# chromium --temp-profile --proxy-server="socks5://localhost:8080"


Note the flag — proxy-server that tells Chromium where is located the proxy. This is enough to browse using the SSH tunnel.

You can add more flags to a Chromium session, there is plenty listed here. Why not running incognito mode and disable most functionalities you don’t use:

# chromium --temp-profile --incognito --no-referrers --enable-strict-mixed-content-checking --disable-java --disable-plugins --no-experiments --no-pings --disable-preconnect --disable-translate --dns-prefetch-disable --disable-background-mode --proxy-server="socks5://localhost:8080"


Add or remove flags depending on your needs.

To configure Firefox (known as Iceweasel on Linux) click on the menu icon and go to Preferences. Click on the tab Advanced and on the inner tab Network. Finally click on Settings button and click on “Manual proxy configuration” typing “localhost” in the field next to SOCKS Host, port 8080. Click on SOCKS v5 if not selected. Click on OK and your browsing should now be encrypted.

Watch out for DNS leaks using Firefox (or Iceweasel). Open the config window typing about:config where you would type a URL and press enter. Search for network.proxy.socks_remote_dns and set it to true. Test results before and after the changes on


The procedure to enable SOCKS proxy on Thunderbird (or Icedove on Linux) is similar as for Firefox described above. Menu, Preferences, Preferences, Advanced, Network and Disk Space, Settings and then configure proxy same way.

Instant messaging

Pigdin is a universal chat client that supports most common protocols and social network chats. In one application you can chat over many networks and in combination with OTR plugin you can encrypt your messages over not secure networks. You can configure Pidgin to use the proxy as well, just open Preferences and under Network label you can set the Proxy Server as SOCKS5, host is “localhost” and port 8080.

If you are more old school and chat over IRC with irssi client, type within the console:

/set proxy_address
/set proxy_port 8080
/set use_proxy ON


Note that is the address of localhost.
I wrote an article about IRC, SSL and OTR configurations if you want to know more.

Optional configurations

You can now create shortcuts for future SSH sessions. You can also run a script at boot time that opens a tunnel in background. You can find many examples on internet about it. I personally prefer to create and delete tunnels as i need it, without any automation.

Remember the command to open a tunnel:

# ssh -i ~/.ssh/id_rsa_tunnel -D 8080 -fNq -p 5432 sshuser@tunnel


To create a shortcut to this command edit or create a config file on your computer at: /home/user/.ssh/config and add the lines:

Host tunnel
    Port 5432
    User sshuser
    IdentityFile ~/.ssh/


Now to open a SSH tunnel you can type:

# ssh -fNq tunnel


An even better alternative are alias. Add the following line to .bashrc file in your home directory:

# alias sshtunnel='ssh -i ~/.ssh/id_rsa_tunnel -D 8080 -fNq -p 5432 sshuser@tunnel'


And now you can create a tunnel just typing:

# sshtunnel


There is one more shortcut available. You can avoid to type the same damn long pass phrase every time you want to log in your VPS: use ssh-add, an SSH agent that takes care of your private keys identities. Type:

# ssh-add


Press enter and type the pass phrase. If ssh agent is not started type:

# eval $(ssh-agent)


And repeat the ssh-add command.
Log in your server with SSH now and if everything is correct you should automatically get the remote shell.

Another important add on useful for tunnels is autossh, a tool to automate SSH reconnections if the tunnel drops for network connectivity problems.


OpenSSH, project homepage

SOCKS, protocol standards

Ufw, un-complicated firewall

SSHguard, log monitor

autossh, restarts SSH sessions and tunnels

IRC with SSL and OTR encryption

IRC is a chat protocol active since early nineties, it belongs to a time when internet services were developed for the sake of communication rather than for profit, intrusive advertising and social control.

You can chat on IRC with people all around the world, using strong encryption, in a matter of minutes.

There are plenty of IRC servers with hundreds active channels each, all you need is a IRC client to access them. This article shows how to properly configure the open source IRC client Irssi (official website) to achieve an encrypted connection between your client and the server you connect and even more between you and the people you chat with.


Irssi is a minimal command line IRC client available for most Linux distributions, on recent Ubuntu and Debian is already compiled with SSL support but to enable OTR you need to install a plugin:

apt-get install irssi irssi-plugin-otr


After installation start the client typing:



Specify your identity with the commands:

/set real_name your_nickname
/set user_name your_nickname
/set nick your_nickname


Official documentation of the OTR plugin suggests to set the following option to speed up sessions:

/set cmd_queue_speed 1msec


To save configuration type:



You can now connect to a server and chat on IRC. Use the commands /connect to connect to a server, /join to join a channel (or create a new one if does not exist) and /query to start a private conversation with somebody.

By default IRC establish a not secure connection but is very easy to improve security using SSL and OTR.


SSL creates an encrypted connection between your client and the IRC server. Assuming you want to connect to Indymedia IRC server, you would type:



Improve this command with SSL: you need to add the -ssl option and the server port:

/connect -ssl 6697


That’s it. To verify the secure connection you can whois your self typing:

/whois your_nickname


Press Alt + 1 to go to the main window of Irssi and read the response, press Alt + Left (or Right) Arrow to jump between open sessions.

If you cannot install an IRC client or your client does not support SSL, a few most popular IRC servers allow you to connect directly via web browser using HTTPS (secure HTTP connection with SSL). For example you can access Indymedia IRC server via as well.

Check the homepage of your favorite IRC server for instructions about SSL configuration.

OTR (Off-the-Record Messaging)

OTR (project homepage) is a protocol that provides encryption, authentication, deniability and perfect forward secrecy for instant messaging chat sessions. It works with IRC, Pidgin, Adium, Jitsi, WeeChat and many others.

In Irssi to enable OTR plugin you must load it from main window (press Alt + 1), type:

/load otr


It’s handy to add in the status bar a notification that tells you the state of the OTR session, type:

/statusbar window add otr


A session can have 4 different states: plain text, finished, OTR, OTR (unverified).

Remember to save the configuration with:



You can automatically load OTR at startup adding the load command in Irssi startup file, type in a separate terminal:

echo “load otr” >> ~/.irssi/startup


Last step is to create a key to be used by your account on a certain IRC server. Once OTR is loaded type:

/otr genkey


Verify the status of the process (might take a while) typing:

/otr info


You need to wait until the key is generated to start using OTR.

OTR only works if both you and the person you want to chat have it installed and enabled. Assuming you are both connected to same server, open a private chat session and then start OTR typing:

/otr init


Once you want to finish th OTR session type:

/otr finish


But are you really sure the person you are chatting is the person you think he/she is?

You can authenticate each other in 3 different ways, remembering that the best way to verify a key fingerprint or share a secret for authentication is to meet face to face or through encrypted email (GPG):

1. Use a shared secret that you both know.

/otr auth secret


Both you and the other person like the same punk band. You both agree to authenticate using the name of the band as secret. In real world scenario you would say something like:

you > let’s check if it’s really you, let’s authenticate with the name of our favorite punk band
person > ok, let’s do it ;)

Assuming the favorite band name is Wolfbrigade, now you both type in your own client:

/otr auth wolfbrigade


If you both type the same band name, you can assume that person is really your friend.

2. Ask a question you can assume the other person answer correctly.

/otr authq [question] secret


For example, I know that the person I want to chat knows my favorite punk band is Wolfbrigade. I can use this to verify is really him:

/otr authq [what’s the name of my favorite punk band?] wolfbrigade


If the person’s answer is correct (in this case wolfbrigade) you can authenticate that person.

3. Trust manually the person.

/otr trust fingerprint


You can print on screen the key fingerprints to verify:

/otr contexts


Or your own key fingerprint:

/otr info


For example you can share the fingerprints via GPG-signed emails, if the person fingerprint matches with the one visualized on your client then you can assume you can trust that user.

/otr trust 6DAB45AA 5569FFAC EEFA5122 C5C501FF ECEC4BFC


Of course the fingerprint above is not real.
You should never copy / paste your fingerprint anywhere and share it with secure means of communications.

You can abort an authentication with:

/otr authabort

Distrust a fingerprint:

/otr distrust fingerprint

And remove it from fingerprints file:

/otr forget fingerprint