通用 TUN/TAP 裝置驅動程式¶
版權所有 © 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
Linux、Solaris 驅動程式 版權所有 © 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
FreeBSD TAP 驅動程式 版權所有 © 1999-2000 Maksim Yevmenkin <m_evmenkin@yahoo.com>
本文件 2002 年修訂版 Florian Thiel <florian.thiel@gmx.net>
1. 描述¶
TUN/TAP 為使用者空間程式提供資料包接收和傳輸。它可以被看作是一個簡單的點對點或乙太網裝置,它不是從物理介質接收資料包,而是從使用者空間程式接收資料包,並且不是透過物理介質傳送資料包,而是將資料包寫入使用者空間程式。
為了使用該驅動程式,程式必須開啟 /dev/net/tun 併發出相應的 ioctl() 來向核心註冊網路裝置。 網路裝置將顯示為 tunXX 或 tapXX,具體取決於選擇的選項。 當程式關閉檔案描述符時,網路裝置和所有相應的路由將消失。
根據選擇的裝置型別,使用者空間程式必須讀取/寫入 IP 資料包(使用 tun)或乙太網幀(使用 tap)。 具體使用哪種取決於 ioctl() 中給出的標誌。
來自 http://vtun.sourceforge.net/tun 的軟體包包含兩個如何使用 tun 和 tap 裝置的簡單示例。 這兩個程式都像兩個網路介面之間的橋樑。 br_select.c - 基於 select 系統呼叫的橋接。 br_sigio.c - 基於非同步 io 和 SIGIO 訊號的橋接。 然而,最好的例子是 VTun http://vtun.sourceforge.net :))
2. 配置¶
建立裝置節點
mkdir /dev/net (if it doesn't exist already) mknod /dev/net/tun c 10 200設定許可權
e.g. chmod 0666 /dev/net/tun允許非 root 使用者訪問裝置沒有壞處,因為建立網路裝置或連線到不屬於相關使用者的網路裝置需要 CAP_NET_ADMIN。 如果您想建立持久裝置並將它們的所有權授予非特權使用者,那麼您需要 /dev/net/tun 裝置可供這些使用者使用。
驅動模組自動載入
確保您的核心中啟用了“核心模組載入器” - 模組自動載入支援。 核心應該在第一次訪問時載入它。
手動載入
手動插入模組
modprobe tun如果您以後者的方式進行操作,則每次需要時都必須載入模組,如果您以前者的方式進行操作,則在開啟 /dev/net/tun 時會自動載入該模組。
3. 程式介面¶
3.1 網路裝置分配¶
char *dev 應該是具有格式字串的裝置名稱(例如“tun%d”),但(就我所見)這可以是任何有效的網路裝置名稱。 請注意,字元指標會被實際裝置名稱覆蓋(例如“tun0”)
#include <linux/if.h>
#include <linux/if_tun.h>
int tun_alloc(char *dev)
{
struct ifreq ifr;
int fd, err;
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 )
return tun_alloc_old(dev);
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
*/
ifr.ifr_flags = IFF_TUN;
if( *dev )
strscpy_pad(ifr.ifr_name, dev, IFNAMSIZ);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
close(fd);
return err;
}
strcpy(dev, ifr.ifr_name);
return fd;
}
3.2 幀格式¶
如果未設定標誌 IFF_NO_PI,則每個幀格式為
Flags [2 bytes]
Proto [2 bytes]
Raw protocol(IP, IPv6, etc) frame.
3.3 多佇列 tuntap 介面¶
從 3.8 版本開始,Linux 支援多佇列 tuntap,它可以使用多個檔案描述符(佇列)來並行傳送或接收資料包。 裝置分配與之前相同,如果使用者想要建立多個佇列,則必須多次呼叫帶有 IFF_MULTI_QUEUE 標誌的 TUNSETIFF,並使用相同的裝置名稱。
char *dev 應該是裝置的名稱,queues 是要建立的佇列數,fds 用於儲存和返回建立給呼叫者的檔案描述符(佇列)。 每個檔案描述符都用作佇列的介面,使用者空間可以透過該介面訪問。
#include <linux/if.h>
#include <linux/if_tun.h>
int tun_alloc_mq(char *dev, int queues, int *fds)
{
struct ifreq ifr;
int fd, err, i;
if (!dev)
return -1;
memset(&ifr, 0, sizeof(ifr));
/* Flags: IFF_TUN - TUN device (no Ethernet headers)
* IFF_TAP - TAP device
*
* IFF_NO_PI - Do not provide packet information
* IFF_MULTI_QUEUE - Create a queue of multiqueue device
*/
ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE;
strcpy(ifr.ifr_name, dev);
for (i = 0; i < queues; i++) {
if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
goto err;
err = ioctl(fd, TUNSETIFF, (void *)&ifr);
if (err) {
close(fd);
goto err;
}
fds[i] = fd;
}
return 0;
err:
for (--i; i >= 0; i--)
close(fds[i]);
return err;
}
引入了一個新的 ioctl(TUNSETQUEUE) 來啟用或停用佇列。 使用 IFF_DETACH_QUEUE 標誌呼叫它時,佇列將被停用。 使用 IFF_ATTACH_QUEUE 標誌呼叫它時,佇列將被啟用。 透過 TUNSETIFF 建立佇列後,預設情況下會啟用佇列。
fd 是我們想要啟用或停用的檔案描述符(佇列),當 enable 為 true 時,我們啟用它,否則我們停用它
#include <linux/if.h>
#include <linux/if_tun.h>
int tun_set_queue(int fd, int enable)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
if (enable)
ifr.ifr_flags = IFF_ATTACH_QUEUE;
else
ifr.ifr_flags = IFF_DETACH_QUEUE;
return ioctl(fd, TUNSETQUEUE, (void *)&ifr);
}
通用 TUN/TAP 裝置驅動程式 常見問題解答¶
TUN/TAP 驅動程式支援哪些平臺?
目前驅動程式已為 3 個 Unix 編寫
Linux 核心 2.2.x、2.4.x
FreeBSD 3.x、4.x、5.x
Solaris 2.6、7.0、8.0
TUN/TAP 驅動程式用於什麼?
如上所述,TUN/TAP 驅動程式的主要目的是隧道。 VTun 使用它 (http://vtun.sourceforge.net)。
使用 TUN/TAP 的另一個有趣的應用程式是 pipsecd (http://perso.enst.fr/~beyssac/pipsec/),這是一個使用者空間 IPSec 實現,可以使用完整的核心路由(與 FreeS/WAN 不同)。
虛擬網路裝置實際上是如何工作的?
虛擬網路裝置可以被視為一個簡單的點對點或乙太網裝置,它不是從物理介質接收資料包,而是從使用者空間程式接收資料包,並且不是透過物理介質傳送資料包,而是將資料包傳送到使用者空間程式。
假設您在 tap0 上配置了 IPv6,那麼每當核心向 tap0 傳送 IPv6 資料包時,它都會傳遞給應用程式(例如 VTun)。 該應用程式加密、壓縮並透過 TCP 或 UDP 將其傳送到另一端。 另一端的應用程式解壓縮和解密接收到的資料,並將資料包寫入 TAP 裝置,核心處理該資料包,就像它來自真正的物理裝置一樣。
TUN 驅動程式和 TAP 驅動程式有什麼區別?
TUN 使用 IP 幀。 TAP 使用乙太網幀。
這意味著使用 tun 時必須讀取/寫入 IP 資料包,使用 tap 時必須讀取/寫入乙太網幀。
BPF 和 TUN/TAP 驅動程式有什麼區別?
BPF 是一個高階資料包過濾器。 它可以附加到現有的網路介面。 它不提供虛擬網路介面。 TUN/TAP 驅動程式確實提供了虛擬網路介面,並且可以將 BPF 附加到此介面。
TAP 驅動程式是否支援核心乙太網橋接?
是的。 Linux 和 FreeBSD 驅動程式支援乙太網橋接。