带有BAD请求的HTTP CONNECT隧道回复(400)

时间:2017-08-11 11:59:43

标签: java apache http

我有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回复

  

&#34; HTTP / 1.1 400错误请求&#34;

2 个答案:

答案 0 :(得分:2)

找到解决方案!

缺少\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";

答案 1 :(得分:1)

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

clear-host
$name = wmic bios get serialnumber
$name = $name[2]
$computername = "LT-" + "$name"
$computername.replace(' ','')
Rename-Computer -NewName $computername

在相关说明中,您可以删除ASCII7内容。 HTTP的“控制代码”可以使用US-ASCII,但邮件正文可能不行。更糟糕的是,select头可能包含UTF8。我也有点困惑,因为你在HTTP / 1.1中发出请求,同时期望你的代码中有HTTP / 1.0响应。