我在一个基于 TUN 的 VPN 服务器上工作,它的目标是在将它们转发到目的地之前分析它收到的数据包。目前我正在从 TUN 接口(interface)接收 IP 数据包,并简单地将它们原封不动地发送到目的地。
我知道分析 UDP 数据包的内容就像剥离 IP 和 UDP header 一样简单。但是,要分析 TCP 流量的内容,我需要从多个 IP 数据包中重建消息。有没有一种简单的方法可以在不重新实现 TCP 的情况下做到这一点?是否有用于此任务的易于访问的 C/C++ 库?我更喜欢 Linux 系统库和/或开源、非病毒/非 copyleft 库。
我已经考虑过的一件事是制作每个 IP 数据包的拷贝,并将拷贝的目标 IP 更改为本地主机,以便我的服务器的不同部分可以接收这些 TCP 请求和响应,这些请求和响应完全重构且没有 header 。但是,我无法将目标 IP 与流量内容相关联,这是我想要的。
最佳答案
您需要的功能很可能总是与数据包解析紧密结合。确实需要好的协议(protocol)解析器来提取所需的信息。所以我的建议是使用可用的最佳开源工具 - wireshark.org
它提供“跟随 TCP 流”功能:
我看起来不像您可以轻松提取 Wireshark 剖析逻辑的一部分,但至少有一个很好的例子 packet-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
usage :
/* 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;
}
实际逻辑有据可查且可用 here :
/*
* 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 library .可以提取这个库并独立使用它。请小心使用许可证。
关于c++ - 如何从多个 IP 数据包重建 TCP 流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18727135/