【问题标题】:HTTP CONNECT Tunnel reply with BAD Request (400)带有错误请求的 HTTP CONNECT 隧道回复 (400)
【发布时间】:2017-08-11 11:59:42
【问题描述】:

我有这个 HTTP 隧道的代码

private static void doTunnelHandshake(Socket conn, String proxyHost, int proxyPort, String host, int port) throws IOException {

    String msg = "CONNECT " + host + ":" + port + " HTTP/1.1\n" + "Host: https://" + proxyHost + ":" + proxyPort + "\r\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent+ "\r\n\r\n";

OutputStream out = conn.getOutputStream();

byte b[];
try {
    /*
     * We really do want ASCII7 -- the http protocol doesn't change with
     * locale.
     */
    b = msg.getBytes("ASCII7");
} catch (UnsupportedEncodingException ignored) {
    /*
     * If ASCII7 isn't there, something serious is wrong, but Paranoia
     * Is Good (tm)
     */
    b = msg.getBytes();
}

out.write(b);
out.flush();

/*
 * We need to store the reply so we can create a detailed error message
 * to the user.
 */
byte reply[] = new byte[200];
int replyLen = 0;
int newlinesSeen = 0;
boolean headerDone = false; /* Done on first newline */

InputStream in = conn.getInputStream();

while (newlinesSeen < 2) {
    int i = in.read();
    if (i < 0) {
        throw new IOException("Unexpected EOF from proxy");
    }
    if (i == '\n') {
        headerDone = true;
        ++newlinesSeen;
    } else if (i != '\r') {
        newlinesSeen = 0;
        if (!headerDone && replyLen < reply.length) {
            reply[replyLen++] = (byte) i;
        }
    }
}

/*
 * Converting the byte array to a string is slightly wasteful in the
 * case where the connection was successful, but it's insignificant
 * compared to the network overhead.
 */
String replyStr;
try {
    replyStr = new String(reply, 0, replyLen, "ASCII7");
} catch (UnsupportedEncodingException ignored) {
    replyStr = new String(reply, 0, replyLen);
}



/* We asked for HTTP/1.0, so we should get that back */
if (!replyStr.startsWith("HTTP/1.0 200")) {
    throw new IOException("Unable to tunnel for " + host + ":" + port + ".  TunnelProxy returns \"" + replyStr + "\"");
} 

/* tunneling Handshake was successful! */
}

但 apache 回复

“HTTP/1.1 400 错误请求”

【问题讨论】:

    标签: java apache http


    【解决方案1】:

    找到解决方案!

    缺少\r

    String msg = "CONNECT " + host + ":" + port + " HTTP/1.1\r\n" + "Host: https://" + proxyHost + ":" + proxyPort + "\r\n" + "User-Agent: " + sun.net.www.protocol.http.HttpURLConnection.userAgent+ "\r\n\r\n";
    

    【讨论】:

    • 这是最令人惊奇的,因为 RFC 要求将 \n\r\n 一样对待。也许有问题的状态机不喜欢将两者混合。
    • 以前的版本运行良好,现在打了安全补丁后出现了这个问题
    【解决方案2】:

    这是一个理论:您的CONNECT 调用格式错误,因为Host header 指定过多;它 - 在这种情况下 - 不应该包含一个完全限定的 URL,而是一个主机名和(如果需要)一个端口。 CONNECTHost 也应该匹配。在这种情况下,代理主机和端口无关紧要,因为您已经打开了套接字。您的初始请求应该(根据RFC 7231, sec. 4.3.6 看起来像这样:

    CONNECT host:port HTTP/1.1
    Host: host:port
    

    在相关说明中,您可以剥离 ASCII7 内容。 HTTP 的“控制代码”可以在 US-ASCII 中工作,但消息正文可能不行。更糟糕的是,选择标头可能包含 UTF8。当您在 HTTP/1.1 中发送请求而期望 HTTP/1.0 在您的代码中响应时,我也有点困惑。

    【讨论】:

    • 服务器回复 HTTP/1.0 200...也许我可以添加 HTTP/1.1 200
    • 可能是peer只支持1.0。这是学术作业吗?
    • 不...实际生产
    猜你喜欢
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 2016-11-18
    • 1970-01-01
    相关资源
    最近更新 更多