具有bind.so的多个OpenVPN客户端和绑定接口-不起作用

困惑的公众

编辑
在遵循@MariusMatutiae的到简介的链接之后,我通过编写脚本来生成路由表和规则解决了该问题policy routing


我试图在运行Minibian的Raspberry Pi上运行两个OpenVPN客户端,并使用bind.so将特定的应用程序(get_iplayer)绑定到其中一个VPN,如此此处所述我最初按照此处的指南进行操作按照此处的指示进行安装iproute,下载和编译bind.so


我正在使用由专用Internet访问提供的配置文件的VPN

一个VPN指向其瑞士服务器,使用udp,我已经设置了该选项dev tun0,因为我希望这是所有流量通过的主要隧道,但我通过使用明确声明的除外bind.so该隧道运行良好,所有流量似乎都通过了该隧道。

第二个VPN指向英国伦敦的服务器,使用tcp并dev tun1设置了选项作为第二条隧道。单独运行时此隧道工作正常我可以正确运行get_iplayer。

当我同时运行两个实例时,会发生问题。tun1即使当我尝试使用bind.so和LD_PRELOAD上面链接中说明方法时,似乎也没有流量通过该接口

bind.so
据我所知我已经编译bind.so正确,复制它/usr/lib,等无奈的是,我没有得到它的工作一次,但我不知道这是如何发生。


我一直在使用的命令ip route来查找网关地址;我确信我使用的是正确的IP地址。例如:

$ ip route
0.0.0.0/1 via 10.30.1.17 dev tun1 
0.0.0.0/1 via 10.198.1.5 dev tun0 
default via 192.168.1.254 dev eth0 
10.30.1.1 via 10.30.1.17 dev tun1 
10.30.1.17 dev tun1  proto kernel  scope link  src 10.30.1.18 
10.198.1.1 via 10.198.1.5 dev tun0 
10.198.1.5 dev tun0  proto kernel  scope link  src 10.198.1.6 
104.238.169.140 via 192.168.1.254 dev eth0 
128.0.0.0/1 via 10.30.1.17 dev tun1 
128.0.0.0/1 via 10.198.1.5 dev tun0 
179.43.177.66 via 192.168.1.254 dev eth0 
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.84 

然后运行:

BIND_ADDR="10.30.1.17" LD_PRELOAD=/usr/lib/bind.so get_iplayer --type=tv

导致没有连接,并且UK VPN的日志中也没有任何内容。

停止Switzerland VPN并运行相同的get_iplayer命令将导致连接和信息下载。ip route给出以下内容:

$ ip route
0.0.0.0/1 via 10.30.1.17 dev tun1 
default via 192.168.1.254 dev eth0 
10.30.1.1 via 10.30.1.17 dev tun1 
10.30.1.17 dev tun1  proto kernel  scope link  src 10.30.1.18
104.238.169.119 via 192.168.1.254 dev eth0 
128.0.0.0/1 via 10.30.1.17 dev tun1 
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.84

因此,据我打开或关闭不同VPN时的路由判断,ip地址没有任何变化,也没有发生任何奇怪的事情。

我不知道为什么bind.so似乎没有效果。没有输出到终端以显示其是否成功,并且我不确定在哪里寻找日志(如果它正在输出任何内容)(终端中的输出用于命令,即get_iplayer)。

显然,我可以运行cron作业/脚本来打开和关闭VPN,以允许我成功/通过UK VPN运行get_iplayer,但是我宁愿保持两个VPN都打开,让我所有的流量都通过tun0接口,并且仅tun1用于需要时使用get_player bind.so

任何人都可以提供帮助吗?如果我们不能解决此问题,那么为编写特定的路由表或get_iplayer流程规则提供一些帮助将非常有用。

谢谢。

马里乌斯·马图蒂亚

bind.so 并不是这个问题的原因,它是路由之一:在每个路由表中只能有一个默认网关,但是VPN的每个实例都尝试设置最适合它的网关(以及一般的路由),产生带有如下行的表:

  0.0.0.0/1 via 10.30.1.17 dev tun1 
  0.0.0.0/1 via 10.198.1.5 dev tun0 

内核要做什么呢?它应该通过tun0还是通过tun1路由?答案是:它不能真正路由,您的PC无法连接。

出路:

  1. 设置两个路由表,并有一条规则指示内核何时使用它们中的任何一个。这就是所谓的policy or source routing,您可以在这里找到它的简要介绍这很棘手,不是因为策略路由本身很困难),而是因为您必须自己设置OpenVPN的两个实例之一的路由,以确保将路由规则添加到另一个路由中桌子。但这是可以做到的,因为OpenVPN提供了一条语句

--route-nopull

与--client或--pull一起使用时,接受服务器EXCEPT推送的用于路由的选项。

这使您可以根据需要设置路由。

  1. 设置一个网络命名空间,在其中启动一个OpenVPN实例以及使用它的程序。您可以在此处找到有关网络名称空间的介绍这也需要一些工作,但主要是死记硬背。如果您愿意,我写的以下脚本(非常简单!)可以直接使用。

编辑

由于您是通过ssh会话进行工作的,因此我不得不对脚本进行一些修改。

您可以从以下开始

     newnsssh NameOfNNS start

但您仍会发现自己位于默认的网络名称空间(简称NNS)内。在访问它之前,最好打开一个终端:

     xterm &

如果您通过以下方式连接到RPI,这将打开图形终端

    ssh -Y me@rpi

所提供的$DISPLAY环境变量被设置为:

  export DISPLAY=localhost:10.0

打开之后xterm,进入它,然后发出以下命令:

   sudo ip netns exec NameOfNNS bash

新的提示位于新的NNS中;去检查,

    ip netns identify $$

如果未返回任何内容,则您位于默认的NNS中,否则将显示NameOfNNS。您现在可以启动OpenVPN

      openvpn --config /path/to/config/file &
      su YourName

到此为止。现在,从该xterm内,所有程序都将通过该OpenVPN实例进行路由,而在该xterm之外启动的所有程序,都将在OpenVPN之外启动,或者通过OpenVPN的另一个实例启动(如果您正巧制定了另一个实例)。

完成后,只需关闭,xterm然后在ssh会话中,

    newnsssh NameOfNNS stop

就这样。

#!/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.


# 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. 

export 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

 export IP=$($WHEREIS -b ip | /usr/bin/awk '{print $2}')
 export IPTABLES=$($WHEREIS -b iptables | /usr/bin/awk '{print $2}')

 if [ x$IP = x ] ; then
    echo "please install the iproute2 package"
    IERROR1=1
 fi

 if [ x$IPTABLES = x ] ; then
    echo "please install the iptables package"
    IERROR2=1
 fi


 if [[ $IERROR1 == 0 && $IERROR2 == 0 ]] 
    then
    :   
 else
    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. 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


    ICOUNTER=1
    export Nns=$ICOUNTER 
    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 
ln -s /proc/1/ns/net /var/run/netns/default 2> /dev/null
#   $IP netns exec $1 bash & $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. 


rm /var/run/netns/default
$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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

具有必需属性的MVC客户端验证不起作用

来自分类Dev

带有客户端图形和动态classbreakrenderer的打印任务不起作用

来自分类Dev

带有客户端图形和动态classbreakrenderer的打印任务不起作用

来自分类Dev

具有href绑定的图片不起作用

来自分类Dev

具有双向绑定的AngularJS指令不起作用

来自分类Dev

具有bindValue的PDO绑定不起作用

来自分类Dev

具有单个语句的多个PDO插入不起作用

来自分类Dev

具有多个选择的PHP SQL不起作用

来自分类Dev

ngIf具有多个|| (OR)条件不起作用

来自分类Dev

具有多个参数的MVC路由不起作用

来自分类Dev

具有多个值的Zabbix用户参数不起作用

来自分类Dev

具有多个条件的 if 语句不起作用

来自分类Dev

具有多个参数的猫鼬 findOne 不起作用

来自分类Dev

如果语句具有多个条件不起作用

来自分类Dev

具有多个匹配项的 Angular ngIf 不起作用

来自分类Dev

具有网络凭据的HttpWebResponse和代理不起作用

来自分类Dev

*ngIf 有多个条件不起作用

来自分类Dev

keyup和keydown在具有剔除绑定的表上不起作用

来自分类Dev

客户端排序不起作用

来自分类Dev

python多个客户端聊天不起作用

来自分类Dev

具有多个命令和标志的Git别名不起作用

来自分类Dev

具有多个参数和模型访问权限的耙任务不起作用

来自分类Dev

具有多个命令和标志的Git别名不起作用

来自分类Dev

显示和隐藏具有相同类名的多个div不起作用

来自分类Dev

WPF图像源绑定有时起作用有时不起作用

来自分类Dev

绑定不起作用?

来自分类Dev

绑定不起作用

来自分类Dev

带有滑块绑定的TranslateTransform不起作用

来自分类Dev

带有绑定的Perl SQLite DBI SELECT不起作用

Related 相关文章

热门标签

归档