Was Sie verlangen, existiert nicht . Aus diesem Grund sind Sie mit den Antworten, die Sie gefunden haben, unzufrieden (einige davon sind möglicherweise meine): Alle haben Problemumgehungen vorgeschlagen , keine echte Lösung, weder einfach noch komplex.
Lassen Sie mich erklären. Das Routing in allen Betriebssystemen wird durch die Zieladresse bestimmt: Möglicherweise haben Sie mehrere Routen, aber die Wahl zwischen diesen basiert nicht auf der Anwendung, die die Verbindung aufruft, sondern lediglich auf der Zieladresse. Punkt.
Lassen Sie mich ein nicht triviales Beispiel geben. Wenn ein VPN-Client eine Verbindung zu seinem Server hergestellt hat, ist es weiterhin möglich, eine Verbindung zu einer bestimmten Site, z. B. example.org, außerhalb des VPN weiterzuleiten. Alle Anwendungen, die versuchen, diese spezielle Adresse zu erreichen, werden jedoch außerhalb des VPN weitergeleitet: Einige Anwendungen können nicht über das VPN zu example.org geleitet werden, während andere Apps außerhalb des VPN übertragen werden.
Mit dem Linux-Kernel, der das Quellrouting ermöglicht, wird die Situation reicher: Dies bedeutet, dass Sie zwei oder mehr Routingtabellen haben können und die Auswahl zwischen diesen auf der Quelladresse und nicht auf der Zieladresse basiert.
Ein nicht triviales Beispiel: Mein PC hat zwei Amtsleitungen mit zwei unterschiedlichen öffentlichen IPs. Es kann über beide Schnittstellen kontaktiert werden, und es ist wichtig, dass meine Antworten auf eine bestimmte Verbindung über dieselbe Schnittstelle erfolgen, über die die Verbindung hergestellt wurde. Andernfalls werden sie als irrelevant verworfen, wenn sie die Person erreichen, die die Verbindung hergestellt hat. Dies ist Quellrouting.
Fair genug, was ist mit Verbindungen, die wir beginnen? In einigen Apps können Sie die Bindungsadresse angeben, z. B. im openssh-Client :
-b bind_address
Verwenden Sie bind_address auf dem lokalen Computer als Quelladresse der Verbindung. Nur nützlich auf Systemen mit mehr als einer Adresse.
Für sie ist es kein Problem, wenn eine Instanz das VPN durchläuft (z. B. Routing-Tabelle 1), während eine andere Instanz das VPN verlässt (z. B. Routing-Tabelle 2). Andere Apps wie Firefox sind jedoch nicht nur notorisch schwer an eine bestimmte Quell-IP-Adresse zu binden (siehe hier für eine sehr clevere Problemumgehung), sondern auch gemein und böse, da Sie nicht zwei Kopien von sich selbst haben können läuft gleichzeitig und ist jeweils an eine andere Quelladresse gebunden. Mit anderen Worten, während Sie dank des oben genannten Tricks eine Instanz zur Bindung an eine Quelladresse Ihrer Wahl verpflichten können, können Sie keine andere Version davon an die andere Quelladresse binden lassen.
Dies erklärt, warum wir Problemumgehungen verwenden: Sie basieren alle auf der gleichen Idee, dass sie mit einem separaten Netzwerkstapel arbeiten als der Rest des PCs. Sie können also in abnehmender ungefährer Reihenfolge der Komplexität VMs, Docker, Container und Namespaces verwenden. In jeder von ihnen haben Sie eine oder mehrere Routing-Tabellen, aber Sie können mehrere Instanzen von jeder haben (VM / Docker / Container / Namespaces) und Sie können sie auch frei mischen, wobei jede von ihnen ihre eigene App wie Firefox ausführt, glücklich getrennt von den anderen.
Vielleicht interessieren Sie sich noch für eine der Problemumgehungen?
BEARBEITEN:
Die einfachste Lösung ist ein Netzwerk-Namespace. Das Skript unten Griffe alle notwendigen Aspekte eines NNS und legt es in einer Datei (Sie Ihren Namen wählen, verwende ich im Allgemeinen newns
, aber Sie tun , was Sie bevorzugen) in /usr/local/bin
, dann chmod 755 FILE_NAME
, und Sie können es wie folgt verwendet werden :
newns NAMESPACE_NAME start
newns NAMESPACE_NAME stop
Es wird ein xterm
für Sie geöffnet (das liegt daran, dass xterm gerne funktioniert, aber Sie können es ändern, wenn Sie etwas anderes verwenden möchten), das zum neuen Namespace gehört. Wenn Sie möchten, können Sie aus dem xterm heraus Ihren VPN starten und dann Ihr Spiel starten. Mit dem folgenden Befehl können Sie leicht überprüfen, ob Sie das VPN verwenden:
wget 216.146.38.70:80 -O - -o /dev/null | cut -d" " -f6 | sed 's/<\/body><\/html>//'
Das gibt Ihnen Ihre öffentliche IP zurück. Nach dem Einrichten des VPN in xterm können Sie überprüfen, ob sich Ihre öffentliche IP in Ihren anderen Fenstern unterscheidet. Sie können bis zu 254 xterms mit 254 verschiedenen NNSs und verschiedenen Verbindungen öffnen.
#!/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 "$@"
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
Wenn Sie möchten, können Sie mit sogar einen ganzen Desktop im neuen Netzwerk-Namespace starten
sudo startx -- :2
dann können Sie mit Alt+ Ctrl+ danach suchen Fn, wobei Fn einer von F1, F2, ....- ist
Ich muss eine Einschränkung hinzufügen: Die DNS-Behandlung in Namespaces ist etwas fehlerhaft, seien Sie geduldig.