可以在网络上接收 TCP 流/UDP 数据报吗?

发布于 2024-08-13 17:09:01 字数 197 浏览 8 评论 0原文

有没有人做过使用 UDPSocket (用于 UDP 数据报)和 InputStream (用于 TCP 流)实现的数据包捕获接口(如 jpcap)的工作)?

我想考虑到 jpcap 中的回调 API,这不会太难,但是有人已经这样做了吗?这样做有什么问题吗(例如,我是否必须自己弄清楚如何重新组装 TCP 流?)

Has anyone out there done the work of sitting on top of a packet capture interface (like jpcap) with an implementation of UDPSocket (for UDP datagrams) and InputStream (for TCP streams)?

I suppose it wouldn't be too hard to do given the callback API in jpcap, but has anyone out there already done it? Are there any issues with doing this (do I have to figure out how to reassemble a TCP stream myself, for example?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

思念绕指尖 2024-08-20 17:09:01

我还没有做过这个特别的事情,但我确实做了很多工作来解析 C/C++ 中捕获的数据包。我不知道是否有 Java 库可以实现这些。

本质上,您需要从 IP 开始,沿着协议栈向上发展。 pcap 数据以链路级标头开始,但我认为除了忽略非 IP 数据包之外,您并不关心其中的太多内容。

IP 最棘手的事情是重新组装碎片数据报。这是通过使用标志字段中的更多片段位和片段偏移字段,结合标识字段来区分来自不同数据报的片段然后使用协议字段来标识 TCP 和 UDP 数据包,并使用标头长度字段来查找相应标头的开始。

对于 TCP 和 UDP,下一步是解复用,分离出捕获的数据包流中的各种连接。两种协议都通过源和目标 IP 地址以及源和目标端口的 4 元组来识别连接(嗯,UDP 本身没有连接,但我没有更好的词方便),因此连接将是与所有 4 个值相匹配的数据包序列。

一旦完成,对于 UDP,你就差不多完成了,除非你想检查校验和。 UDP 标头中的长度字段告诉您数据包的长度;减去 8 个字节作为标头,这就是您的数据。

TCP 有点复杂,因为您确实必须重新组装流,这是使用标头中的序列号与长度相结合来完成的。这两者的总和告诉您流中的下一个序列号。请记住,您正在跟踪两个方向的流量。

(这比编写实际的 TCP 实现要容易得多,因为那时您必须实现 Nagle 算法和其他细节。)

网上有很多关于标头格式的信息;对于初学者来说,谷歌“IP header”。像 Wireshark 这样的网络分析仪对于这项工作是必不可少的,因为它会向您展示捕获的数据应该是什么样子。事实上,由于 Wireshark 是开源的,您可能可以通过查看它的工作方式来了解很多信息

I have not done this particular thing, but I do do a lot of work with parsing captured packets in C/C++. I don't know if there exist Java libraries for any of this.

Essentially, you need to work your way up the protocol stack, starting with IP. The pcap data starts with the link-level header, but I don't think there's much in it that you're concerned about, other than ignoring non-IP packets.

The trickiest thing with IP is reassembling fragmented datagrams. This is done using the More Fragments bit in the Flags field and the Fragment Offset field, combined with the Identification field to distinguish fragments from different datagrams Then you use the Protocol field to identify TCP and UDP packets, and the Header Length field to find the start of the corresponding header.

The next step, for both TCP and UDP, is demultiplexing, separating out the various connections in the captured packet stream. Both protocols identify connections (well, UDP doesn't have connections per se, but I don't have a better word handy) by the 4-tuple of the source and destination IP address and the source and destination port, so a connection would be a sequence of packets that matches on all 4 of these values.

Once that's done, for UDP, you're just about finished, unless you want to check the checksum. The Length field in the UDP header tells you how long the packet is; subtract 8 bytes for the header and there's your data.

TCP is somewhat more complicated, as you do indeed have to reassemble the stream, This is done using the sequence number in the header, combined with the length. The sum of these two tells you the next sequence number in the stream. Remember that you're keeping track of the traffic in two directions.

(This is a lot easier than writing an actual TCP implementation, as then you have to implement the Nagle algorithm and other minutiae.)

There's a lot of information on the net about the header formats; google "IP header" for starters. A network analyzer like Wireshark is indispensable for this work, as it will show you how your captured data is supposed to look. Indeed, as Wireshark is open source, you can probably find out a lot by looking at how it does things

oО清风挽发oО 2024-08-20 17:09:01

Tcp 重组可以使用 JNetPcap 完成。这是一个完整的例子:

final String SOME_PORT = 8888;

StringBuilder errbuf = new StringBuilder();
Pcap pcap = Pcap.openOffline("/dir/someFile.pcap", errbuf); //Can be replace with .openLive(...)

if (pcap == null) {
    System.err.printf("Error: "+errbuf.toString());
    return;
}

//Handler that receive Tcp Event one by one
AnalyzerListener<TcpStreamEvent> handler = new AnalyzerListener<TcpStreamEvent>() {

    @Override
    public void processAnalyzerEvent(TcpStreamEvent evt) {
        JPacket packet = evt.getPacket();

        Tcp tcp = new Tcp();
        if (packet.hasHeader(tcp)) {

              //Limiting the analysis to a specific protocol
              if (tcp.destination() == SOME_PORT || tcp.source() == SOME_PORT) {
                    String data = new String(tcp.getPayload());
                    System.out.println("Capture data:{"+data+"}");
              }
        }
    }
};

TcpAnalyzer tcpAnalyzer = JRegistry.getAnalyzer(TcpAnalyzer.class);
tcpAnalyzer.addTcpStreamListener(handler, null);

//Starting the capture
pcap.loop(Pcap.LOOP_INFINATE,  JRegistry.getAnalyzer(JController.class), null);

Tcp reassembly can be done with JNetPcap. Here is a complete example:

final String SOME_PORT = 8888;

StringBuilder errbuf = new StringBuilder();
Pcap pcap = Pcap.openOffline("/dir/someFile.pcap", errbuf); //Can be replace with .openLive(...)

if (pcap == null) {
    System.err.printf("Error: "+errbuf.toString());
    return;
}

//Handler that receive Tcp Event one by one
AnalyzerListener<TcpStreamEvent> handler = new AnalyzerListener<TcpStreamEvent>() {

    @Override
    public void processAnalyzerEvent(TcpStreamEvent evt) {
        JPacket packet = evt.getPacket();

        Tcp tcp = new Tcp();
        if (packet.hasHeader(tcp)) {

              //Limiting the analysis to a specific protocol
              if (tcp.destination() == SOME_PORT || tcp.source() == SOME_PORT) {
                    String data = new String(tcp.getPayload());
                    System.out.println("Capture data:{"+data+"}");
              }
        }
    }
};

TcpAnalyzer tcpAnalyzer = JRegistry.getAnalyzer(TcpAnalyzer.class);
tcpAnalyzer.addTcpStreamListener(handler, null);

//Starting the capture
pcap.loop(Pcap.LOOP_INFINATE,  JRegistry.getAnalyzer(JController.class), null);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文