Contourner le filtrage web en entreprise

Je suis fatigué et irrité par les politiques de filtrage web des grandes entreprises qui, pour des raisons de sécurité ou par manque de confiance envers leurs employés, appliquent un filtrage bien trop agressif sur leur trafic web de sortie.

J’avais rencontré ce problème sur mon premier poste en sortant d’école. Tous les employés étaient d’ailleurs pris pour des étudiants, puisque l’entreprise utilisait des listes de filtrages en usage dans les universités françaises. Impossible donc de consulter la carte de l’enseigne de restauration du coin (Jamais compris le gain de sécurité). Plus embêtant était le blocage pur et simple de gist, ou d’outils similaires – ce qui est quand même fort dommage quand, au détour d’une discussion web sur un problème technique, tout le monde pointe vers une solution à laquelle vous n’avez pas accès.

Comme d’habitude dans ces cas-là, certains employés ont trouvé une solution pour simplement pouvoir faire leur travail sans qu’on leur mette constamment des bâtons dans les roues. A l’époque, l’intégralité de mon équipe avait configuré son poste de travail pour que le trafic passe par le même proxy que celui utilisé par les machines qui hébergeaient nos environnements de développement et de test. Proxy qui était pas ou peu filtré.

Je pensais naïvement qu’en presque 10 ans, les choses s’étaient améliorées, et pourtant, je suis à nouveau confronté aux mêmes problèmes idiots. Un exemple parmi d’autres: récemment, le système de surveillance du trafic réseau du client chez lequel j’interviens a décidé de bloquer le site web de npm, à savoir https://www.npmjs.com. Plus d’accès à la documentation (sauf à trouver le dépôt des sources). Terminé la récupération des dépendances en local… Le blocage fut heureusement de courte durée, mais bon, c’est rapidement une journée de travail perdue pour les personnes concernées. 

Autre exemple, impossible de faire des recherches sur les technologies WebGL, et tout ce qui tourne autour des modèles 3D dans le navigateur. Pourquoi donc, me direz-vous ? Où est le danger ? Ce coup là, le blocage est effectué car ces sujets sont assimilés au domaine du jeu vidéo et donc bloqués de peur que les employées passent leur journée à jouer. Bravo, vous venez par la même occasion de vous assurer que l’entreprise n’innovera pas dans ce domaine, ou avec difficulté.

En fait, le problème est en général tellement courant, qu’on finit par apprendre que pour pouvoir travailler, une équipe entière s’est fait installer une connexion internet domestique pour son propre usage.

Revenons à nos moutons, filtrage excessif du trafic web: ras-le-bol. Pas de droits d’admin sur ma machine, et installations limitées au catalogue de logiciels autorisés… Je dispose par contre d’une machine virtuelle chez l’un des grands fournisseurs mondiaux de cloud (il faut bien trouver une manière de travailler quand tout est bloqué). La solution: utiliser cette machine comme nœud de sortie pour mon trafic web.

Pour ce faire, je dispose bien entendu d’une entrée dans mon fichier .ssh/config, de la forme:

Host proxy
  HostName <ip_machine_distante>
  User <username>
  IdentityFile <chemin_vers_le_fichier_pem>

A partir de là, je vais donc lancer un proxy SOCKS via ssh avec la commande: ssh proxy -N -D 9090.
-N précise qu’aucune commande ne sera exécutée sur l’hôte distant et -D pour utiliser, ici le port 9090, comme port sur la machine local exposant le proxy SOCKS.

Deuxième étape: télécharger Firefox en version portable pour disposer d’un navigateur sur lequel j’ai la main sur la configuration des paramètres de proxy: https://portableapps.com/apps/internet/firefox_portable .

Enfin, configurer notre Firefox en version portable pour utiliser notre proxy SOCKS. Dans la partie préférence, rechercher le terme proxy. Choisir ensuite “Manual proxy configuration”, et renseigner “127.0.0.1” dans “SOCKS Host” et “9090” dans “Port”. Conserver la case “SOCKS v5” cochée et valider.

Enfin, vérifier que l’url précédemment bloquée est accessible.

Dernière étape, aller chercher un café et le siroter en parcourant un web non filtré. Hourra !

Pour essayer de simplifier le lancement du proxy, j’ai créé 2 scripts: proxy.bat et start_proxy.sh. proxy.bat me sert de point d’entrée pour lancer le script principal start_proxy.sh via git bash, simplement en cliquant sur le fichier dans l’explorateur Windows.

"C:\Program Files\Git\bin\bash.exe" --login -i -c "C:/Users/<username>/APPS/start_proxy.sh"
# pause

Le script start_proxy.sh est quant à lui une copie inspirée d’un script partagé au détour d’un gist.

#! /bin/bash
# Inspired by: https://gist.github.com/scy/6781836?permalink_comment_id=2777535#gistcomment-2777535

set -eu
SOCKS_PROXY_PORT=9090
HOST=proxy

socket=$(mktemp -t deploy-ssh-socket.XXXXXX)
rm ${socket} # delete socket file so path can be used by ssh

exit_code=0

cleanup () {
    # Stop SSH port forwarding process, this function may be
    # called twice, so only terminate port forwarding if the
    # socket still exists
    if [ -S ${socket} ]; then
        echo
        echo "Sending exit signal to SSH process"
        ssh -S ${socket} -O exit ${HOST}
    fi
    exit $exit_code
}

trap cleanup EXIT ERR INT TERM

echo "Starting SOCKS proxy on port ${SOCKS_PROXY_PORT}"
# https://mpharrigan.com/2016/05/17/background-ssh.html
# Start SSH port forwarding process
ssh -M -S ${socket} -fNT -o ExitOnForwardFailure=yes -D ${SOCKS_PROXY_PORT} ${HOST}

# -f : Run in the background before command execution.
# -N : Do not execute a remote command; this is useful for just forwarding ports.
# -T : Disable pseudo-tty allocation.
# -S <socketname>: Use a control socket.
# -M : Put control socket in master mode.
# ExitOnForwardFailure : if set to "yes", the connection shall be terminated 
#   if ssh cannot set up all requested dynamic, tunnel, local, and remote port forwardings,
#   (e.g. if either end is unable to bind and listen on a specified port).
# -D <port>: Port on which to expose on the local machine.

ssh -S ${socket} -O check ${HOST}
# -O check,exit : Control command

# launching a shell here causes the script to not exit and allows you
#   to keep the forwarding running for as long as you want.
#   I also like to customise the prompt to indicate that this isn't a normal shell.

bash --rcfile <(echo 'PS1="\nwith-ports> "')

Le tout fonctionne plutôt, avec parfois une perte de connexion en revenant de la pause déjeuner, après une interruption trop longue de la connexion internet, ou une période d’inactivité. Dans cette situation, je ferme simplement la fenêtre “cmd” où tournait le script, et je relance le tout par un double clic sur mon premier fichier.

Simple, efficace et surtout fonctionnel.

Proxy

Lorsqu’on travaille derrière un proxy, on se retrouve vite à devoir configurer nos outils pour être certain que leur trafic passera bien par celui-ci. Voici donc quelques paramètres de configuration pour répondre à ce problème.

GNU/Linux

Les variables d’environnement qui nous intéresse sont les suivantes:

  • http_proxy
  • https_proxy
  • ftp_proxy
  • no_proxy

On peut également les retrouver en majuscule: HTTP_PROXY par exemple.

La configuration s’effectue de la manière suivante dans un terminal:

export http_proxy=http://yourproxyaddress:proxyport
export no_proxy='127.0.0.1, *.local'

Pour visualiser le contenu d’une variable:

echo $http_proxy

GNOME

gsettings set org.gnome.system.proxy ignore-hosts "['127.0.0.1','*.local' ]"

APT-GET/APTITUDE

Si aptitude n’utilise pas le proxy défini au niveau système pour une raison ou une autre, on peut modifier le fichier /etc/apt/apt.conf pour y ajouter la ligne suivante:

Acquire::http::Proxy "http://yourproxyaddress:proxyport";

GIT

git config --global http.proxy http://yourproxyadress:port
git config --global https.proxy http://yourproxyaddress:port

Si le proxy bloque le protocole git://, on force l’utilisation de http:// :

git config --global url."http://".insteadOf git://

Et en cas de problème avec le protocole https://, on peut envisager :

git config --global http.sslVerify false

WINDOWS

NPM

Dans le fichier .npmrc, ajouter les lignes:

proxy=http://yourproxyadress:port
strict-ssl = false

BOWER

Dans le fichier .bowerrc, ajouter les lignes:

{
  "proxy":"http://yourproxyadress:port",
  "https-proxy":"http://yourproxyadress:port"
}

12 lines proxy with Node.js and Request

Easy and simple http proxy using Node.js and request.

var request = require('request')
  , http = require('http')
  , port = 8888
  , host = 'localhost'
  , proxy = http.createServer(function (req, res) {
    var x = request(req.url)
    req.pipe(x)
    x.pipe(res)
  })
proxy.listen(port, host, function () {
  console.log('Proxy running on port ' + port);
})

Code available on Github: node-simple-proxy.

It would be great to support https. And of course, you can do it without request.