2

某些东西正在改变写入我的 Windows (Windows 7) 机器上的 TCP 套接字的数据 - 具体来说,当字节遵循特定的 HTTP POST 模式时,当从连接的相应侦听器套接字端读取字节时,模式会重复。

以下字节被写入客户端套接字(注意:每行以回车符和换行符结尾,两个非空行后跟两个空行):

POST / HTTP/1.1
Transfer-Encoding: chunked

从侦听器套接字读取的内容是:

POST / HTTP/1.1
Transfer-Encoding: chunked


POST / HTTP/1.1
Transfer-Encoding: chunked

我已经在我的机器上的环回(127.0.0.1)地址上对此进行了测试,但是当侦听器套接字在另一台机器上时,我也看到了修改后的字节,所以看起来字节在客户端被修改了。我已经在我的机器上使用 netcat 和 java 程序(见下文)重现了这个问题,所以问题似乎出在 TCP 堆栈中。我只能使用一组特定的 HTTP 标头来触发它,因此似乎有什么东西正在对我的 TCP 通信进行深度数据包检查并对其进行更改。如果我稍微改变输入字节(例如,它不是一个有效的 HTTP 请求,例如,将“POST”更改为“QOST”,它工作正常)。

下面是我编写的一个 java 程序,它演示了这一点及其输出:

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;

public final class Main {

    private static final String PAYLOAD
        = "POST / HTTP/1.1\r\n"
            + "Transfer-Encoding: chunked\r\n"
            + "\r\n"
            + "\r\n"
            ;
    private static final int PORT = 8080;

    public static final void main(final String[] args) throws Exception {
        final Thread serverThread = new Thread(new Server());
        serverThread.start();

        final byte[] payloadBytes = PAYLOAD.getBytes(Charset.forName("UTF-8"));
        int i = 0;
        try (final Socket socket = new Socket(InetAddress.getLoopbackAddress(), PORT)) {
            socket.setTcpNoDelay(true);
            final OutputStream os = socket.getOutputStream();
            for (final byte byteValue : payloadBytes) {
                os.write(byteValue);
                os.flush();
                i++;
            }
        }
        serverThread.join();
        System.out.println("bytes written: " + i);
    }

    private static final class Server implements Runnable {

        @Override
        public void run() {
            try (final ServerSocket serverSocket = new ServerSocket(PORT)) {
//                while (true) {
                    final Socket socket = serverSocket.accept();
                    socket.setTcpNoDelay(true);
                    try (final InputStream is = socket.getInputStream()) {
                        int i = 0;
                        int byteValue;
                        while ((byteValue = is.read()) >= 0) {
                            System.out.print((char) byteValue);
                            System.out.flush();
                            i++;
                        }
                        System.out.println("----------------");
                        System.out.println("bytes read: " + i);
                    }
//                }
            } catch (final Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

输出:

POST / HTTP/1.1
Transfer-Encoding: chunked


POST / HTTP/1.1
Transfer-Encoding: chunked

----------------
bytes read: 96
bytes written: 49

下面是在 windows 上使用 netcat(来自 cygwin 的 nc.exe)的相同测试(注意:文件 test_payload.blob 包含如上所述的字节,并从 java 程序中的 PAYLOAD 常量派生):

启动 nc 监听器:

nc -l 8080 > nc_capture; more nc_capture

运行 nc 客户端(在侦听器的另一个 shell 中):

nc -v 127.0.0.1 8080 < test_payload.blob

写入 nc_capture 的输出:

POST / HTTP/1.1
Transfer-Encoding: chunked


POST / HTTP/1.1
Transfer-Encoding: chunked

我的第一个想法是防火墙有问题,所以我禁用了它,但它仍然会发生。我也试过重置我的winsock和tcp/ip,它仍然发生。我尝试禁用我的所有网络适配器(上述测试适用于环回 IP 地址,因此不需要它们),它仍然会发生。在这一点上,我几乎没有想法,我什至不知道我将如何尝试在较低级别进行调试。有没有人见过这样的东西?Windows 上是否有一些低级别的诊断工具,我可以使用它来查看它可能与我的 TCP 堆栈挂钩的内容?

4

0 回答 0