- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Linux 上,可以使用 AF_PACKET 创建一个套接字,以从套接字接收原始数据并在应用程序中进行 IP 过滤。但是 OSX 的手册页没有这个:
PF_LOCAL Host-internal protocols, formerly called PF_UNIX,
PF_UNIX Host-internal protocols, deprecated, use PF_LOCAL,
PF_INET Internet version 4 protocols,
PF_ROUTE Internal Routing protocol,
PF_KEY Internal key-management function,
PF_INET6 Internet version 6 protocols,
PF_SYSTEM System domain,
PF_NDRV Raw access to network device
最佳答案
没有任何协议(protocol)是 POSIX 标准。 POSIX 根本不需要系统支持任何特定的网络协议(protocol)或任何网络协议(protocol)。AF_PACKET
是一个纯 Linux 发明 AFAIK,你不会在其他系统上找到它。
BPF(伯克利包过滤器)也不是 POSIX,它是许多系统复制的 BSD 发明,因为它非常方便。但是,您不能使用它注入(inject)流量,您只能使用它捕获传入和传出流量。
如果有人关心,这里是最新的 POSIX 标准:
The Open Group Base Specifications Issue 7, 2018 edition
IEEE Std 1003.1™-2017 (Revision of IEEE Std 1003.1-2008)
如果你真的想发送原始 IP 数据包(无论是 IPv4 还是 IPv6),使用原始 IP 套接字是最便携的:
int soc = socket(PF_INET, SOCK_RAW, IPPROTO_IP);
然后你需要告诉系统你想提供你自己的IP头:
int yes = 1;
setsockopt(soc, IPPROTO_IP, IP_HDRINCL, &yes, sizeof(yes));
现在您可以将原始 IP 数据包(例如 IP header + UDP header + 有效负载数据)发送到套接字进行发送,但是,根据您的系统,系统将执行一些健全性检查,并且可能会覆盖 header 中的某些字段。例如。它可能不允许您创建格式错误的 IP 数据包或阻止您执行 IP 地址欺骗。因此,它可能会为您计算 IPv4 header 校验和,或者如果您的 IP header 使用
0.0.0.0
,则自动填写正确的源地址。或
::
作为源地址。查看
ip(4)
的手册页或
raw(7)
在您的目标系统上。 Apple 不再提供 macOS 的程序员手册页,但
you can find them online.
Unlike previous BSD releases, the program must set all the fields ofthe IP header, including the following:
ip->ip_v = IPVERSION;
ip->ip_hl = hlen >> 2;
ip->ip_id = 0; /* 0 means kernel set appropriate value */
ip->ip_off = offset;
ip->ip_len = len;Note that the
ip_off
andip_len
fields are in host byte order.If the header source address is set to
INADDR_ANY
, the kernel willchoose an appropriate address.
ip_sum
根本没有提到,所以显然你不必提供那个,系统总是会为你计算它。
┌───────────────────────────────────────────────────┐
│IP Header fields modified on sending by IP_HDRINCL │
├──────────────────────┬────────────────────────────┤
│IP Checksum │ Always filled in │
├──────────────────────┼────────────────────────────┤
│Source Address │ Filled in when zero │
├──────────────────────┼────────────────────────────┤
│Packet ID │ Filled in when zero │
├──────────────────────┼────────────────────────────┤
│Total Length │ Always filled in │
└──────────────────────┴────────────────────────────┘
IPPROTO_IP
而不是
IPPROTO_RAW
.使用
IPPROTO_RAW
时您不必设置
IP_HDRINCL
:
A protocol of
IPPROTO_RAW
implies enabledIP_HDRINCL
and is able tosend any IP protocol that is specified in the passed header.
IPPROTO_RAW
对于传出流量:
An
IPPROTO_RAW
socket is send only.
IPPROTO_IP
您将收到所有 IP 数据包,但在 Linux 上这可能不起作用,因此创建了一个新套接字
PF_PACKET
socket 类型。应该在两个系统上工作的是指定一个子协议(protocol):
int soc = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
当然,现在您只能通过该套接字发送/接收 UDP 数据包。如果设置
IP_HDRINCL
同样,您需要在发送时提供完整的 IP header ,并且您将在接收时收到完整的 IP header 。如果你不设置它,你可以只在发送时提供UDP头,系统会自己添加一个IP头,也就是说,如果套接字是连接的并且可以选择绑定(bind),那么系统就知道在那个头中使用哪些地址.对于接收该选项不起作用,您总是会为您在此类套接字上收到的每个 UDP 数据包获取 IP header 。
PF_INET
而不是
AF_INET
: PF 表示协议(protocol)族,AF 表示地址族。通常这些是相同的(例如
AF_INET == PF_INET
)所以你使用什么并不重要,但严格来说应该使用
PF_
创建套接字和家人在
sockaddr
结构应设置为
AF_
有一天可能会有一种协议(protocol)支持两种不同的地址,然后会有
AF_XXX1
和
AF_XXX2
并且两者都不能与
PF_XXX
相同.
关于macos - OSX 上的 AF_PACKET,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17169298/
我对 AF_PACKET 套接字系列(用于 SOCK_RAW 套接字)与以太网 (IEEE 802.3) 的具体关系感到非常困惑。 目前我的理解: 我了解 OSI 模型,以及第 2 层技术如何像以太网
sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
在 Linux 上,可以使用 AF_PACKET 创建一个套接字,以从套接字接收原始数据并在应用程序中进行 IP 过滤。但是 OSX 的手册页没有这个: PF_LOCAL
我在尝试让 wpa_supplicant 在运行自定义嵌入式 Linux 发行版的板上运行时遇到了问题。经过一些调试,原来是因为内核不支持域类型PF_PACKET: drv->eapol_tx_soc
如何在不指定数据绑定(bind)到哪个主机的情况下在 SOCK_PACKET 套接字上发送数据?我已经构建了 IP header 以显示它应该去哪里,但是 write() 不起作用。 最佳答案 不要。
正如 this question 所暗示的那样,似乎校验和是由以太网硬件计算和验证的,因此当使用 AF_PACKET 套接字发送帧时,它似乎不太可能必须由软件生成,看起来 here和 here .另外
我试图使用 AF_PACKET 原始套接字嗅探网络流量。我能够获取所有 IP/ARP 数据包,但根本无法获取任何 IPv6 数据包。我需要做什么才能获得 IPv6 流量吗? unsigned c
我想不通。当我运行我的代码时......即使我绑定(bind)成功,我也会看到来自所有以太网类型和所有接口(interface)的数据。运行几分钟后……它会自行修复。然后我只从一个特定的接口(inte
使用以下方法使用 AF_PACKET 和环形缓冲区(伪 C)捕获数据包: // Set up socket fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_A
我正在使用 Python 构建数据包嗅探程序,但是我遇到了减速带。出于某种原因,我认为套接字没有正确导入,因为我在程序运行时收到以下消息:AttributeError: module 'socket'
关闭创建为AF_PACKET 和AF_INET 的套接字之间存在这种时间差异的原因是什么?如何减少 AF_PACKET 的关闭时间? sockfd = socket(AF_PACKET, SOCK_R
我想编写一个应用程序,它应该接收所有传入的数据包,而不管数据包是发往我的机器并假设被转发还是发往本地主机。 为此,我打开了一个 AF_PACKET 套接字。但是,由于我的机器有多个接口(interfa
在两台 PC 上,我正在打开一个 AF_PACKET/PF_PACKET 套接字,原始协议(protocol)。 sock = socket(AF_PACKET, SOCK_RAW, htons(PR
下面的 Linux 代码应该搜索所有接口(interface),直到它使用 ETHERNET 类型 2 帧从特定 MAC 地址获得响应。 尚未完成。 我希望 select() 阻止超时值。问题是没有数
我正在尝试在 Linux (Ubuntu 18.04) 上的 C 中创建一个测试程序,该程序使用 SOCK_RAW 通过 AF_PACKET/PF_PACKET 套接字发送一个空的 UDP 数据包.在
我是一名优秀的程序员,十分优秀!