这是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, '\0', 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()
得到了什么以及我传递给{{{ 1}}。
答案 0 :(得分:0)
显然,我的错误是将sizeof(struct ethhdr)
添加到有效负载以便到达数据包的IP头:这就是为什么我总是得到奇怪的协议和端口号,我在偏移的地方我不应该。
仍然得到E
但是没关系,我现在可以阅读成功的协议和端口号;对不起我的分心。
我在这里找到了这个:How does nfq_get_payload structure its return data?