24

この問題を理解するのに苦労しています。Linux トンネル ドライバーと対話するプログラムを作成しようとしています。非常に基本的なレベルでは、ネットワーク トンネルを介してデータを転送できるアプリケーションを作成したいだけです。ただし、これを達成するためにトンネルドライバーを適切にセットアップする方法については、完全に途方に暮れています。

私は Ubuntu 9.04 で開発しており、トンネル ドライバー カーネル モジュールをロードしています。

デバイスは存在しますが、デバイス/dev/net/tunはありません/dev/tunX。を使用してこれらのデバイスを作成することができませんifconfig- を実行するたびに/sbin/ifconfig tun0 up、たとえば、次のエラーが表示されます。

tun0: インターフェイス フラグの取得中にエラーが発生しました: そのようなデバイスはありません。

デバイスを見ようとする/dev/net/tunと、次のエラーが表示されます。

cat: /dev/net/tun: ファイル記述子が不適切な状態です。

/dev/tunX基本的に、単純な小さなプログラムを介して開こうとしています

tun_fd = open( "/dev/tun0", O_RDWR )

-1 を返します: アプリケーションはルートとして実行されていますが、まだこのトンネル デバイスを開くことができません。を開くことは可能ですが、代わりに使用する新しいデバイスを/dev/net/tun生成するようには見えません。/dev/tunX

要約すると、Linux トンネル ドライバーを使用するアプリケーションを作成するにはどうすればよいでしょうか。どんな洞察も大歓迎です。

ありがとう; 〜ロバート

4

3 に答える 3

28

/dev/tunXデバイスファイルがありません。代わりに、 を開き、を「指す」/dev/net/tunように構成します。基本的な手順を示すために、コマンド ライン ツールを使用して TUN インターフェイスを作成し、その TUN デバイスから読み取る C コードを示します。したがって、コマンド ライン経由で tun インターフェイスを作成するには、次のようにします。ioctl()tun0ip tun tap

ip addr show # my eth0 inet address is 10.0.2.15/24 as Im running on a VirtualBox vm with Ubuntu 18.04 guest
sudo ip tuntap add mode tun dev tun0
sudo ip addr add 10.0.3.0/24 dev tun0  # give it an address (that does not conflict with existing IP)
sudo ip link set dev tun0 up  # bring the if up
ip route get 10.0.3.50  # check that packets to 10.0.3.x are going through tun0
# 10.0.3.50 dev tun0 src 10.0.3.0 uid 1000 
ping 10.0.3.50 # leave this running in another shell to be able to see the effect of the next example, nobody is responding to the ping

tun0が作成され、宛先 IP アドレス 10.0.3.x へのすべてのパケットが にルーティングされますtun0

/dev/net/tunユーザー空間プログラムからこのインターフェイスにパケットを読み書きするには、ioctl(). tun0インターフェイスに到着するパケットを読み取り、サイズを出力する例を次に示します。

#include <fcntl.h>  /* O_RDWR */
#include <string.h> /* memset(), memcpy() */
#include <stdio.h> /* perror(), printf(), fprintf() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <sys/ioctl.h> /* ioctl() */
#include <unistd.h> /* read(), close() */

/* includes for struct ifreq, etc */
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>

int tun_open(char *devname)
{
  struct ifreq ifr;
  int fd, err;

  if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
       perror("open /dev/net/tun");exit(1);
  }
  memset(&ifr, 0, sizeof(ifr));
  ifr.ifr_flags = IFF_TUN;
  strncpy(ifr.ifr_name, devname, IFNAMSIZ); // devname = "tun0" or "tun1", etc 

  /* ioctl will use ifr.if_name as the name of TUN 
   * interface to open: "tun0", etc. */
  if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
    perror("ioctl TUNSETIFF");close(fd);exit(1);
  }

  /* After the ioctl call the fd is "connected" to tun device specified
   * by devname ("tun0", "tun1", etc)*/

  return fd;
}


int main(int argc, char *argv[])
{
  int fd, nbytes;
  char buf[1600];

  fd = tun_open("tun0"); /* devname = ifr.if_name = "tun0" */
  printf("Device tun0 opened\n");
  while(1) {
    nbytes = read(fd, buf, sizeof(buf));
    printf("Read %d bytes from tun0\n", nbytes);
  }
  return 0;
}

ping 10.0.3.1またはping 10.0.3.40を実行している場合は、Read 88 bytes from tun0定期的に表示されます。

nc -u 10.0.3.3 2222テキスト + Enter を入力して netcat UDP を使用してテストすることもできます。

何も表示されない場合は、tun0 に割り当てられた ID アドレス / IP 範囲が到達可能 / ルーティング可能 / アドレス可能でない可能性が最も高いです。Linux カーネルが 10.0.3.4 へのパケットを tun0 デバイスに送信する必要があることを認識していることをip route get 10.0.3.4示すショーを確認してください。10.0.3.4 dev tun0

削除するにtun0

sudo ip link set dev tun0 down
sudo ip tuntap del mode tun dev tun0
于 2016-03-01T23:42:25.537 に答える
21

読んでください/usr/src/linux/Documentation/networking/tuntap.rst

あなたはデバイスに想定されてopen/dev/net/tunます。ioctl開いている fd で次のコマンドを実行すると、 tun0(または任意の名前を付けて) ネットワーク インターフェイスが作成されます。/dev/*Linux のネットワーク インターフェイスは、どのデバイスにも対応していません。

于 2009-06-16T20:30:34.183 に答える
3

これについての素晴らしい紹介チュートリアルに出くわしました

http://backreference.org/2010/03/26/tuntap-interface-tutorial/

ソース tarball が付属しています。

この質問と同じ一連の Google 検索結果に含まれていました。:-)

于 2012-05-30T04:42:19.080 に答える