VPN sûr et efficace pour son NAS

Openmediavault_header_logoComme beaucoup ^^, j’utilise mon NAS pour stocker mes données (non, sérieux ?), mais aussi, notamment, pour télécharger des « films de vacances » et des ISO de distro NuNux 😉

Et comme on est jamais trop prudent à l’heure actuelle, que ce soit niveau vie privée, sécurité pure et simple, ou s’éviter des problèmes avec les Inquisiteurs de la Propriété intellectuelle, il m’était donc apparu nécessaire de palier à toute une série de problèmes/inconvénients.

Je me suis donc attelé à chercher des solutions existantes, sans toutefois trouver mon bonheur « clé sur porte », mais j’ai néanmoins trouvé une base de départ dans mes pérégrinations : le script de e-raw [@] e-raw.be (sur NAS-Forum si ma mémoire est bonne)

Détails concernant mon NAS et adaptations possibles à votre NAS

J’utilise un NAS home-made (je détaillerai une fois pour le fun la partie hardware), tournant sur OpenMediaVault (basé sur Debian 🙂 ), avec pour la partie téléchargement, les outils suivants : Transmission-BT, SabNZBd et JDownloader. Et pour le VPN : OpenVPN, cela va sans dire 😉

banner_omv

Vous allez me dire, c’est pas tout le monde qui fonctionne sous OpenMediaVault, etc etc…Effectivement 😉

La solution présentée dans ce tuto est très facilement adaptable à un NAS du commerce comme Synology, QNAP, … De même, le script est construit autour des 3 outils précédemment cités, mais s’adapte comme rien à tout autres outils ou services.

Mais que fait le script ?!

Ce script va vous permettre de (périodiquement) :

  • Vérifier que votre connexion OpenVPN est UP et la re-démarrer si nécessaire
  • Arrêter l’ensemble des outils/services lié au téléchargement (Transmission-BT, SabNZBd, JDownloader) en cas de déconnexion du VPN et les re-démarrer une fois la connexion VPN à nouveau UP
  • Ajouter dynamiquement à chaque (re)connexion du VPN, des règles iptables (Firewall), vous protégeant également avec cette connexion spécifique
  • Conserver une trace de toutes les opérations réalisées dans un fichier LOG dans /var/log/mycheck.log

Vous allez me dire, mais mon fournisseur VPN a déjà un Firewall !?

Effectivement, c’est sans doute le cas (il vaudrait mieux d’ailleurs ^^), mais d’une part, cela implique que vous avez une confiance aveugle en votre fournisseur et ses compétences, et d’autre part, dans un contexte post Snowden, il me paraît pas inutile de vous protéger également de votre fournisseur de VPN…On est jamais trop prudent 😉

De quoi avons-nous besoin ?

Je ne vais pas détailler comment configurer un connexion OpenVPN, ou l’installation des outils Transmission-BT/SabNZBd/JDownloader dans cet article. De plus, cette solution se voulant la plus « universelle » possible, je ne peux pas couvrir le cas de tout les NAS et de leurs spécificités.

Je vais donc supposer que tout cela est déjà fonctionnel sur votre NAS et détailler le tuto sur base d’une configuration OpenMediaVault standard.

Nous avons donc besoin de :

  • Une connexion OpenVPN configurée correctement avec les fichiers de configuration présents dans /etc/openvpn
  • Une authentification automatique pour OpenVPN : mot de passe contenu dans un fichier texte (auth.txt) + paramètre auth-user-pass auth.txt dans votre configuration OpenVPN
  • Transmission-BT, SabNZBd et JDownloader installés et configurés

Mise en place du script

Faites un copié/collé du script fourni en fin d’article dans un fichier texte sur votre NAS dans /usr/local/bin sous le nom mychecktun0.sh

nano /usr/local/bin/mychecktun0.sh

On le rend exécutable

chmod +x /usr/local/bin/mychecktun0.sh

Configuration du script

Nous allons maintenant configurer le script en lui-même.

Si vous fonctionnez avec OpenMediaVault, il n’y que les numéros de port et le nom de l’interface réseau de la connexion VPN à adapter.

Et éventuellement le chemin des outils si vous avez une config custom.

Pour les autres, chaque paramètre devra éventuellement être adapté.

Toute la partie configuration du script est en tout début de script, donc pas la peine de chercher partout.

Néanmoins, j’invite chacun, en fonction de ses connaissances, à parcourir celui-ci et à en comprendre le fonctionnement. Le script est abondement commenté, cela devrais faciliter les choses 😉

Pour déterminer le nom de l’interface réseau de votre VPN

ifconfig | grep -i link

Et cela donne

docker0   Link encap:Ethernet  HWaddr 02:42:f6:9f:0a:77  
eth0      Link encap:Ethernet  HWaddr AA:AA:AA:AA:AA:AA  
lo        Link encap:Boucle locale  
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00

Une autre méthode, plus propre

ip link

Et cela donne

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1503 qdisc mq state UP mode DEFAULT qlen 1000
    link/ether AA:AA:AA:AA:AA:AA brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether BB:BB:BB:BB:BB:BB brd ff:ff:ff:ff:ff:ff
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT 
    link/ether 02:42:f6:9f:0a:77 brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT qlen 100
    link/none

L’interface du VPN est ici tun0 (tun, comme tunnel).

Remarque : l’adresse MAC des interfaces eth0/1 sont fictives

Adaptez la configuration du script au besoin (c’est tun0 par défaut)

# interface réseau du VPN
interface="tun0"

Adapter les outils/services (Transmission-BT,SabNZBd,JDownloader,iptables)

Les paramètres service1/2/3 correspondent au noms des scripts init permettant de démarrer/stopper/… ces services (par exemple : service transmission-daemon start). Ces scripts se trouvent dans /etc/init.d.
Les paramètres process1/2/3 correspondent aux noms des processus tel que vous les verrez apparaître dans un ps auxw ou un top)

Voici les paramètres par défaut pour OpenMediaVault

# service Transmission
service1="transmission-daemon"
process1="transmission-daemon"
# service JDownloader
service2="jdownloader"
process2="JDownloader.jar"
# service SabNZBd
service3="sabnzbd"
process3="sabnzbd"

Et pour iptables

# chemin vers le binaire d'iptables
iptables="/sbin/iptables"

Adapter le port pour Transmission-BT

Vous devez adapter le port pour Transmission-BT en fonctio du port alloué à celui-ci par votre fournisseur VPN.

Remarque : n’oubliez-pas de modifier le port dans Transmission-BT également 😉

Modifiez le paramètre suivant

# port ouvert chez le provider du VPN pour Transmission
portTransmissionBT="24152"

Adapter si besoin, le chemin vers le fichier LOG + configurer un logrotate

Par défaut, le fichier log est créé dans /var/log (conseillé), mais vous pouvez le mettre où vous voulez.

Modifiez si besoin le paramètre suivant

# chemin vers le fichier de log
logfile="/var/log/mycheck.log"

Configurez un logrotate de ce fichier afin de ne pas vous retrouver un jour (quoi que peu probable vu la petite quantité de données) avec un fichier gigantesque et les problèmes qui pourraient en découler.

Pour cela, créez un fichier dans /etc/logrotate.d/ et nommez le mycheck

nano /etc/logrotate.d/mycheck

Et collez-y ceci

/var/log/mycheck.log
{
    rotate 4
    weekly
    size 20M
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        invoke-rc.d rsyslog restart > /dev/null
    endscript
}

Re-démarrez le service de log (rsyslog dans ce cas, mais cela peut-être un autre si vous n’êtez pas sous OpenMediaVault)

service rsyslog restart

Configuration de la vérification périodique via crontab

Afin que le script puisse être exécuté régulièrement (toutes les minute dans mon cas), il faut ajouter celui-ci dans crontab.

Pour cela

nano /etc/crontab

Et ajoutez-ci cette ligne

* * * * * root /usr/local/bin/mychecktun0.sh

Le script

#!/bin/bash
################################################################################
# CheckMyVPN                                                                   #
#   Author : Francois B. (Makotosan / Shakasan)                                #
#   Website : http://makotonoblog.be/                                          #
#   Email : shakasan [at] sirenacorp.be                                        #
#   Licence : GPLv3                                                            #
#   Features of this script :                                                  #
#     - check if the OpenVPN connexion is UP and restart it if necessary       #
#     - Stop/Start TransmissionBT/SabNZBd/JDownloader regarding the VPN status #
#     - add iptables rules for the OpenVPN when (re)start                      #
#   Howto use : see http://makotonoblog.be/vpn-sur-et-efficace-pour-son-nas/   #
################################################################################
#
# A ajouter dans /etc/logrotate.d/
#/var/log/mycheck.log
#{
#    rotate 4
#    weekly
#    size 20M
#    missingok
#    notifempty
#    compress
#    delaycompress
#    sharedscripts
#    postrotate
#        invoke-rc.d rsyslog restart > /dev/null
#    endscript
#}

heure=$(date +%H:%M)
jour=$(date +%d-%m-%Y)

# chemin vers le binaire d'iptables
iptables="/sbin/iptables"
# interface réseau du VPN
interface="tun0"
# service Transmission
service1="transmission-daemon"
process1="transmission-daemon"
# service JDownloader
service2="jdownloader"
process2="JDownloader.jar"
# service SabNZBd
service3="sabnzbd"
process3="sabnzbd"
# port ouvert chez le provider du VPN pour Transmission
portTransmissionBT="24152"
# chemin vers le fichier de log
logfile="/var/log/mycheck.log"

# le VPN est UP à nouveau et on redémarre les services (Transmission, SabNZBd, JDownloader)
# soit le VPN était déjà UP, mais un service s'est arrêté et sera redémarré
function reStartService () {
if (( $(ps -ef | grep -v grep | grep $2 | wc -l) > 0 ))
then
    # déjà UP, on log le status
    echo "> Service : "$1" : UP" >> $logfile
else
    # DOWN, on doit les démarrer !!!!
    echo "> Service : "$1" : (re)démarrage" >> $logfile
    service $1 start >> $logfile
fi
}

# si le VPN est Down, on doit stopper les services (Transmission, SabNZBd, JDownloader)
function stopService () {
if (( $(ps -ef | grep -v grep | grep $2 | wc -l) > 0 ))
then
    # on doit le stopper !!!!
    echo "> OpenVPN : DOWN !!  >>>  On stop "$1" !!" >> $logfile
    service $1 stop >> $logfile
else
    # déjà DOWN, on log le status
    echo "> Service : "$1" : DOWN" >> $logfile
fi
}

echo "--- "$jour" - "$heure" -----------------------------------------------" >> $logfile

if [ -n "$(ifconfig | grep "$interface")" ]; then # -----------------------------------------------------------------

    # le VPN est UP, on log le status
    echo "> OpenVPN : UP ("$interface")" >> $logfile

    # on vérifie s'il y a des régles iptables pour le VPN
    if [ -z "$($iptables -L -v | grep "$interface")" ]; then

        # on ouvre des ports pour TransmissionBT
        echo "> Iptable : Add rules : Begin" >> $logfile
        echo "> Iptable : Add rules : TransmissionBT : port "$portTransmissionBT >> $logfile
        $iptables -A INPUT -i $interface -p tcp --destination-port  $portTransmissionBT  -j ACCEPT >> $logfile
        $iptables -A INPUT -i $interface -p udp --destination-port  $portTransmissionBT  -j ACCEPT >> $logfile

        echo "> Iptables : Add rules : Other" >> $logfile
        $iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT >> $logfile

        $iptables -A INPUT -i $interface -p tcp -j DROP >> $logfile
        $iptables -A INPUT -i $interface -p udp -j DROP >> $logfile
        $iptables -A INPUT -i $interface -p icmp -j DROP >> $logfile
        echo "> Iptables : Add Rules : End" >> $logfile
    else
        # si les règles sont OK, on log le status
        echo "> Iptable : rules OK" >> $logfile
    fi # --------------------------------------------------------------

    # on (re)démarre les services (Transmission, SabNZBd, JDownloader)
    reStartService $service1 $process1
    reStartService $service2 $process2
    reStartService $service3 $process3

else #---------------------------------------------------------------------------------------------------------------

    # le VPN est DOWN, on log le status
    echo "> OpenVPN : DOWN !! ("$interface")" >> $logfile

    # on arrête les serices (Transmission, SabNZBd, JDownloader)
    stopService $service1 $process1
    stopService $service2 $process2
    stopService $service3 $process3

    # on redémarre le VPN !!!!
    echo "> OpenVPN : démarrage" >> $logfile
    service openvpn start >> $logfile

fi # ----------------------------------------------------------------------------------------------------------------

exit 0;

Conclusion

J’espère que ce script et ce tuto vous ont été utiles et, surtout, abordables et clairs.

N’hésitez pas à réagir dans les commentaires s’il y a une coquille ou simplement si vous avez une question ou une suggestion 😉