Ubuntu 16.04 デスクトップで VPN クライアント用のトンネル アダプターを構成しますか?

Ubuntu 16.04 デスクトップで VPN クライアント用のトンネル アダプターを構成しますか?

カスタムVPN用のネットワーク設定を構成しようとしていますクライアント図書館。


わからないこと

C++ スクリプトがトンネルの読み取り/書き込みを行えるように、通常の VPN セットアップでトラフィックを転送できるようにする必要があります。間違っていなければ、セットアップは次のようになります。

       Normal Setup           How I think my setup should be
------------------------------------------------------------
Start → Aplication → Finish    Start → Aplication → Finish
          ↓   ↑                          ↓   ↑ 
       iface-enp0s3                   iface-enp0s3
          ↓   ↑                          ↓   ↑
        interwebs                      iface-tun1
                                         ↓   ↑
                                       c++ script
                                         ↓   ↑
                                       vpn-server
                                         ↓   ↑
                                       interwebs

私の C++ スクリプトは現在これを実行しておらず、アダプタからデータを読み取るだけであることはわかっていますtun1。当面は、それが私が達成しようとしていることのすべてです。ただし、ルートが適切に機能していないようです。

訪問するとhttp://google.comクライアント システムから、これらのパケットが C++ スクリプトに表示され、トラフィックが他の場所には送信されないことを確認したいです。

すべてのトラフィックを適切にルーティングできるようになったらポートを除くトンネル インターフェイスを使用して C++ スクリプト経由で VPN が接続されていることを確認したら、VPN クライアント ライブラリ経由で送信を開始します。

私の知る限り、C++ スクリプトは現在動作しています。10.0.0.2 (アダプタtun1) に ping すると、パケットが通過するのがわかります。

私はいくつかの異なることを試しました。具体的には次の通りです。

sudo iptables -t nat -A POSTROUTING --out-interface tun1 -j MASQUERADE
sudo iptables -A FORWARD --in-interface enp0s3 -j ACCEPT

これは機能しませんでした。

net.ipv4.ip_forward注:が に設定され1、 が実行されていることはすでに確認済みですsudo sysctl -p

現在の設定の詳細については以下を参照してください。

注: Ubuntu 16.04 デスクトップを実行しています。


現在のアダプター

注: enp0s3 はプライマリ アダプタです。これは仮想マシン上で実行されています。enp0s3 はインターネットへの接続です。

enp0s3    Link encap:Ethernet  HWaddr 08:00:27:ea:97:d2  
           inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
           inet6 addr: fe80::8ec8:60b7:f404:77c5/64 Scope:Link
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           RX packets:58668 errors:0 dropped:0 overruns:0 frame:0
           TX packets:39067 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:1000 
           RX bytes:39002535 (39.0 MB)  TX bytes:7442839 (7.4 MB)

tun1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
           inet addr:10.0.0.1  P-t-P:10.0.0.2  Mask:255.255.255.255
           inet6 addr: fe80::fed9:4107:8688:8501/64 Scope:Link
           UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
           TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:500 
           RX bytes:0 (0.0 B)  TX bytes:984 (984.0 B)

tun1アダプターの設定方法

$ sudo ip tuntap add dev tun1 mode tun

$ sudo ifconfig tun1 10.0.0.1 dstaddr 10.0.0.2 アップ


私が聞いているC++スクリプトtun1

 // Includes ommited.

 using namespace std;

 typedef void data_receiver(char* data, int length);

 struct receive_handle {
     data_receiver* receiver;
 } typedef receive_handle;

 // Function used to retrieve the interface.
 static int if_nametofd(char *name)
 {
     int interface = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
     ifreq ifr;
     memset(&ifr, 0, sizeof(ifr));
     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
     strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
     if (ioctl(interface, TUNSETIFF, &ifr)) {
         perror("Cannot get TUN interface");
         exit(1);
     }

     return interface;
 }

 // Called when a packet is received from the tun0 interface.
 void received_data(char* data, int length)
 {
     // Truncate the packet so that we only see the first 15 bytes.
     // This way we don't spam the console.
     for(int i=0; i<15; ++i)
         std::cout << std::hex << (int)data[i];

     std::cout << endl;
 }

 int main()
 {
     cout << "Getting interface..." << endl;

     int iface = if_nametofd("tun1");
     cout << "Using interface: " << iface << endl;

     cout << "Creating handler..." << endl;
     receive_handle* handle = (receive_handle*)malloc(sizeof(receive_handle));
     handle->receiver = received_data;

     char packet[1024];
     cout << "Listening..." << endl;
     while (true)
     {
         if (read(iface, packet, sizeof(packet)) > 0) {
             handle->receiver(packet, sizeof(packet));
         }
     }

     return 0;
 }

このスクリプトの唯一の目的は、アダプタをラッチしtun1、そこから継続的に読み取ることです。


答え1

ワークステーションのデフォルト ゲートウェイを変更する必要があります。次のコマンドを発行すると、システムのデフォルト ゲートウェイが表示されます。

ip route show table main
default via 1.2.3.4 dev wanif

ip route replace (man ip-route) を使用して変更できます。

さらに良い方法として、オープン VPN トリックを使用して、デフォルト ルートを削除せずに上書きすることができます (--redirect-gateway def1)。

これは、IPv4 アドレス空間全体をカバーする 2 つのルートを追加することで機能します。この 2 つのルートはそれぞれデフォルト ルートよりも具体的なので、デフォルト ルートは実質的に上書きされます。

これは次のように行われます。

ip route add 0.0.0.0/1 via 10.0.2.15 dev tun1
ip route add 128.0.0.0/1 via 10.0.2.15 dev tun1

ここで、10.0.2.15 はトンネルのローカル エンドポイントです。

スクリプトは、意味のあるトンネリング サービスを提供するために「通常のインターネット経由で」どこかに接続する必要があるため、上記のルールが適用されないように、次のようにリモート エンドポイントを追加する必要があります。

ip route add 7.8.9.10/32 via 1.2.3.4 dev wanif

ここで、7.8.9.10 はリモート エンドポイント、1.2.3.4 は ISP のデフォルト ゲートウェイです。

ルーティングルールの基本ルールを覚えておいてください。最も具体的なルールは、より具体的なルールよりも優先されます。

関連情報