Wiki [Tuto] Se connecter à son OpenVPN depuis son LAN et WAN malgré routeur pas compatible hairpinning

0
26
sept.
2017

Sommaire

Introduction

Pour une raison suspicieuse, les box des Fournisseurs d'Accès Internet (FAI) sont régulièrement incompatible avec le hairpinning. Pour outrepasser ce problème, nous allons simplement dupliquer le fichier de conf (.ovpn) afin qu'un soit compatible avec le LAN et un avec internet (WAN). Ensuite nous lancerons un script au démarrage de la machine qui décidera quel fichier de conf (.ovpn) il faut lancer en fonction de si votre serveur est sur le même réseau ou non.
Ce script est compatible avec les tunnels SSH (au choix en local ou en wan ou même les deux ou aucun).

Mise en place sur le client

Note : pour ce tuto je pars du principe que votre OpenVPN est déjà installé et le port ouvert sur le routeur du réseau du serveur (par défaut 1194).

  1. Copiez le fichier de configuration de votre client OpenVPN, nous allons ajouter _LAN dans le titre du nouveau fichier
sudo cp /etc/openvpn/monUser.ovpn cp /etc/openvpn/monUser_LAN.ovpn 
  1. Éditez la copie qui nous servira pour le LAN
sudo nano /etc/openvpn/monUser_LAN.ovpn
  • A la ligne commençant par "remote", rajoutez _LAN dans le nom de domaine (ou remplacez le nom de domaine par l'IP LAN statique de votre serveur OpenVPN).
remote www.server_LAN.com 1194
  1. Ensuite éditez votre fichier /etc/hosts afin d'y indiquer la correspondance entre notre nouveau nom de domaine dédié au LAN et l'adresse IP du serveur OpenVPN.
sudo nano /etc/hosts
  • Ajoutez une ligne du style
192.168.1.42       www.server_LAN.com
  1. Créez le script de lancement /opt/scripts/vpnSwitcher.bash (CTRL+X pour sauver & quitter)
sudo nano /opt/scripts/vpnSwitcher.bash
  1. Puis collez le script suivant et adaptez le à votre config

Note : source du script

#!/bin/bash
# -- vpnSwitcher --
#  -> WTFPL - infos script : https://www.0rion.netlib.re/forum4/viewtopic.php?f=9&t=646&p=1460#p1460
# -> code by voxdemonix <-
# -> V1.11 (2017/09/11) <-
# uncomment next line for debug
#set -x

if [ ! "$SUDO_USER" ]; then
echo "!!! i need root !!!"
exit 0
fi

    #SCRIPTS OPTIONS
LANG="fr" # notification service ; accept : fr, usa (default)
notificationType="notify" # accept : echo; notify, nothing. Notify not work with root user.

    # NETWORK OPTIONS
INTERFACE="tun"
hostnameVpnLAN="192.168.1.69" # (VPN1 hostname) l'adresse IP locale (LAN) de votre serveur OpenVPN
MacVpnLocal="69:69:69:69:69:69" #l'adresse mac de votre serveur OpenVPN (tapez ifconfig dans un terminal sur votre server)

    # VPN OPTIONS
fichierOvpnLAN="/etc/openvpn/myUser_LAN.ovpn" # (VPN1) le PATH de votre fichier de conf .ovpn en LAN
fichierOvpnNotLAN="/etc/openvpn/myUser.ovpn" # (VPN2) le PATH de votre fichier de conf .ovpn pour les connnexions WAN/SSH
openVpn1Param=" " # add options (ex: --route-nopull) for openvpn connexion to server 1 (lan)
openVpn2Param=" " # add options (ex: --route-nopull) for openvpn connexion to server 2 (ssh/tor/wan)

    # SSH OPTIONS
hosnameVpnNotLAN="blablablablablabla.onion" # (VPN2 hostname)
UserLocalForSshTunneling="daenerys" # l'user a utiliser sur votre ordinateur pour le montage du tunnel (celui qui a exporté sa clés)
UserRemoteForSshTunneling="proxy-ssh" # l'user a utiliser côté server ( /!\ n'utilisez jamais root !)
portEntree="1194" # le port sur le pc local, par défaut 1194 (tcp)
portSortie="1194" # le port sur le serveur, par défaut 1194 (tcp)
sshLanEnable=0  # 0 for disable ; 1 for enable : enable or disable the ssh tunneling in LAN
sshNotLanEnable=0 # 0 for disable ; 1 for enable : enable or disable the ssh tunneling in Wan | Tor



            # NOTIFICATION SYSTEM
function vpnNotification {
        # $1 = message ID (watch switch/case);
        # $2 = hostnameVPN
    message=""
    #hostnameVPN=$(cat "$2" | grep "remote " | sed 's/remote //g' | sed 's/ [[:digit:]]\+//g')
    hostnameVPN=$2

    case $LANG in
        fr )
                case $1 in
                    VpnDisabled )
                            message="Connexion VPN fermée ($hostnameVPN)"
                        ;;
                    VpnConnecting )
                            message="Connexion VPN en cours ($hostnameVPN)"
                        ;;
                    VpnEnabled )
                            message="VPN Connecté ! ($hostnameVPN)"
                        ;;
                    SshStop )
                            message="Tunnel SSH STOP ($hostnameVPN)"
                        ;;
                    SshStart )
                            message="Tunnel SSH START ($hostnameVPN)"
                        ;;
                    * )
                            message="message inconnu"
                        ;;
                esac
            ;;
        usa | *)
                case $1 in
                    VpnDisabled )
                            message="VPN Connection Close ($hostnameVPN)"
                        ;;
                    VpnConnecting )
                            message="VPN Connection in progress ($hostnameVPN)"
                        ;;
                    VpnEnabled )
                            message="VPN Connected ! ($hostnameVPN)"
                        ;;
                    SshStop )
                            message="SSH Tunneling STOP ($hostnameVPN)"
                        ;;
                    SshStart )
                            message="SSH Tunneling START ($hostnameVPN)"
                        ;;
                    * )
                            message="unknow message"
                        ;;
                esac
            ;;
    esac


    case $notificationType in
        echo)
                echo "$message"
            ;;
        notify)
                notify-send "$message"
            ;;
        nothing | *)
            ;;
    esac
}

function quitOpenVPN {
        # $1 = ovpn ( $fichierOvpnLAN, $fichierOvpnNotLAN)
        # $2 = hostnameVPN ( $hostnameVpnLAN, $hosnameVpnNotLAN)
        ovpn=$1
        hostVPN=$2
            #stop VPN
        if [ $(pkill -c -f $ovpn) -gt 0 ]; then
        hostnameVPN=$(cat $ovpn | grep "remote " | sed 's/remote //g' | sed 's/ [[:digit:]]\+//g')
        vpnNotification "VpnDisabled" $hostnameVPN
        fi
            #stop ssh
        if [ $(pkill -c -f "autossh.*$UserRemoteForSshTunneling@$hostVPN") -gt 0 ]; then
            vpnNotification "SshStop" $hostVPN
        fi
        sleep 1
}

function startOpenVPN {
        # $1 = hostname VPN ($hostnameVpnLAN, $hosnameVpnNotLAN)
        # $2 = ovpn ($fichierOvpnLAN, $fichierOvpnNotLAN)
        # $3 = ssh enable (1) or not (0) ($sshLanEnable, $sshNotLanEnable)
        # $4 = OpenVpn Param ($openVpn1Param, $openVpn2Param)

        hostVPN=$1
        ovpn=$2
        sshChoice=$3
        openvpnParam=$4

                # SSH TUNNELING
            if [ $sshChoice == 1 ]; then
                    # kill oprevious ssh tunneling
                for pid in `ps -ef | grep "[a]utossh" | grep "$hostVPN" | awk '{print $2}'` ; do kill $pid ; done
                    # creat new ssh tunneling
                su $UserLocalForSshTunneling -c "autossh -M 0 -q -N -o 'ServerAliveInterval 60' -o 'ServerAliveCountMax 3' -L $portEntree:127.0.0.1:$portSortie $UserRemoteForSshTunneling@$hostVPN -f"
                if ps -aux | grep "[a]utossh" | grep "$hostVPN"  | grep -v "grep" >> /dev/null 2>&1; then
                    vpnNotification "SshStart" $hostVPN
                fi
            fi

                # START OpenVPN
            openvpn --daemon $openvpnParam --config $ovpn

                # NOTIFICATIONS
            hostnameVPN=$(cat $ovpn | grep "remote " | sed 's/remote //g' | sed 's/ [[:digit:]]\+//g')
            vpnNotification "VpnConnecting" $hostnameVPN

                # boucle qui permet de verifier si le VPN se connecte bien
        stop=0
        while [ $stop -lt 10 ]
        do       # temps d'attente entre chaque tentative
            if ifconfig | grep -iq $INTERFACE; then
                    vpnNotification "VpnEnabled" $hostnameVPN
                    stop=10
                    exit
            fi
                sleep 5
               stop=$((stop+1))
        done

}



        # boucle qui permet d'attendre que le réseau soit connecté
stop="0"
while [ $stop -lt 1 ]
do
    sleep 3       # temps d'attente entre chaque tentative

    _IP=$(hostname -I) || true
    if [ "$_IP" ]; then
            stop=1
    fi
done

if ps -aux | grep "[o]penvpn" >> /dev/null 2>&1; then
    #Connexion VPN active

            # vpn server 1
        quitOpenVPN $fichierOvpnLAN $hostnameVpnLAN
            # vpn server 2
        quitOpenVPN $fichierOvpnNotLAN $hosnameVpnNotLAN


else

        ping $hostnameVpnLAN -c 2 >> /dev/null 2>&1
        macRecover=$(arp -n | grep -i -o $MacVpnLocal)

        if [ "$macRecover" == "$MacVpnLocal" ]; then
        #        echo "local/LAN/First VPN"
            startOpenVPN $hostnameVpnLAN $fichierOvpnLAN $sshLanEnable $openVpn1Param

        else
        #        echo "tor/wan/second VPN"
            startOpenVPN $hosnameVpnNotLAN $fichierOvpnNotLAN $sshNotLanEnable $openVpn2Param

        fi

fi
  • Éditez les valeurs suivantes

    • hostnameVpnLAN="192.168.1.69" => (VPN1 hostname) l'adresse IP locale (LAN) de votre serveur OpenVPN
    • MacVpnLocal="69:69:69:69:69:69" => l'adresse mac de votre serveur OpenVPN (tapez ifconfig dans un terminal sur votre server)
    • fichierOvpnLAN="/etc/openvpn/myUser_LAN.ovpn" => (VPN1) le PATH de votre fichier de conf .ovpn en LAN
    • fichierOvpnNotLAN="/etc/openvpn/myUser.ovpn" => (VPN2) le PATH de votre fichier de conf .ovpn pour les connnexions WAN/SSH
  1. Sauvez et quittez avec CTRL+X, puis rendez votre fichier exécutable
sudo chmod +x /opt/scripts/vpnSwitcher.bash
  1. Lancez ensuite le script afin de le tester
sudo /opt/scripts/vpnSwitcher.bash

S'il fonctionne correctement, ajoutez le au démarrage du client soit via /etc/rc.local soit via cron

sudo crontab -e
  1. Ajoutez enfin la ligne suivante (CTRL+X pour sauver et quitter)
@reboot     /opt/scripts/vpnSwitcher.bash
  • # Un peu d'aide

    Posté par . Évalué à 2 (+0/-0).

    Salut !
    Merci pour ce tuto, il me servira sûrement dans quelques temps.

    Vue que tu as l'air d'avoir quelques compétence sur le sujet je te pose un souci que j'ai en ce moment.
    Je suis en train de me faire un routeur derrière ma box (192.168.1.X). J'ai mis un VPN qui fonctionne bien. Le problème est que je ne peux plus accéder au réseau local qui se trouve entre la box et le routeur (192.168.0.X), le disque de la partie TV de la box par exemple.
    Dans la conf d'Open VPN j'ai mis

    redirect-gateway def1
    route 192.168.0.0 255.255.0.0 net_gateway
    

    La première ligne redirige tout le traffic vers le tunel et de ce que j'ai compris la deuxième ligne fait une exception pour les adresses locales … mais ça ne semble pas fonctionner et je ne comprend pas trop pourquoi. Si tu as une idée.

    • [^] # Re: Un peu d'aide

      Posté par . Évalué à 1 (+1/-0). Dernière modification le 01/10/17 à 19:52.

      Tu as testé route 192.168.0.0 255.255.255.0 net_gateway ?

      Dans ton fichier /etc/openvpn/server.conf :

      • Si tu veux que les machines communiquent entre elles en LAN sans passer par le VPN, commentes (mettre un # devant) la ligne push "route 192.168.1.0 255.255.255.0". (c'est conseillé pour les machines mobiles pour éviter d'éventuels conflits lors de la connexion sur un autre réseau)

      • Si tu ne veux pas forcer tout le trafic à passer par le VPN tu peux aussi commenter push "redirect-gateway def1" (a ce moment les communications ne passent par le VPN que lorsque tu contactes une IP interne au VPN (10.8.0.1 par exemple))

      Merci pour ce tuto

      2 rien :)

      Si ce n'est libre,cela n'existe. Donation bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

      • [^] # Re: Un peu d'aide

        Posté par . Évalué à 2 (+0/-0).

        En fait je me rend compte que je n'ai pas dit que c'est le routeur qui a le VPN en tant que client. Les machines derrière le routeur ne savent pas qu'elles passent par un VPN. Donc c'est bien l'ensemble du traffic qui doit passer par le VPN, hormis le réseau local.

        Pour le «255.255.255.0», en fait le routeur à 4 carte réseau. Je n'en n'exploite qu'une pour l'instant mais a terme j'aimerais bien faire une DMZ sur une des cartes. C'est pour cela que j'ai mis le masque un peu plus large. Mais je vais essayer quand même, on ne sait jamais.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.