我正在开发一台基于TUN的VPN服务器,其目标是在将数据包转发到目的地之前对其接收的数据包进行分析。目前,我正在接收来自TUN接口的IP数据包,并且简单地将它们发送到它们的目的地。
我知道,分析UDP数据包的内容就像去掉IP和UDP报头一样简单。然而,为了分析TCP流量的内容,我需要从多个IP数据包中重构消息。在不重新实现TCP的情况下,是否有一种简单的方法可以做到这一点?是否有任何易于访问的C/C++库用于此任务?我更喜欢Linux系统库和/或开源、非病毒/非版权库。
我已经考虑过的一件事是复制每个IP数据包,并将副本的目标IP更改为本地主机,这样我的服务器的另一部分就可以接收到这些TCP请求和响应,并且完全重构并且没有报头。但是,我无法将目的地is与流量内容联系起来,这是我所希望的。
发布于 2013-09-15 00:58:49
您需要的功能很可能总是与数据包分离紧密耦合在一起。真正需要良好的协议分解来提取所需的信息。所以我的建议是使用最好的开源工具- wireshark.org。
它提供了“跟踪TCP流”功能:

我看上去不太容易提取Wireshark剖析逻辑的一部分,但至少有一个很好的例子数据包-tcp
typedef struct _tcp_flow_t {
guint32 base_seq; /* base seq number (used by relative sequence numbers)
* or 0 if not yet known.
*/
tcp_unacked_t *segments;
guint32 fin; /* frame number of the final FIN */
guint32 lastack; /* last seen ack */
nstime_t lastacktime; /* Time of the last ack packet */
guint32 lastnondupack; /* frame number of last seen non dupack */
guint32 dupacknum; /* dupack number */
guint32 nextseq; /* highest seen nextseq */
guint32 maxseqtobeacked;/* highest seen continuous seq number (without hole in the stream) from the fwd party,
* this is the maximum seq number that can be acked by the rev party in normal case.
* If the rev party sends an ACK beyond this seq number it indicates TCP_A_ACK_LOST_PACKET contition */
guint32 nextseqframe; /* frame number for segment with highest
* sequence number
*/基本上,有单独的会话提取逻辑,请注意find_conversation 用法。
/* Attach process info to a flow */
/* XXX - We depend on the TCP dissector finding the conversation first */
void
add_tcp_process_info(guint32 frame_num, address *local_addr, address *remote_addr, guint16 local_port, guint16 remote_port, guint32 uid, guint32 pid, gchar *username, gchar *command) {
conversation_t *conv;
struct tcp_analysis *tcpd;
tcp_flow_t *flow = NULL;
conv = find_conversation(frame_num, local_addr, remote_addr, PT_TCP, local_port, remote_port, 0);
if (!conv) {
return;
}实际的逻辑有很好的文档化和可用的这里:
/*
* Given two address/port pairs for a packet, search for a conversation
* containing packets between those address/port pairs. Returns NULL if
* not found.
*
* We try to find the most exact match that we can, and then proceed to
* try wildcard matches on the "addr_b" and/or "port_b" argument if a more
* exact match failed.
* ...
*/
conversation_t *
find_conversation(const guint32 frame_num, const address *addr_a, const address *addr_b, const port_type ptype,
const guint32 port_a, const guint32 port_b, const guint options)
{
conversation_t *conversation;
/*
* First try an exact match, if we have two addresses and ports.
*/
if (!(options & (NO_ADDR_B|NO_PORT_B))) {所以我实际上建议的是使用EPAN库。可以提取这个库并独立使用它。请小心驾驶执照。
发布于 2013-09-09 23:38:25
也许您对libipq - iptables用户空间数据包队列库感兴趣。
#include <linux/netfilter.h>
#include <libipq.h>Netfilter提供了一种机制,用于将数据包从堆栈中传递出去,以便排队到用户空间,然后将这些数据包接收回内核,并指定如何处理数据包(例如接受或丢弃)。在重新注入回内核之前,还可以在用户空间中修改这些数据包。对于每个受支持的协议,一个名为队列处理程序的内核模块可以向Netfilter注册,以执行向用户空间传递数据包和从用户空间传递数据包的机制。 IPv4的标准队列处理程序是ip_queue。它作为一个带有2.4内核的实验模块提供,并使用Netlink套接字进行内核/用户空间通信。 加载ip_queue后,可以使用iptables选择IP数据包,并通过队列目标排队进行用户空间处理
下面是如何分解tcp/ip数据包的简单示例:
ipq_packet_msg_t *m = ipq_get_packet(buf);
struct iphdr *ip = (struct iphdr*) m->payload;
struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl));
int port = htons(tcp->dest);
status = ipq_set_verdict(h, m->packet_id,
NF_ACCEPT, 0, NULL);
if (status < 0)
die(h);快速简介
如果这不是您要寻找的东西,您可以尝试使用wireshark EPAN图书馆。
https://stackoverflow.com/questions/18708569
复制相似问题