你所要求的并没有存在。这就是为什么您对找到的答案不满意的原因(其中一些可能是我的):所有这些都提出了建议的解决方法,而不是简单或复杂的真正解决方案。
让我解释。所有操作系统中的路由均由目标地址决定:您可能有数条路由,但是它们之间的选择不是基于调用连接的应用程序,而是仅基于目标地址。句号
让我举一个简单的例子。当VPN客户端建立与其服务器的连接时,仍然可以将连接路由到VPN外部的给定站点,例如example.org。但是,所有尝试到达该特殊地址的应用程序都将路由到VPN外部:您不能让某些应用程序通过VPN进入example.org,而其他应用程序则通过VPN之外。
Linux内核允许源路由,这种情况变得更加丰富:这意味着您可以拥有两个或更多路由表,并且它们之间的选择取决于源地址,而不是目标地址。
一个不平凡的例子:我的电脑有两条外线,有两个不同的公共IP。可以通过任一接口进行联系,并且重要的是,我对给定连接的答复将通过与连接进入的接口相同的接口:否则,当它们到达发起连接的人员时,它们将被视为无关。这是源路由。
公平地说,我们开始的联系如何?一些应用程序允许您指定绑定地址,例如openssh客户端:
-b bind_address
使用本地计算机上的bind_address作为连接的源地址。仅在具有多个地址的系统上有用。
对于他们来说,让一个实例通过VPN(例如路由表1)而另一个实例将在VPN外部(例如路由表2)则没有问题。但其他应用程序,如Firefox,不仅是出了名的难绑定到特定的源IP地址(但看到这里的一个非常聪明的解决办法),但也有刻薄和肮脏的,因为它们不会让你有自己的两个副本同时运行,每个绑定到一个不同的源地址。换句话说,尽管由于上述技巧,您可以强制一个实例绑定到您选择的源地址,但是您不能让该实例的另一个版本绑定到另一个源地址。
这就解释了为什么我们使用变通方法:它们都基于相同的思想,即它们与PC的其余部分一起使用单独的网络堆栈。因此,您可以以降低复杂性的近似顺序获得虚拟机,泊坞窗,容器,名称空间。在它们的每一个中,您将都有一个或多个路由表,但是每个表都可以有多个实例(VM / docker /容器/命名空间),还可以自由地混合它们,其中的每一个都运行自己的应用程序,如Firefox从其他的。
也许您仍然对其中一种解决方法感兴趣?
编辑:
最简单的解决方法是网络名称空间。下面的脚本处理了NNS的所有必要方面:将其放在(然后newns
选择)文件中(通常选择您的名字,但您可以根据自己的喜好进行选择)/usr/local/bin
,然后chmod 755 FILE_NAME
可以按以下方式使用它:
newns NAMESPACE_NAME start
newns NAMESPACE_NAME stop
它将xterm
为您打开一个(属于我,因为xterm可以工作,但是如果您希望使用其他功能,则可以更改它),它属于新的命名空间。如果愿意,可以从xterm内部启动vpn,然后开始游戏。您可以通过以下命令轻松检查您是否正在使用VPN:
wget 216.146.38.70:80 -O - -o /dev/null | cut -d" " -f6 | sed 's/<\/body><\/html>//'
这将返回您的公共IP。在xterm中设置VPN后,您可以检查其他窗口中的公共IP是否不同。您最多可以打开254个xterm,其中包含254个不同的NNS和不同的连接。
#!/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
如果需要,您甚至可以通过以下方式在新的网络名称空间内启动整个桌面:
sudo startx -- :2
那么您可以使用Alt+ Ctrl+ 搜索它Fn,其中Fn是F1,F2,....-之一
我需要添加一个警告:名称空间内的DNS处理有点麻烦,请耐心等待。