投射到 iphdr 和 tcphdr 的正确偏移量是多少?
What is the correct offset for casting to iphdr and tcphdr?
这是 recv()
的一个奇怪行为。
我正在使用 libnetfilter_queue
库和 iptables
以便将传入的数据包存储到三个不同的队列中,这取决于它们的源端口(我检查这个条件要感谢下面写的 iptables
规则)。
基本上,我收到的数据包的有效载荷总是包含字母 E
。
这是我的代码(为简洁起见,我省略了对错误的控制)。
/* bunch of #include <whatineed.h> */
int main() {
pthread_t threads[3];
pthread_create(&threads[0], NULL, queueThread, (void *)0);
pthread_create(&threads[1], NULL, queueThread, (void *)1);
pthread_create(&threads[2], NULL, queueThread, (void *)2);
pthread_exit(NULL);
return 0;
}
每个线程执行的函数:
void *queueThread(void *queuenum) {
int fd, rv;
int queue_num = (int)queuenum;
struct nfq_handle *h = NULL;
struct nfq_q_handle *qh = NULL;
char buf[8192] __attribute__ ((aligned));
/* queue handling setup */
h = nfq_open();
nfq_unbind_pf(h, AF_INET);
nfq_bind_pf(h, AF_INET);
qh = nfq_create_queue(h, queue_num, &packetHandler, NULL);
nfq_set_queue_maxlen(qh, 10000);
nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff);
memset(buf, '[=11=]', sizeof(buf));
/* Tried to increase socket buffer size, but nothing changes */
nfnl_rcvbufsiz(nfq_nfnlh(h), 10000 * 1500);
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) > 0)) {
printf("queueThread: read %d bytes from file descriptor %d\n", rv, fd);
nfq_handle_packet(h, buf, rv);
}
nfq_destroy_queue(qh);
nfq_close(h);
pthread_exit(NULL);
}
我从 queueThread
:
获得的每个数据包调用的回调函数
int packetHandler(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data) {
struct nfqnl_msg_packet_hdr *ph = NULL;
unsigned char *nf_packet = NULL;
int pkt_size = 0;
ph = nfq_get_msg_packet_hdr(nfa);
int id = ntohl(ph -> packet_id);
pkt_size = nfq_get_payload(nfa, &nf_packet);
printf("packetHandler: pkt is %d byte, it says: %s\n", pkt_size, nf_packet);
/* Let's check, e.g., its protocol */
struct iphdr *iph = (struct iphdr *) (nf_packet + sizeof(struct ethhdr));
printf("packetHandler: pkt protocol is %d\n", iph->protocol);
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}
在 iptables
上设置以下规则后:
sudo iptables -I INPUT -p tcp --sport 25 -j NFQUEUE --queue-num 0
sudo iptables -I INPUT -p tcp --sport 80 -j NFQUEUE --queue-num 1
sudo iptables -I INPUT -p udp --sport 5060 -j NFQUEUE --queue-num 2
sudo iptables -I INPUT -p tcp --sport 5060 -j NFQUEUE --queue-num 2
在我的浏览器上打开一个新标签并加载一个页面(因此,从端口 80 获取数据包),这是我的输出:
queueThread: read 148 bytes from file descriptor 4
packetHandler: pkt is 60 byte, it says: E
packetHandler: pkt protocol is 35
queueThread: read 148 bytes from file descriptor 4
packetHandler: pkt is 60 byte, it says: E
packetHandler: pkt protocol is 35
queueThread: read 148 bytes from file descriptor 4
packetHandler: pkt is 60 byte, it says: E
packetHandler: pkt protocol is 35
我也尝试过 nping
通过在另一个终端向自己发送来自端口 25 和端口 5060 的数据包,结果是一样的:奇怪的协议号和字母 E。
我无法将有效载荷正确地转换为 tcphdr
或 udphdr
结构并获取我需要的数据,因为我不知道我从 queueThread()
得到了什么以及我传递给 packetHandler()
.
显然,我的错误是将 sizeof(struct ethhdr)
添加到有效载荷以到达数据包的 IP header:这就是为什么我总是得到奇怪的协议和端口号,我在一个抵消我不应该去的地方。
仍然有 E
但没关系,我现在可以成功读取协议和端口号;抱歉让我分心了。
这是我发现这个的地方:How does nfq_get_payload structure its return data?
这是 recv()
的一个奇怪行为。
我正在使用 libnetfilter_queue
库和 iptables
以便将传入的数据包存储到三个不同的队列中,这取决于它们的源端口(我检查这个条件要感谢下面写的 iptables
规则)。
基本上,我收到的数据包的有效载荷总是包含字母 E
。
这是我的代码(为简洁起见,我省略了对错误的控制)。
/* bunch of #include <whatineed.h> */
int main() {
pthread_t threads[3];
pthread_create(&threads[0], NULL, queueThread, (void *)0);
pthread_create(&threads[1], NULL, queueThread, (void *)1);
pthread_create(&threads[2], NULL, queueThread, (void *)2);
pthread_exit(NULL);
return 0;
}
每个线程执行的函数:
void *queueThread(void *queuenum) {
int fd, rv;
int queue_num = (int)queuenum;
struct nfq_handle *h = NULL;
struct nfq_q_handle *qh = NULL;
char buf[8192] __attribute__ ((aligned));
/* queue handling setup */
h = nfq_open();
nfq_unbind_pf(h, AF_INET);
nfq_bind_pf(h, AF_INET);
qh = nfq_create_queue(h, queue_num, &packetHandler, NULL);
nfq_set_queue_maxlen(qh, 10000);
nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff);
memset(buf, '[=11=]', sizeof(buf));
/* Tried to increase socket buffer size, but nothing changes */
nfnl_rcvbufsiz(nfq_nfnlh(h), 10000 * 1500);
fd = nfq_fd(h);
while ((rv = recv(fd, buf, sizeof(buf), 0)) > 0)) {
printf("queueThread: read %d bytes from file descriptor %d\n", rv, fd);
nfq_handle_packet(h, buf, rv);
}
nfq_destroy_queue(qh);
nfq_close(h);
pthread_exit(NULL);
}
我从 queueThread
:
int packetHandler(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data) {
struct nfqnl_msg_packet_hdr *ph = NULL;
unsigned char *nf_packet = NULL;
int pkt_size = 0;
ph = nfq_get_msg_packet_hdr(nfa);
int id = ntohl(ph -> packet_id);
pkt_size = nfq_get_payload(nfa, &nf_packet);
printf("packetHandler: pkt is %d byte, it says: %s\n", pkt_size, nf_packet);
/* Let's check, e.g., its protocol */
struct iphdr *iph = (struct iphdr *) (nf_packet + sizeof(struct ethhdr));
printf("packetHandler: pkt protocol is %d\n", iph->protocol);
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}
在 iptables
上设置以下规则后:
sudo iptables -I INPUT -p tcp --sport 25 -j NFQUEUE --queue-num 0
sudo iptables -I INPUT -p tcp --sport 80 -j NFQUEUE --queue-num 1
sudo iptables -I INPUT -p udp --sport 5060 -j NFQUEUE --queue-num 2
sudo iptables -I INPUT -p tcp --sport 5060 -j NFQUEUE --queue-num 2
在我的浏览器上打开一个新标签并加载一个页面(因此,从端口 80 获取数据包),这是我的输出:
queueThread: read 148 bytes from file descriptor 4
packetHandler: pkt is 60 byte, it says: E
packetHandler: pkt protocol is 35
queueThread: read 148 bytes from file descriptor 4
packetHandler: pkt is 60 byte, it says: E
packetHandler: pkt protocol is 35
queueThread: read 148 bytes from file descriptor 4
packetHandler: pkt is 60 byte, it says: E
packetHandler: pkt protocol is 35
我也尝试过 nping
通过在另一个终端向自己发送来自端口 25 和端口 5060 的数据包,结果是一样的:奇怪的协议号和字母 E。
我无法将有效载荷正确地转换为 tcphdr
或 udphdr
结构并获取我需要的数据,因为我不知道我从 queueThread()
得到了什么以及我传递给 packetHandler()
.
显然,我的错误是将 sizeof(struct ethhdr)
添加到有效载荷以到达数据包的 IP header:这就是为什么我总是得到奇怪的协议和端口号,我在一个抵消我不应该去的地方。
仍然有 E
但没关系,我现在可以成功读取协议和端口号;抱歉让我分心了。
这是我发现这个的地方:How does nfq_get_payload structure its return data?