以下是一个示例代码,展示如何向 TUN/TAP 设备写入 UDP 数据,并将其发送给指定的 UDP 服务器。
向 TUN/TAP 写入 UDP 数据的示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 2048
#define TUN_DEVICE "/dev/net/tun"
#define UDP_SERVER_IP "192.168.1.100" // 替换为目标UDP服务器的IP地址
#define UDP_SERVER_PORT 12345 // 替换为目标UDP服务器的端口
// 创建 TUN/TAP 设备
int create_tun_device() {
struct ifreq ifr;
int fd;
fd = open(TUN_DEVICE, O_RDWR);
if (fd < 0) {
perror("open");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; // 使用 IFF_TUN 表示只处理网络层数据包
strncpy(ifr.ifr_name, "tun0", IFNAMSIZ);
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
perror("ioctl");
close(fd);
return -1;
}
printf("TUN device %s created\n", ifr.ifr_name);
return fd;
}
int main() {
// 创建 TUN 设备并获取文件描述符
int tun_fd = create_tun_device();
if (tun_fd < 0) {
exit(EXIT_FAILURE);
}
// 创建 UDP socket
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
perror("socket");
close(tun_fd);
exit(EXIT_FAILURE);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(UDP_SERVER_PORT);
if (inet_aton(UDP_SERVER_IP, &server_addr.sin_addr) == 0) {
perror("inet_aton");
close(sockfd);
close(tun_fd);
exit(EXIT_FAILURE);
}
char buffer[BUFFER_SIZE];
while (1) {
// 模拟要发送的数据
snprintf(buffer, BUFFER_SIZE, "Hello from TUN device! PID: %d", getpid());
// 将数据写入到 TUN/TAP 设备
int nwrite = write(tun_fd, buffer, strlen(buffer));
if (nwrite < 0) {
perror("write to tun device");
break;
}
printf("Wrote %d bytes to TUN device\n", nwrite);
// 将数据通过 socket 发送到指定的 UDP 服务端
ssize_t sent_bytes = sendto(sockfd, buffer, nwrite , MSG_CONFIRM,
(const struct sockaddr *)&server_addr,
sizeof(server_addr));
if(sent_bytes<0){
perror("sendto failed");
break;
}
printf("Sent %ld bytes to UDP server\n", sent_bytes);
sleep(1); // 每秒发送一次数据
}
close(sockfd);
close(tun_fd);
return EXIT_SUCCESS;
}
编译与运行
将上述代码保存为 tun_udp_sender.c
,然后通过以下命令编译:
gcc tun_udp_sender.c -o tun_udp_sender
sudo ./tun_udp_sender
注意事项
- 权限: 因为需要操作
/dev/net/tun
和创建 Socket,所以通常需要以超级用户权限运行程序。 - 网络配置: 请确保目标服务器(指定的
UDP_SERVER_IP
)可以从你执行这个程序的机器访问。 - 错误处理: 示例中的错误处理较简单,可根据实际情况进行改进。
此程序会模拟一条消息,然后将其写入到创建的 TUN/TAP 接口,并同时通过 UDP 套接字发送该消息。每隔一秒会重复这一过程。可以根据需要修改消息内容或发送频率。
内容由零声教学AI助手提供,问题来源于学员提问