GNU/Linux >> Tutoriels Linux >  >> Linux

Acheminez uniquement le trafic spécifique via VPN

Ce que vous demandez n'est pas exister. C'est pourquoi vous n'êtes pas satisfait des réponses que vous avez trouvées (certaines d'entre elles étant peut-être les miennes) :toutes ont suggéré des solutions de contournement , pas une véritable solution, qu'elle soit simple ou complexe.

Laisse-moi expliquer. Le routage dans tous les OS est déterminé par l'adresse de destination :vous pouvez très bien avoir plusieurs routes, mais le choix entre elles n'est pas basé sur l'application invoquant la connexion, mais simplement sur l'adresse de destination. Point final.

Laissez-moi vous donner un exemple non trivial. Lorsqu'un client VPN a établi une connexion avec son serveur, il est toujours possible d'acheminer une connexion vers un site donné, par exemple example.org, en dehors du VPN. Mais toutes les applications essayant d'atteindre cette adresse spéciale seront routées en dehors du VPN :certaines applications ne peuvent pas accéder à example.org via le VPN tandis que d'autres applications passent en dehors du VPN.

La situation devient plus riche avec le noyau Linux, qui permet le routage source :cela signifie que vous pouvez avoir deux tables de routage ou plus, et le choix entre elles est basé sur l'adresse source, pas sur l'adresse de destination.

Un exemple non trivial :mon pc a deux lignes extérieures, avec deux IP publiques distinctes. Il peut être contacté via l'une ou l'autre des interfaces, et il est important que mes réponses à une connexion donnée passent par la même interface que celle par laquelle la connexion est arrivée :sinon, elles seront rejetées comme non pertinentes lorsqu'elles parviendront à la personne qui a initié la connexion. C'est le routage source.

Assez juste, qu'en est-il des connexions que nous commençons ? Certaines applications vous permettent de spécifier l'adresse de liaison, comme le client openssh :

-b bind_address

Utilisez bind_address sur la machine locale comme adresse source de la connexion. Uniquement utile sur les systèmes avec plus d'une adresse.

Pour eux, il n'y a aucun problème à ce qu'une instance passe par le VPN (par exemple, la table de routage 1) tandis qu'une autre instance ira en dehors du VPN (par exemple, la table de routage 2). Mais d'autres applications, comme Firefox, sont non seulement notoirement difficiles à lier à une adresse IP source spécifique (mais voir ici pour une solution de contournement très intelligente), mais sont également méchantes et méchantes en ce sens qu'elles ne le feront pas vous permettent d'avoir deux copies d'eux-mêmes s'exécutant simultanément, chacune liée à une adresse source différente. En d'autres termes, alors que grâce à l'astuce référencée ci-dessus, vous pouvez obliger une instance à se lier à une adresse source de votre choix, vous ne pouvez pas en avoir une autre version se liant à l'autre adresse source.

Cela explique pourquoi nous utilisons des solutions de contournement :elles sont toutes basées sur la même idée, à savoir qu'elles fonctionnent avec une pile réseau distincte du reste du PC. Vous pouvez donc avoir, par ordre approximatif décroissant de complexité, des VM, des dockers, des conteneurs, des espaces de noms. Dans chacun d'eux, vous aurez une ou plusieurs tables de routage, mais vous pouvez avoir plusieurs instances de chacun (VM/dockers/containers/namespaces) et vous pouvez également les mélanger librement, chacun d'eux exécutant sa propre application comme Firefox heureusement séparés des autres.

Peut-être êtes-vous toujours intéressé par l'une des solutions de contournement ?

MODIF :

La solution de contournement la plus simple est un espace de noms réseau. Le script ci-dessous gère tous les aspects nécessaires d'un NNS :mettez-le dans un fichier (vous choisissez votre nom, j'utilise généralement newns , mais vous faites ce que vous préférez) dans /usr/local/bin , puis chmod 755 FILE_NAME , et vous pouvez l'utiliser comme suit :

       newns NAMESPACE_NAME start
       newns NAMESPACE_NAME stop

Cela ouvrira un xterm pour vous (c'est parce que j'aime que xterm fonctionne, mais vous pouvez le changer si vous souhaitez utiliser autre chose), qui appartient au nouvel espace de noms. Depuis l'intérieur du xterm, vous pouvez, si vous le souhaitez, démarrer votre vpn, puis démarrer votre jeu. Vous pouvez facilement vérifier que vous utilisez le VPN à l'aide de la commande suivante :

    wget 216.146.38.70:80 -O - -o /dev/null | cut -d" " -f6 | sed 's/<\/body><\/html>//'

qui vous renvoie votre adresse IP publique. Après avoir configuré le VPN dans le xterm, vous pouvez vérifier que votre IP publique est différente dans vos autres fenêtres. Vous pouvez ouvrir jusqu'à 254 xterms, avec 254 NNS différents et différentes connexions.

#!/bin/bash

#
# This script will setup an internal network 10.173.N.0/24; if this causes
# any conflict, change the statement below.

export IP_BASE=10.173

# It will open an xterm window in the new network namespace; if anything
# else is required, change the statement below.

export XTERM=/usr/bin/xterm

# The script will temporarily activate ip forwarding for you. If you
# do not wish to retain this feature, you will have to issue, at the 
# end of this session, the command
# echo 0 > /proc/sys/net/ipv4/ip_forward 
# yourself. 

 ###############################################################################

 WHEREIS=/usr/bin/whereis

 # First of all, check that the script is run by root:


 [ "root" != "$USER" ] && exec sudo $0 "[email protected]"

 if [ $# != 2 ]; then
    echo "Usage $0 name action"
    echo "where name is the network namespace name,"
    echo " and action is one of start| stop| reload."
    exit 1
 fi

 # Do we have all it takes?

 IERROR1=0
 IERROR2=0
 IERROR3=0
 export IP=$($WHEREIS -b ip | /usr/bin/awk '{print $2}')
 if [ $? != 0 ]; then
    echo "please install the iproute2 package"
    IERROR1=1
 fi

 export IPTABLES=$($WHEREIS -b iptables | /usr/bin/awk '{print $2}')
 if [ $? != 0 ]; then
    echo "please install the iptables package"
    IERROR2=1
 fi

 XTERM1=$($WHEREIS -b $XTERM | /usr/bin/awk '{print $2}')
 if [ $? != 0 ]; then
    echo "please install the $XTERM package"
    IERROR3=1
 fi
 if [ IERROR1 == 1 -o IERROR2 == 1 -o IERROR3 == 1 ]; then
    exit 1
 fi

 prelim() {

 # Perform some preliminary setup. First, clear the proposed 
 # namespace name of blank characters; then create a directory
 # for logging info, and a pid file in it; then determine 
 # how many running namespaces already exist, for the purpose
 # of creating a unique network between the bridge interface (to 
 # be built later) and the new namespace interface. Lastly, 
 # enable IPv4 forwarding. 

    VAR=$1
    export NNSNAME=${VAR//[[:space:]]}

    export OUTDIR=/var/log/newns/$NNSNAME

    if [ ! -d $OUTDIR ]; then
            /bin/mkdir -p $OUTDIR
    fi
    export PID=$OUTDIR/pid$NNSNAME

    # Find a free subnet

    ICOUNTER=0
    while true; do
            let ICOUNTER=ICOUNTER+1
            ip addr show | grep IP_BASE.$ICOUNTER.1 2>&1 1> /dev/null
            if [ ! $? == 0 -a $ICOUNTER -lt 255 ]; then
                    export Nns=$ICOUNTER
                    break
            elif [ ! $? == 0 -a $ICOUNTER -gt 254 ]; then
                    echo "Too many open network namespaces"
                    exit 1
            fi
    done
    if [ $Nns == 1 ]; then
            echo 1 > /proc/sys/net/ipv4/ip_forward
    fi

 }

 start_nns() {

 # Check whether a namespace with the same name already exists. 

    $IP netns list | /bin/grep $1 2> /dev/null
    if [ $? == 0 ]; then
            echo "Network namespace $1 already exists,"
            echo "please choose another name"
            exit 1
    fi

    # Here we take care of DNS

    /bin/mkdir -p /etc/netns/$1
    echo "nameserver 8.8.8.8" > /etc/netns/$1/resolv.conf
    echo "nameserver 8.8.4.4" >> /etc/netns/$1/resolv.conf
                                                                           

    # The following creates the new namespace, the veth interfaces, and
    # the bridge between veth1 and a new virtual interface, tap0.
    # It also assigns an IP address to the bridge, and brings everything up

    $IP netns add $1
    $IP link add veth-a$1 type veth peer name veth-b$1
    $IP link set veth-a$1 up
    $IP tuntap add tap$1 mode tap user root
    $IP link set tap$1 up
    $IP link add br$1 type bridge
    $IP link set tap$1 master br$1
    $IP link set veth-a$1 master br$1
    $IP addr add $IP_BASE.$Nns.1/24 dev br$1
    $IP link set br$1 up

    # We need to enable NAT on the default namespace

    $IPTABLES -t nat -A POSTROUTING -j MASQUERADE

    # This assigns the other end of the tunnel, veth2, to the new 
    # namespace, gives it an IP address in the same net as the bridge above, 
    # brings up this and the (essential) lo interface, sets up the 
    # routing table by assigning the bridge interface in the default namespace
    # as the default gateway, creates a new terminal in the new namespace and 
    # stores its pid for the purpose of tearing it cleanly, later. 

    $IP link set veth-b$1 netns $1
    $IP netns exec $1 $IP addr add $IP_BASE.$Nns.2/24 dev veth-b$1
    $IP netns exec $1 $IP link set veth-b$1 up
    $IP netns exec $1 $IP link set dev lo up
    $IP netns exec $1 $IP route add default via $IP_BASE.$Nns.1
    $IP netns exec $1 su -c $XTERM $SUDO_USER &
    $IP netns exec $1 echo "$!" > $PID



}

stop_nns() {

# Check that the namespace to be torn down really exists

    $IP netns list | /bin/grep $1 2>&1 1> /dev/null
    if [ ! $? == 0 ]; then
            echo "Network namespace $1 does not exist,"
            echo "please choose another name"
            exit 1
    fi

    # This kills the terminal in the separate namespace, 
    # removes the file and the directory where it is stored, and tears down
    # all virtual interfaces (veth1, tap0, the bridge, veth2 is automatically
    # torn down when veth1 is), and the NAT rule of iptables. 

    /bin/kill -TERM $(cat $PID) 2> /dev/null 1> /dev/null
    /bin/rm $PID
    /bin/rmdir $OUTDIR
    $IP link set br$1 down
    $IP link del br$1
    $IP netns del $1
    $IP link set veth-a$1 down
    $IP link del veth-a$1
    $IP link set tap$1 down
    $IP link del tap$1
    $IPTABLES -t nat -D POSTROUTING -j MASQUERADE
    /bin/rm /etc/netns/$1/resolv.conf
    /bin/rmdir /etc/netns/$1

}


case $2 in
    start)
            prelim "$1"
            start_nns $NNSNAME
            ;;
    stop)
            prelim "$1"
            stop_nns $NNSNAME
            ;;
    reload)
            prelim "$1"
            stop_nns $NNSNAME
            prelim "$1"
            start_nns $NNSNAME
            ;;
    *)
 # This removes the absolute path from the command name

            NAME1=$0
            NAMESHORT=${NAME1##*/}

            echo "Usage:" $NAMESHORT "name action,"
            echo "where name is the name of the network namespace,"
            echo "and action is one of start|stop|reload"
            ;;
 esac

Si vous le souhaitez, vous pouvez même démarrer un bureau entier à l'intérieur du nouvel espace de noms réseau, au moyen de

            sudo startx -- :2 

alors vous pouvez le rechercher en utilisant Alt +Ctrl +Fn , où Fn est l'un des F1,F2,....-

Je dois ajouter une mise en garde :la gestion DNS à l'intérieur des espaces de noms est un peu boguée, soyez patient.


Linux
  1. Ssh – Trafic de tunnel via une autre machine via Ssh ?

  2. Comment s'assurer que tout le trafic Internet ne passe que par Vpn ?

  3. Comment obtenir une adresse mémoire spécifique en utilisant C

  4. Surveiller le trafic TCP sur un port spécifique

  5. L'ajout d'une route à un hôte spécifique sort d'une interface spécifique

Ouvrez les ports et acheminez le trafic à travers votre pare-feu

Comment puis-je tunneliser tout mon trafic réseau via SSH ?

Comment router uniquement un sous-réseau spécifique (source IP) vers une interface particulière ?

Transférer le trafic http vers une autre adresse IP avec iptables

Limiter l'accès SSH à des clients spécifiques par adresse IP

Spécification de l'adresse IP pour les connexions sortantes sur un hôte multi-IP