环回抓包
Capturing packets on loopback
此代码在 Ubuntu 16.04 上运行良好,并在我通过环回接口处理 UDP 字节时打印正确的值 (ETHERTYPE_IP):
#include <pcap.h>
#include <iostream>
#include <net/ethernet.h>
int main(int argc,char **argv)
{
char errbuf[PCAP_ERRBUF_SIZE];
auto pcap = pcap_open_live("lo0", BUFSIZ, 0, 1000, errbuf);
pcap_loop(pcap,0, [] (u_char *self, const struct pcap_pkthdr *header,
const u_char *packet) {
auto eth = (struct ether_header *) packet;
auto eth_type = ntohs(eth->ether_type);
std::cout << "eth_type: " << std::hex << eth_type << std::endl;
}, nullptr);
return 0;
}
网络猫:
➜ ~ nc -uv -l 54321
Listening on [0.0.0.0] (family 0, port 54321)
➜ ~ nc -4u localhost 54321
hello
程序输出:
➜ ~ sudo ./a.out
eth_type: 800
但是在 OS X 10.11.5 上打印 eth_type: 4011。有趣的是,它可以与 en1 适配器一起正常工作。
为什么环回和非环回适配器之间存在如此大的差异?在两者上捕获数据包的正确方法是什么?
更新:
tcpdump 也有效:
➜ ~ sudo tcpdump -i lo0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
15:09:00.160664 IP localhost.54321 > localhost.63543: UDP, length 4
由于 link 类型不是以太网,header 不包含适合 ether_header 的数据。
在使用 pcap_open_live 获取句柄后添加此代码以查看 link-layer header 类型:
if (pcap_datalink(pcap) != DLT_EN10MB) {
fprintf(stderr, "Device doesn't provide Ethernet headers - link type was %d\n", pcap_datalink(pcap));
return 1;
}
运行 这表示 lo0 的 linktype 值为 0,DLT_NULL。文档指出这意味着 "BSD loopback encapsulation; the link layer header is a 4-byte field, in host byte order, containing a PF_ value from socket.h for the network-layer protocol of the packet."
确实,当我查看 ether_dhost 字段的前 4 个字节时,我看到值 2,对应于 PF_INET。最后,如果您试图区分 UDP 数据包,这对您没有多大帮助。
您可以在此处找到更多文档:http://www.tcpdump.org/linktypes.html
此代码在 Ubuntu 16.04 上运行良好,并在我通过环回接口处理 UDP 字节时打印正确的值 (ETHERTYPE_IP):
#include <pcap.h>
#include <iostream>
#include <net/ethernet.h>
int main(int argc,char **argv)
{
char errbuf[PCAP_ERRBUF_SIZE];
auto pcap = pcap_open_live("lo0", BUFSIZ, 0, 1000, errbuf);
pcap_loop(pcap,0, [] (u_char *self, const struct pcap_pkthdr *header,
const u_char *packet) {
auto eth = (struct ether_header *) packet;
auto eth_type = ntohs(eth->ether_type);
std::cout << "eth_type: " << std::hex << eth_type << std::endl;
}, nullptr);
return 0;
}
网络猫:
➜ ~ nc -uv -l 54321
Listening on [0.0.0.0] (family 0, port 54321)
➜ ~ nc -4u localhost 54321
hello
程序输出:
➜ ~ sudo ./a.out
eth_type: 800
但是在 OS X 10.11.5 上打印 eth_type: 4011。有趣的是,它可以与 en1 适配器一起正常工作。
为什么环回和非环回适配器之间存在如此大的差异?在两者上捕获数据包的正确方法是什么?
更新: tcpdump 也有效:
➜ ~ sudo tcpdump -i lo0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
15:09:00.160664 IP localhost.54321 > localhost.63543: UDP, length 4
由于 link 类型不是以太网,header 不包含适合 ether_header 的数据。
在使用 pcap_open_live 获取句柄后添加此代码以查看 link-layer header 类型:
if (pcap_datalink(pcap) != DLT_EN10MB) {
fprintf(stderr, "Device doesn't provide Ethernet headers - link type was %d\n", pcap_datalink(pcap));
return 1;
}
运行 这表示 lo0 的 linktype 值为 0,DLT_NULL。文档指出这意味着 "BSD loopback encapsulation; the link layer header is a 4-byte field, in host byte order, containing a PF_ value from socket.h for the network-layer protocol of the packet."
确实,当我查看 ether_dhost 字段的前 4 个字节时,我看到值 2,对应于 PF_INET。最后,如果您试图区分 UDP 数据包,这对您没有多大帮助。
您可以在此处找到更多文档:http://www.tcpdump.org/linktypes.html