【问题标题】:Listening to virtual network interface监听虚拟网络接口
【发布时间】:2021-09-16 21:17:47
【问题描述】:

不要对我谈论 L2TP 感到困惑。虽然我的问题与 L2TP 有关,但它本身并不是 L2TP 问题。这更像是一个网络问题。

背景

我正在编写一个使用 L2TP 的应用程序。这是我第一次使用 L2TP 和 linux L2TP 子系统,所以我希望我做对了。 创建 L2TP 以太网会话时,子系统会自动创建一个虚拟网络接口。
启动接口后,我可以使用 Wireshark 检查,并且确实将所需的数据发送到接口。这是没有任何包装的。它不在以太网帧或任何东西内,而只是 L2TP 数据包中包含的数据字节。
我无法控制实际创建设备,但我可以查询它的名称以及它的索引等,到目前为止一切都很好。

实际问题

我的问题其实很简单:如何将发送到虚拟接口的数据放入我的用户空间应用程序?
我在unix上没有很多网络经验,但我的期望是这是一个相当简单的问题,可以通过获取一个我可以使用read/recv的文件描述符或以某种方式绑定一个套接字来解决到那个网络接口。
我找不到任何 (gen-)netlink / ioctl API(或其他任何东西)来执行此操作或类似的操作。

虽然我的应用程序是用 GO 而不是 C 编写的,但 C 语言的解决方案就足够了。 Tbh 在这一点上,我对任何以编程方式解决此问题的方法感到高兴。 :)

提前非常感谢

【问题讨论】:

  • 我可以查询它的名字和索引。如何?你用什么命令吗?
  • @kiner_shah 您通过netlink api for L2TP(L2TP_CMD_SESSION_GET 命令)获得名称。要获取索引,您可以在 go (net.InterfaceByName) 中使用 net std lib,在 C 中您可以使用 netlink 或 ioctl。
  • 通过“获取数据”,我认为您想收听在虚拟接口上接收到的数据。要了解哪些接口是虚拟的,请参阅this link。要收听虚拟网络接口,this link 可能会有所帮助。
  • @kiner_shah 我想我已经尝试使用来自getifaddrs(来自您的第二个链接)的sockaddr 设置一个套接字,但它对我不起作用,但我很乐意再试一次之后。也许我做错了什么。我会告诉你它是否有效。
  • 我再次尝试getifaddrs,但一开始无法正常工作,因为我的接口的一个地址是家庭AF_PACKET(上次测试时,我丢弃了所有地址,这些地址是不是家人AF_INET 或AF_INET6)。 AF_PACKETsockets 不像通常的 AF_INET 套接字那样工作,在研究我遇到的 this tutorial 时,它回答了我所有的问题。非常感谢您的帮助❤

标签: c unix network-programming posix l2tp


【解决方案1】:

我刚刚找到了一个回答我自己问题的教程。使用AF_PACKET 套接字实际上非常简单。

有一个lovely tutorial on microhowto.info,它解释了AF_PACKET 套接字的工作原理,比我做得更好。它甚至包括一个部分“仅从特定网络接口捕获”。


这是一个适用于我的用例的最小示例:

#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <linux/if_packet.h>
#include <sys/socket.h>

// [...]

// Create socket
int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (fd == -1) {
    perror("ERROR socket");
    exit(1);
}

// Interface index (i.e. obtainable via ioctl SIOCGIFINDEX)
int ifindex = 1337;

// create link layer socket address
struct sockaddr_ll addr = {0};
addr.sll_family = AF_PACKET;
addr.sll_ifindex = ifindex;
addr.sll_protocol = htons(ETH_P_ALL)

if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
    perror("ERROR bind");
    exit(1);
}

char buffer[65535];
ssize_t len;    
do { 
    len = recv(fd, buffer, sizeof(buffer) -1, 0);
    if (len < 0) {
        perror("ERROR recvfrom");
        exit(1);
    }
    printf("recived data (length: %i)\n", (int) len);
} while (len > 0);

【讨论】:

  • 很高兴您找到了解决方案 :-) 但是,目前这个答案是“仅链接”。您能否编辑答案以包含链接中的必要部分?
  • 当然。我添加了一个最小的例子。我希望这足够。如果不是这样说:D。我只是不想复制粘贴别人的作品。
猜你喜欢
  • 2013-11-21
  • 1970-01-01
  • 2012-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多