欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux tun虛擬網(wǎng)卡通信的使用解讀

 更新時間:2025年05月28日 09:52:16   作者:wifi chicken  
這篇文章主要介紹了Linux tun虛擬網(wǎng)卡通信的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

什么是linux tun設(shè)備

Linux TUN 設(shè)備是一種虛擬網(wǎng)絡(luò)設(shè)備,用于在用戶空間和內(nèi)核空間之間建立數(shù)據(jù)通道,使用戶空間程序可以通過這個設(shè)備與內(nèi)核網(wǎng)絡(luò)棧進行交互。TUN 設(shè)備是一種通用的網(wǎng)絡(luò)隧道設(shè)備,常用于實現(xiàn)虛擬專用網(wǎng)絡(luò)(VPN)和其他網(wǎng)絡(luò)隧道技術(shù)。

TUN 設(shè)備的工作原理

將網(wǎng)絡(luò)數(shù)據(jù)包從用戶空間發(fā)送到內(nèi)核空間,或者從內(nèi)核空間發(fā)送到用戶空間??梢允瞻l(fā)第三層數(shù)據(jù)報文包,如IP封包,這使得用戶空間的應(yīng)用程序可以讀取和處理傳入的數(shù)據(jù)包,然后將數(shù)據(jù)包發(fā)送回TUN 設(shè)備,再由內(nèi)核負責將數(shù)據(jù)包發(fā)送到目標地址。

在使用 TUN 設(shè)備時,用戶空間程序通常會打開 TUN 設(shè)備文件,并像讀寫普通文件一樣對其進行讀寫操作。這樣,用戶空間程序就可以將網(wǎng)絡(luò)數(shù)據(jù)包發(fā)送到 TUN 設(shè)備或者從 TUN 設(shè)備讀取接收到的數(shù)據(jù)包。TUN 設(shè)備通常具有一個虛擬的 IP 地址,作為與內(nèi)核網(wǎng)絡(luò)棧進行交互的入口和出口

基本處理框架

  • 創(chuàng)建 TUN 設(shè)備: 在 Linux 系統(tǒng)中,可以使用 ip 命令或者其他網(wǎng)絡(luò)管理工具來創(chuàng)建 TUN 設(shè)備。
  • 用戶空間應(yīng)用程序與 TUN 設(shè)備交互: 用戶空間的應(yīng)用程序通常會打開 TUN 設(shè)備文件,這類似于打開普通文件。例如,應(yīng)用程序可以打開 /dev/net/tun 設(shè)備文件。
  • 數(shù)據(jù)包傳輸: 當用戶空間的應(yīng)用程序向 TUN 設(shè)備文件寫入數(shù)據(jù)包時,數(shù)據(jù)包將被發(fā)送到內(nèi)核空間的 TUN 設(shè)備驅(qū)動程序。這個過程是由內(nèi)核的 TUN/TAP 驅(qū)動來完成的。
  • 內(nèi)核處理: 內(nèi)核中的 TUN/TAP 驅(qū)動程序接收從用戶空間傳入的數(shù)據(jù)包。對于 TUN 設(shè)備,它會將數(shù)據(jù)包解析為 IP 數(shù)據(jù)包,并將其發(fā)送到內(nèi)核網(wǎng)絡(luò)棧進行進一步處理。
  • 數(shù)據(jù)包處理: 在內(nèi)核網(wǎng)絡(luò)棧中,數(shù)據(jù)包將按照路由表和網(wǎng)絡(luò)配置進行處理。如果數(shù)據(jù)包的目標地址與本地網(wǎng)絡(luò)或者路由表匹配,那么數(shù)據(jù)包將被內(nèi)核轉(zhuǎn)發(fā)到目標地址。
  • 接收數(shù)據(jù)包: 當內(nèi)核收到其他網(wǎng)絡(luò)設(shè)備傳入的數(shù)據(jù)包(如網(wǎng)絡(luò)接口收到的數(shù)據(jù)包),如果目標地址是 TUN 設(shè)備的 IP 地址,那么數(shù)據(jù)包將被傳遞給 TUN 設(shè)備驅(qū)動程序。
  • 用戶空間讀?。?數(shù)據(jù)包通過 TUN 設(shè)備驅(qū)動程序傳遞到用戶空間的應(yīng)用程序打開的 TUN 設(shè)備文件。應(yīng)用程序可以讀取這些數(shù)據(jù)包并進行處理。

如下是框架流程圖:

linux tun設(shè)備可以用作什么技術(shù)

  • VPN(Virtual Private Network): TUN 設(shè)備可用于構(gòu)建 VPN。通過將數(shù)據(jù)包從用戶空間發(fā)送到內(nèi)核空間,再通過TUN 設(shè)備進行加密、隧道封裝和傳輸,可以實現(xiàn)安全的遠程訪問和數(shù)據(jù)傳輸。
  • 隧道技術(shù): TUN 設(shè)備也可用于其他隧道技術(shù),如隧道模式下的 IPv6-over-IPv4 和 IPv4-over-IPv6 隧道。它允許不同網(wǎng)絡(luò)之間通過隧道進行通信。
  • 加密通信: TUN 設(shè)備可以用于實現(xiàn)端到端的加密通信,保護數(shù)據(jù)的安全性和隱私。
  • 虛擬專用網(wǎng)絡(luò): 使用 TUN 設(shè)備,可以創(chuàng)建虛擬專用網(wǎng)絡(luò)(VPN)或虛擬局域網(wǎng)(VLAN),將不同的網(wǎng)絡(luò)或子網(wǎng)連接在一起。
  • 網(wǎng)絡(luò)隔離: TUN 設(shè)備可以用于實現(xiàn)網(wǎng)絡(luò)隔離,將不同的應(yīng)用程序或服務(wù)隔離在不同的虛擬網(wǎng)絡(luò)中,增強網(wǎng)絡(luò)的安全性。
  • 協(xié)議代理: TUN 設(shè)備還可以用作協(xié)議代理,允許用戶空間應(yīng)用程序處理特定的網(wǎng)絡(luò)協(xié)議,例如將 UDP 或 TCP 流量進行自定義處理。
  • 網(wǎng)絡(luò)測試和仿真: 利用 TUN 設(shè)備,可以在用戶空間中模擬網(wǎng)絡(luò)環(huán)境,用于測試和仿真網(wǎng)絡(luò)應(yīng)用程序的性能和穩(wěn)定性。

本文今天要完成什么?

使用虛擬機ubuntu 自帶tun驅(qū)動完成:

  • 虛擬驅(qū)動的啟動
  • 應(yīng)用層發(fā)包給虛擬網(wǎng)卡驅(qū)動tun并寫入設(shè)備節(jié)點文件,應(yīng)用層完成讀取,加密,寫入設(shè)備節(jié)點并發(fā)送給協(xié)議棧
  • 使用tcpdump工具抓取包驗證是否正確發(fā)送與接收

完成框架

  • 利用已有的tun設(shè)備驅(qū)動,打開并配置ip,添加靜態(tài)路由表
  • 寫兩個應(yīng)用層進程,分別完成數(shù)據(jù)發(fā)送到tun和數(shù)據(jù)接收處理加密并發(fā)回tun驅(qū)動

linux已經(jīng)自帶驅(qū)動:

ubuntu:/dev/net$ ls 
tun

應(yīng)用層代碼1:

基本邏輯:

  • 打開虛擬設(shè)備網(wǎng)卡
  • 添加靜態(tài)路由
  • 阻塞等待數(shù)據(jù)的到來
  • read后,再進行wirite操作
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <linux/if_tun.h>
#include<stdlib.h>
#include<stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define IP_VERSION 4
#define IP_HEADER_LENGTH 20 // IPv4頭部長度,單位為字節(jié)
#define DEST_IP "10.0.0.2"

struct iphdr {
    unsigned char  ihl_version;
    unsigned char  tos;
    unsigned short total_length;
    unsigned short id;
    unsigned short frag_off;
    unsigned char  ttl;
    unsigned char  protocol;
    unsigned short checksum;
    unsigned int   saddr;
    unsigned int   daddr;
};
int tun_alloc(int flags)
{
    struct ifreq ifr;
    int fd, err;
    char *clonedev = "/dev/net/tun";
    if ((fd = open(clonedev, O_RDWR)) < 0) {
        return fd;
    }
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = flags;

    if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) {
        close(fd);
        return err;
    }
    system("sudo ifconfig tun0 10.0.0.1 up");//啟動tun虛擬網(wǎng)卡
    system("sudo route add -net 10.0.0.2 netmask 255.255.255.255 dev tun0");//將所有發(fā)送到 10.0.0.2 的數(shù)據(jù)包,通過網(wǎng)絡(luò)接口 "tun0" 進行傳輸,而且這個目標地址被視為一個單獨的主機,而不是一個整個網(wǎng)絡(luò)。
    system("sudo route add -net 192.168.6.1 netmask 255.255.255.255 dev tun0");
    printf("Open tun/tap device: %s for reading...\n", ifr.ifr_name);

    return fd;
}

int main()
{

            int tun_fd, nread;
            char buffer[1500];
            char buffer1[IP_HEADER_LENGTH + 100]; // IP頭部長度 + 應(yīng)用層數(shù)據(jù)長度        
            tun_fd = tun_alloc(IFF_TUN | IFF_NO_PI);
            if (tun_fd < 0) 
            {
            perror("Allocating interface");
            exit(1);
            }
while (1) {
            //發(fā)送數(shù)據(jù)包到TUN/TAP設(shè)備
            memset(buffer,0,sizeof(buffer));
            //讀取協(xié)議棧發(fā)送來的信息
            nread = read(tun_fd, buffer, sizeof(buffer));
            if (nread < 0) {
            close(tun_fd);
            exit(1);
            }
            printf("Read %zd bytes from tun/tap device\n", nread);
            // 以十六進制格式輸出IP數(shù)據(jù)包
            for (int i = 0; i < nread; i++) {
            printf("%02X ", buffer[i]);
            if ((i + 1) % 16 == 0) {
            printf("\n");
            }
            }
            printf("\n");
            // 構(gòu)造 IP 數(shù)據(jù)包頭部,此處就可以進行數(shù)據(jù)加密,具體的功能未完成,可自行加密處理
            struct iphdr *ip_header = (struct iphdr *)buffer1;
            ip_header->ihl_version = (IP_VERSION << 4) | (IP_HEADER_LENGTH / 4);
            ip_header->tos = 0;
            ip_header->total_length = htons(IP_HEADER_LENGTH + 8); // IP 頭部長度 + ICMP 數(shù)據(jù)長度
            ip_header->id = 0;
            ip_header->frag_off = 0;
            ip_header->ttl = 64;
            ip_header->protocol = 1;//IPPROTO_ICMPCMP 協(xié)議
            ip_header->checksum = 0; // 留空,內(nèi)核會自動計算校驗和
            ip_header->saddr = inet_addr("10.0.0.1"); // 源 IP 地址
            ip_header->daddr = inet_addr("14.0.0.2"); // 目標 IP 地址

            // 添加 ICMP 數(shù)據(jù)
            char *icmp_data = buffer1 + IP_HEADER_LENGTH;
            icmp_data[0] = 8; // ICMP 類型為 8(Echo Request)
            icmp_data[1] = 0; // ICMP 代碼為 0
            icmp_data[2] = 0; // 校驗和高位字節(jié)
            icmp_data[3] = 0; // 校驗和低位字節(jié)
            icmp_data[4] = 0x12; // 標識符高位字節(jié)
            icmp_data[5] = 0x34; // 標識符低位字節(jié)
            icmp_data[6] = 0; // 序列號高位字節(jié)
            icmp_data[7] = 0; // 序列號低位字節(jié)

            // 計算 ICMP 校驗和
            unsigned short checksum = 0;
            for (int i = 0; i < 8; i += 2) {
            checksum += (icmp_data[i] << 8) | icmp_data[i + 1];
            }
            checksum = (checksum >> 16) + (checksum & 0xFFFF);
            checksum = ~checksum;
            icmp_data[2] = (checksum >> 8) & 0xFF;
            icmp_data[3] = checksum & 0xFF;
            // 將數(shù)據(jù)包寫入TUN設(shè)備的設(shè)備節(jié)點
            ssize_t num_bytes_sent = write(tun_fd, buffer1, IP_HEADER_LENGTH + 8);

            if (num_bytes_sent < 0) {
            perror("write");
            close(tun_fd);
            return -1;
            }
            printf("Sent %zd bytes to TUN device.\n", num_bytes_sent);
            }
            close(tun_fd);
            return 0;
}

應(yīng)用層2代碼

基本邏輯:

負責給虛擬網(wǎng)卡驅(qū)動發(fā)送應(yīng)用層數(shù)據(jù)包

#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <linux/if_tun.h>
#include<stdlib.h>
#include<stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define DEST_IP "10.0.0.2"
#define DEST_IP1 "192.168.6.1"


int main()
{

// 創(chuàng)建套接字
            int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (sockfd < 0) {
            perror("Error creating socket");
            //close(tun_fd);
            exit(1);
            }
            sleep(5);
            // 設(shè)置目標 IP 地址和端口
            printf("------------start-------------------\n");
            struct sockaddr_in dest_addr;
            memset(&dest_addr, 0, sizeof(dest_addr));
            dest_addr.sin_family = AF_INET;
            dest_addr.sin_port = htons(12345);
            inet_pton(AF_INET, DEST_IP, &(dest_addr.sin_addr));

            // 模擬發(fā)送數(shù)據(jù)到 TUN 設(shè)備
            const char* message = "Hello, TUN device!!!!!";

            int sockfd1 = socket(AF_INET, SOCK_DGRAM, 0);
            if (sockfd1 < 0) {
            perror("Error creating socket");
            //close(tun_fd);
            exit(1);
            }
            sleep(5);
            // 設(shè)置目標 IP 地址和端口
            printf("------------start-------------------\n");
            struct sockaddr_in dest_addr1;
            memset(&dest_addr1, 0, sizeof(dest_addr1));
            dest_addr1.sin_family = AF_INET;
            dest_addr1.sin_port = htons(1234);
            inet_pton(AF_INET, DEST_IP1, &(dest_addr1.sin_addr));

            // 模擬發(fā)送數(shù)據(jù)到 TUN 設(shè)備
            const char* message1 = "tun tunt tunt!!!!!!";

            while(1)
            {
            sendto(sockfd1, message1, strlen(message1), 0, (struct sockaddr*)&dest_addr1, sizeof(dest_addr1));        
               sleep(5);
               sendto(sockfd, message, strlen(message), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
            }
            close(sockfd);
            close(sockfd1);
  
}

應(yīng)用層如何編譯

如果您經(jīng)常閱讀我的文章,就不應(yīng)該問出這樣的問題,以前的文章都有提及!

驗證

root權(quán)限執(zhí)行應(yīng)用層代碼1結(jié)果(有刪減):

sudo ./net_device_user1
RTNETLINK answers: File exists
Open tun/tap device: tun0 for reading...

Read 50 bytes from tun/tap device
45 00 00 32 03 FFFFFF9E 40 00 40 11 23 1B 0A 00 00 01 
0A 00 00 02 FFFFFF86 0D 30 39 00 1E 05 27 48 65 6C 6C 
6F 2C 20 54 55 4E 20 64 65 76 69 63 65 21 21 21 
21 21 
Sent 28 bytes to TUN device.
Read 47 bytes from tun/tap device
45 00 00 2F 03 FFFFFF9F 40 00 40 11 23 1D 0A 00 00 01 
0A 00 00 02 FFFFFFC0 3E 04 FFFFFFD2 00 1B FFFFFFF3 FFFFFFDE 74 75 6E 20 
74 75 6E 74 20 74 75 6E 74 21 21 21 21 21 21 
Sent 28 bytes to TUN device.

root權(quán)限執(zhí)行應(yīng)用層代碼2結(jié)果

sudo ./net_device.o
------------start-------------------

抓取tupdump包

sudo tcpdump -i tun0 -w tcpdump_30.pcap
tcpdump: listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
tcpdump: pcap_loop: The interface went down
16 packets captured
16 packets received by filter
0 packets dropped by kernel

分別抓到了應(yīng)用層發(fā)來的數(shù)據(jù)包(兩個包),讀取完后完成數(shù)據(jù)包的發(fā)送

利用十六進制轉(zhuǎn)字符串驗證應(yīng)用代碼2發(fā)送給應(yīng)用代碼1的數(shù)據(jù)是否發(fā)送成功:

  • 第一個包
Read 50 bytes from tun/tap device
45 00 00 32 03 FFFFFF9E 40 00 40 11 23 1B 0A 00 00 01 
0A 00 00 02 FFFFFF86 0D 30 39 00 1E 05 27 48 65 6C 6C 
6F 2C 20 54 55 4E 20 64 65 76 69 63 65 21 21 21 
21 21

其中的data數(shù)據(jù)轉(zhuǎn)化結(jié)果:

  • 第二個包
Read 47 bytes from tun/tap device
45 00 00 2F 03 FFFFFF9F 40 00 40 11 23 1D 0A 00 00 01 
0A 00 00 02 FFFFFFC0 3E 04 FFFFFFD2 00 1B FFFFFFF3 FFFFFFDE 74 75 6E 20 
74 75 6E 74 20 74 75 6E 74 21 21 21 21 21 21 

結(jié)果

驗證成功

ps:

  • 完成的功能很少,希望這能拋磚引玉
  • 代碼解釋不是特別詳細,代碼行中有很多注釋,希望能幫助到你

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • centos中yum命令刪除還原的補救方法介紹

    centos中yum命令刪除還原的補救方法介紹

    Yum: 即Yellowdog Update Modifier,是一種基于rpm的包管理工具,這篇文章主要給大家介紹了關(guān)于在centos中yum命令刪除還原的補救方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-01-01
  • CentOS 7安裝Mysql并設(shè)置開機自啟動的方法

    CentOS 7安裝Mysql并設(shè)置開機自啟動的方法

    本篇文章主要介紹了CentOS 7安裝Mysql并設(shè)置開機自啟動的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • centos7下安裝oracle11gR2的詳細步驟

    centos7下安裝oracle11gR2的詳細步驟

    本篇文章主要介紹了centos7下安裝oracle11gR2的詳細步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • 深入理解apahce的工作模式perfork、worker

    深入理解apahce的工作模式perfork、worker

    本文介紹下,apache的兩種工作模式perfork與worker,就它們的區(qū)別進行深入分析,供大家學習參考
    2013-06-06
  • telnet?Connection?refused端口不通如何處理

    telnet?Connection?refused端口不通如何處理

    本文介紹了telnet命令的基本用途及排查telnet連接拒絕的處理思路,telnet主要用于測試網(wǎng)絡(luò)連接,如遇到連接問題,可能是由于防火墻未開放或目的主機服務(wù)未啟動,文章通過實際例子解釋了telnet命令的作用,并提供了解決網(wǎng)絡(luò)連接問題的方法
    2024-10-10
  • 詳解Linux(Centos)之安裝Nginx及注意事項

    詳解Linux(Centos)之安裝Nginx及注意事項

    Nginx是一個高性能的HTTP和反向代理服務(wù)器,這篇文章主要介紹了詳解Linux(Centos)之安裝Nginx及注意事項,有興趣的可以了解一下。
    2017-03-03
  • CentOS7升級內(nèi)核kernel5.0版本

    CentOS7升級內(nèi)核kernel5.0版本

    這篇文章主要介紹了CentOS7升級內(nèi)核kernel5.0版本,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • Apache中的Order Allow,Deny用法詳解

    Apache中的Order Allow,Deny用法詳解

    這篇文章主要介紹了Apache中的Order Allow,Deny用法,結(jié)合實例較為詳細的分析了Apache中Order Allow,Deny的具體作用及使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-12-12
  • linux下如何安裝nginx

    linux下如何安裝nginx

    這篇文章主要介紹了linux下如何安裝nginx問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Apache 開通子站點配置方法

    Apache 開通子站點配置方法

    前一段時間突發(fā)奇想,想自己給自己做個記錄系統(tǒng),暫且就叫他記錄系統(tǒng)吧。其實木的就是記錄一些亂七八糟的事情,譬如,賬簿,記事本之類的
    2012-06-06

最新評論