TUN/TAP虛擬網絡設備為用戶空間程序提供了網絡數據包的發送和接收能力。他既可以當做點對點設備(TUN),也可以當做以太網設備(TAP)。
TUN/TAP虛擬網絡設備的原理:
在Linux內核中添加了一個TUN/TAP虛擬網絡設備的驅動程序和一個與之相關連的字符設備/dev/net/tun,字符設備tun作為用戶空間和內核空間交換數據的接口。當內核將數據包發送到虛擬網絡設備時,數據包被保存在設備相關的一個隊列中,直到用戶空間程序通過打開的字符設備tun的描述符讀取時,它才會被拷貝到用戶空間的緩沖區中,其效果就相當於,數據包直接發送到了用戶空間。通過系統調用write發送數據包時其原理與此類似。
1、tun設備
TUN 設備是一種虛擬網絡設備,通過此設備,程序可以方便地模擬網絡行為。
TUN 模擬的是一個三層設備,也就是說,通過它可以處理來自網絡層的數據,更通俗一點的說,通過它,我們可以處理 IP 數據包。
先來看看物理設備是如何工作的:
圖中的 eth0 是主機已有的真實的網卡接口 (interface)。
網卡接口 eth0 所代表的真實網卡通過網線(wire)和外部網絡相連,該物理網卡收到的數據包會經由接口 eth0 傳遞給內核的網絡協議棧(Network Stack)。然后協議棧對這些數據包進行進一步的處理。
對於一些錯誤的數據包,協議棧可以選擇丟棄;
對於不屬於本機的數據包,協議棧可以選擇轉發;
而對於確實是傳遞給本機的數據包,而且該數據包確實被上層的應用所需要,協議棧會通過 Socket API 告知上層正在等待的應用程序。
下面看看 TUN 的工作方式:
我們知道,普通的網卡是通過網線來收發數據包的話,而 TUN 設備比較特殊,它通過一個設備文件(/dev/tunX)收發數據包。
如上圖所示,tunX 和上面的 eth0 在邏輯上面是等價的, tunX 也代表了一個網絡接口,雖然這個接口是系統通過軟件所模擬出來的。
網卡接口 tunX 所代表的虛擬網卡通過文件 /dev/tunX 與我們的應用程序(App) 相連,應用程序每次使用 write 之類的系統調用將數據寫入該文件,這些數據會以網絡層數據包的形式,通過該虛擬網卡,經由網絡接口 tunX 傳遞給網絡協議棧。
同時該應用程序也可以通過 read 之類的系統調用,經由文件 /dev/tunX 讀取到協議棧向 tunX 傳遞的所有數據包。
協議棧可以像操縱普通網卡一樣來操縱 tunX 所代表的虛擬網卡:
比如,給 tunX 設定 IP 地址,設置路由,總之,在協議棧看來,tunX 所代表的網卡和其他普通的網卡區別不大,當然,硬要說區別,那還是有的,那就是 tunX 設備不存在 MAC 地址,這個很好理解,tunX 只模擬到了網絡層,要 MAC地址沒有任何意義。
如果是 tapX 的話,在協議棧的眼中,tapX 和真是網卡沒有任何區別!!!!
示例:
Tun/Tap都是虛擬網卡,沒有直接映射到物理網卡,是一種純軟件的實現。Tun是三層虛擬設備,能夠處理三層即IP包,Tap是二層設備,能處理鏈路層網絡包如以太網包。使用虛擬網絡設備,可以實現隧道,如OpenVPN的實現。
上面的圖中,左右兩邊分別為兩台機器。一台有一塊物理網卡配置了IP:172.16.1.11,這台機器的系統里有一個Tun(以Tun為例,不講Tap了)設備,配置了IP:192.168.1.11; 另一台的一塊物理網卡配置了IP:172.16.1.12,系統里有一個Tun設備並配置了IP:192.168.1.12。
左邊Linux系統里有一個Application,綁定到端口地址為: 192.168.1.11:5000,右邊Linux也有一個Application,綁定到端口地址為:192.168.1.12:5000,顯然它們綁定的都是Tun設備的IP,接着它們就通過這兩個地址通信了。
假設左邊的Application要給右邊的Application發送一個數據包,流程是這樣的:
左邊的Application並不知道什么虛擬網絡設備,它只知道往"192.168.1.12:5000"這個地址發送,左邊主機系統首先按正常的發包過程處理,比如判斷目的主機是不是位於同一網段等等,然后數據包就在Linux的網絡協議棧中穿行。Tun設備並不是真實的物理網卡,它不知道把數據包往哪里送,但是這些經過了Linux網絡協議棧的數據可以從Tun設備的文件描述符中讀取到,圖中的“User Program”就是監聽這個描述符等待讀取數據的。這個“User Program”程序綁定的端口地址是:172.16.1.11:6000,每當它從Tun設備讀到數據的時候,就把這些數據從物理網卡發送出去,目標地址是右邊的:172.168.1.12:6000。
數據到達右邊的系統,經過網絡協議棧之后到達“User Program”應用進程,“User Program”將接收到的數據往Tun設備對應的文件描述符寫入。對於Tun設備來說,“寫入”就像是物理網卡接受到數據包一樣,因此這些接收到的數據又進入了Linux的網絡協議棧,最終到達右邊的Application。
這里的Application是指各種各樣的用戶程序,如ping工具。“User Program”是用來輔助Tun設備來實現隧道功能的,可以想象成是OpenVPN進程,沒有它隧道就廢了!!!!
2、TAP設備
如圖所示,當備一個 TAP 設被創建時,在 Linux 設備文件目錄下將會生成一個對應 char 設備,用戶程序可以像打開普通文件一樣打開這個文件進行讀寫。
當執行write()操作時,數據進入 TAP 設備,此時對於 Linux 網絡層來說,相當於 TAP 設備收到了一包數據,請求內核接受它,如同普通的物理網卡從外界收到一包數據一樣,不同的是其實數據來自 Linux 上的一個用戶程序。Linux 收到此數據后將根據網絡配置進行后續處理,從而完成了用戶程序向 Linux 內核網絡層注入數據的功能。
當用戶程序執行read()請求時,相當於向內核查詢 TAP 設備上是否有需要被發送出去的數據,有的話取出到用戶程序里,完成 TAP 設備的發送數據功能。
針對 TAP 設備的一個形象的比喻是:
使用 TAP 設備的應用程序相當於另外一台計算機,TAP 設備是本機的一個網卡,他們之間相互連接。應用程序通過 read()/write()操作,和本機網絡核心進行通訊。
TAP 設備與 TUN 設備工作方式完全相同,區別在於:
1)TUN 設備是點對點的三層設備,處理IP分組,它只模擬到了 IP 層,即網絡層 我們可以通過 /dev/tunX 文件收發 IP 層數據包,它無法與物理網卡做 bridge,但是可以通過三層交換(如 ip_forward)與物理網卡連通。可以使用ifconfig等命令給該設備設定 IP 地址。
2)TAP 設備是一個二層虛擬以太網設備,處理以太網幀,它比 TUN 更加深入,通過 /dev/tapX 文件可以收發 MAC 層數據包,即數據鏈路層,擁有 MAC 層功能,可以與物理網卡做 bridge,支持 MAC 層廣播。同樣的,我們也可以通過ifconfig等命令給該設備設定 IP 地址,還可以給它設定 MAC 地址。
3)
TAP:子網掩碼是/24,255.255.255.0,對應以太網設備
TUN:子網掩碼是/30,255.255.255.252,點對點設備。
4)設備節點號不同:
2.4的核:TUN 設備號是36 16+,文件節點:/dev/tun0
2.6的核:TUN 設備號是10 200,文件節點:/dev/net/tun
OSI模型中的七層:
第一層是物理層
第二層是數據鏈路層(tap設備)
第三層是網絡層(tun設備)
第四層是傳輸層
第五層是會話層
第六層是表示層
第七層是應用層
3、VETH
VETH 設備出現較早,它的作用是反轉通訊數據的方向,需要發送的數據會被轉換成需要收到的數據,重新送入內核網絡層進行處理,從而間接的完成數據的注入。
VETH 設備總是成對出現,送到一端請求發送的數據總是從另一端以請求接受的形式出現。
該設備不能被用戶程序直接操作,但使用起來比較簡單。創建並配置正確后,向其一端輸入數據,VETH 會改變數據的方向並將其送入內核網絡核心,完成數據的注入。在另一端能讀到此數據
veth、tun、tap比對