O que você está pedindo não existe não . É por isso que você está insatisfeito com as respostas que encontrou (algumas delas, possivelmente, sendo minhas): todas elas sugeriram soluções alternativas , não uma solução genuína, simples ou complexa.
Deixe-me explicar. O roteamento em todos os sistemas operacionais é determinado pelo endereço de destino: você pode muito bem ter várias rotas, mas a escolha entre elas não se baseia no aplicativo invocando a conexão, mas simplesmente no endereço de destino. Ponto final.
Deixe-me dar um exemplo não trivial. Quando um cliente VPN estabeleceu uma conexão com seu servidor, ainda é possível rotear uma conexão para um determinado site, digamos exemplo.org, fora da VPN. Mas todos os aplicativos que tentam acessar esse endereço especial serão encaminhados para fora da VPN: você não pode ter alguns aplicativos indo para example.org através da VPN, enquanto outros aplicativos passam fora da VPN.
A situação fica mais rica com o kernel Linux, que permite o roteamento de origem: isso significa que você pode ter duas ou mais tabelas de roteamento e a escolha entre elas é baseada no endereço de origem, não no endereço de destino.
Um exemplo não trivial: meu pc tem duas linhas externas, com dois IPs públicos distintos. Ele pode ser contatado através de qualquer interface, e é importante que minhas respostas a uma determinada conexão passem pela mesma interface que a conexão entrou: senão elas serão descartadas como irrelevantes quando atingirem a pessoa que iniciou a conexão. Este é o roteamento de origem.
Justo, e as conexões que começamos? Alguns aplicativos permitem que você especifique o endereço de ligação, como o cliente openssh :
-b bind_address
Use bind_address on the local machine as the source address of the connection. Only useful on systems with more than one address.
Para eles, não há problema em ter uma instância passando pela VPN (digamos, tabela de roteamento 1) enquanto outra instância sairá da VPN (digamos, tabela de roteamento 2). Mas outros aplicativos, como o Firefox, não são apenas notoriamente difíceis de se vincular a um endereço IP de origem específico (mas veja
Isso explica por que usamos soluções alternativas: todas elas são baseadas na mesma ideia, que funcionam com uma pilha de rede separada do que o resto do pc. Assim, você pode ter, em ordem decrescente de complexidade, VMs, janelas de encaixe, contêineres, namespaces. Em cada um deles você terá uma ou mais tabelas de roteamento, mas você pode ter várias instâncias de cada (VM / dockers / containers / namespaces) e você também pode misturá-las livremente, cada uma delas executando seu próprio aplicativo como o Firefox felizmente separado dos outros.
Talvez você ainda esteja interessado em uma das soluções alternativas?
EDITAR:
A solução mais simples é um namespace de rede. O script abaixo trata de todos os aspectos necessários de um NNS: coloque-o em um arquivo (você escolhe seu nome, geralmente uso newns
, mas você faz o que preferir) em /usr/local/bin
, depois chmod 755 FILE_NAME
e você pode usar da seguinte forma:
newns NAMESPACE_NAME start
newns NAMESPACE_NAME stop
Ele abrirá um xterm
para você (isso porque eu gosto que o xterm funcione, mas você pode alterá-lo se quiser usar qualquer outra coisa), que pertence ao novo namespace. De dentro do xterm você pode, se desejar, iniciar sua vpn e depois iniciar seu jogo. Você pode facilmente verificar se está usando a VPN através do seguinte comando:
wget 216.146.38.70:80 -O - -o /dev/null | cut -d" " -f6 | sed 's/<\/body><\/html>//'
que retorna seu IP público. Depois de configurar a VPN no xterm, você pode verificar se o seu IP público é diferente em suas outras janelas. Você pode abrir até 254 xterms, com 254 NNSs diferentes e conexões diferentes.
#!/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
Se você quiser, você pode até mesmo iniciar uma área de trabalho inteira dentro do novo namespace de rede, por meio de
sudo startx -- :2
então você pode procurá-lo usando Alt + Ctrl + Fn , onde Fn é um dos F1, F2, .... -
Eu preciso adicionar uma ressalva: o tratamento de DNS dentro dos namespaces é um pouco problemático, seja paciente.