web-dev-qa-db-ja.com

複数のOpenVPNクライアントとbind.soを使用したバインディングインターフェイス-機能しません

編集
@ MariusMatutiaeのpolicy routingの紹介へのリンクをたどった後、ルーティングテーブルとルールを生成するスクリプトを作成することで問題を解決しました。


Minibianを実行しているRaspberryPiで2つのOpenVPNクライアントを実行し、説明されているように、bind.soを使用して特定のアプリケーション(get_iplayer)をVPNの1つにバインドしようとしています ここ および ここ 。私はもともとガイドに従いました ここiprouteをインストールし、そこで指示されているようにbind.soをダウンロードしてコンパイルしました。

VPN
Private InternetAccessが提供する設定ファイルを使用しています。

1つのVPNはスイスのサーバーを指し、udpを使用します。これを、dev tun0を使用して明示的に宣言したものを除いて、すべてのトラフィックが通過するメイントンネルにしたいので、オプションbind.soを設定しました。このトンネルは正常に機能し、すべてのトラフィックがトンネルを通過しているようです。

2番目のVPNは、英国のロンドンサーバーを指し、tcpを使用し、オプションdev tun1が2番目のトンネルとして機能するように設定されています。このトンネルは、実行すると正常に機能しているように見えますそれ自体。 get_iplayerを正しく実行できます。

この問題は、両方のインスタンスを同時に実行すると発生します。上記のリンクで説明されているように、bind.soとtun1アプローチを使用しようとしても、トラフィックはLD_PRELOADインターフェイスを通過しないようです。

bind.so
bind.soを適切にコンパイルし、/usr/libなどにコピーしたことを知っている限り。イライラすることに、動作させましたonceしかし、それがどのように発生したのかわかりません。 。

コマンド
ゲートウェイアドレスを見つけるために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の接続はなく、ログにも何も記録されません。

スイスの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を開閉し、get_iplayerを正常に/ UK VPN経由で実行できるようにすることはできますが、両方のVPNを開いたままにし、すべてのトラフィックをtun0インターフェイスを通過させて使用するだけです。 tun1を使用する必要がある場合のget_playerのbind.so

誰かが助けを提供できますか?この問題を解決できない場合は、get_iplayerプロセスの特定のルーティングテーブルまたはルールを作成するためのヘルプが必要です。

ありがとう。

1
confusedpublic

bind.soはこの問題の原因ではなく、ルーティングの1つです。すべてのルーティングテーブルにはデフォルトゲートウェイが1つしかありませんが、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. どちらかをいつ使用するかをカーネルに指示するルールを使用して、2つのルーティングテーブルを設定します。これはpolicy or source routingと呼ばれ、簡単な紹介があります ここ 。これはトリッキーです。ポリシールーティング自体(これは簡単です)のためではなく、OpenVPNの2つのインスタンスのうちの1つのルーティングを自分で設定する必要があるためです。ルーティングルールがotherルーティングテーブルに追加されていることを確認します。しかし、それは可能です。なぜなら OpenVPNはステートメントを提供します

-route-nopull

--clientまたは--pullとともに使用する場合、ルートを除いてサーバーによってプッシュされたオプションを受け入れます。

これにより、必要に応じてルーティングを設定できます。

  1. OpenVPNのoneインスタンスを開始するネットワーク名前空間とそれを使用するプログラムをセットアップします。ネットワーク名前空間の概要を見つけます ここ 。それにも多少の作業が必要ですが、ほとんどは暗記作業です。必要に応じて、私が作成した次のスクリプト(非常に単純です!)はそのままで機能します。

[〜#〜]編集[〜#〜]

あなたはsshセッションから作業しているので、スクリプトを少し変更する必要がありました。

あなたはそれを始めることができます

     newnsssh NameOfNNS start

ただし、デフォルトのネットワーク名前空間(略してNNS)内にいることに気付くでしょう。アクセスする前に、ターミナルを開くことをお勧めします。

     xterm &

これにより、RPIに接続したグラフィック端末が開きます

    ssh -Y me@rpi

andただし、$DISPLAY環境変数が次のように設定されている場合:

  export DISPLAY=localhost:10.0

xtermを開いた後、そこに移動し、次のコマンドを発行します。

   Sudo ip netns exec NameOfNNS bash

新しいプロンプトは新しいNNSにあります。チェックする、

    ip netns identify $$

何も返されない場合は、defaultNNSになります。それ以外の場合は、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
0
MariusMatutiae