我正在创建一个依赖于设置http.proxyPort
和http.proxyHost
的Java应用程序。有两个过程:一个是常规程序,另一个是代理。我有一个简单的套接字监听器在http.proxyPort
上运行(我控制)。它就像
while (true) {
try {
Socket connection = server.accept();
Handler handler = new Handler(connection);
handler.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
所以每当“进程1”发出http请求时 - 比如
URL yahoo = new URL("http://www.google.ca/");
URLConnection yc = yahoo.openConnection();
System.out.println(yc.getClass().getName());
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
它通过代理。现在如果客户端使用HTTPS协议怎么办?比如使用https://google.ca
?有一个属性https.proxyPort
和https.proxyHost
,但我确实已经尝试了几个月(开启和关闭,它不是太重要)没有运气。我已经阅读了一堆线程(我会在最后列出一些,所以你知道我已经做了一些事情。)
到目前为止我最接近的尝试: 服务器
try {
System.setProperty("javax.net.ssl.keyStore", "test.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "2520xe");
SSLServerSocketFactory sslserversocketfactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket =
(SSLServerSocket) sslserversocketfactory.createServerSocket(9999);
System.out.println("Ready");
SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
OutputStream toClient = sslsocket.getOutputStream();
toClient.write(("HTTP/1.0 200 Connection established\n" +
"Content-Length: " + "Shut down!".getBytes().length
+ "\r\n").getBytes("utf-8"));
toClient.write("Shut down!".getBytes("utf-8"));
toClient.close();
} catch (Exception exception) {
exception.printStackTrace();
}
客户端
try {
System.setProperty("https.proxyHost", "127.0.0.1");
System.setProperty("https.proxyPort", "9999");
URL yahoo = new URL("https://www.google.ca/");
URLConnection yc = yahoo.openConnection();
System.out.println(yc.getClass().getName());
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
我收到此错误javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
我用谷歌搜索了它,但却想出了一些邮件。
基本上,我需要创建一个java代理服务器,它通过https.proxyPort
和https.proxyHost
标志设置为客户端,并且可以将数据发送回客户端应用程序,这可能不会以任何方式进行修改(仅使用URL connection = new URL("https://...")
)
我试过的一些网站......
答案 0 :(得分:8)
正如auntyellow评论的那样:你不需要自己做任何SSL摆弄。基本上,https-proxying是关于在两方之间转发二进制数据。
引用draft-luotonen-web-proxy-tunneling-01.txt:
CLIENT -> SERVER SERVER -> CLIENT -------------------------------------- ----------------------------------- CONNECT home.netscape.com:443 HTTP/1.0 User-agent: Mozilla/4.0 <<< empty line >>> HTTP/1.0 200 Connection established Proxy-agent: Netscape-Proxy/1.1 <<< empty line >>> <<< data tunneling to both directions begins >>>
所以基本上你需要确保你信任你的客户足以从你的代理防火墙位置连接到给定的主机和端口。由于这种常见的做法是将允许的端口限制为443,拒绝与localhost的连接以及来自&#34; untrusted&#34;方。
这是一个简单的&#34;服务器,如果您不相信,可以在Java中用作https.proxy
:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created for http://stackoverflow.com/q/16351413/1266906.
*/
public class Server extends Thread {
public static void main(String[] args) {
(new Server()).run();
}
public Server() {
super("Server Thread");
}
@Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(9999)) {
Socket socket;
try {
while ((socket = serverSocket.accept()) != null) {
(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
return;
}
}
public static class Handler extends Thread {
public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])",
Pattern.CASE_INSENSITIVE);
private final Socket clientSocket;
private boolean previousWasR = false;
public Handler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
String request = readLine(clientSocket);
System.out.println(request);
Matcher matcher = CONNECT_PATTERN.matcher(request);
if (matcher.matches()) {
String header;
do {
header = readLine(clientSocket);
} while (!"".equals(header));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream(),
"ISO-8859-1");
final Socket forwardSocket;
try {
forwardSocket = new Socket(matcher.group(1), Integer.parseInt(matcher.group(2)));
System.out.println(forwardSocket);
} catch (IOException | NumberFormatException e) {
e.printStackTrace(); // TODO: implement catch
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 502 Bad Gateway\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
return;
}
try {
outputStreamWriter.write("HTTP/" + matcher.group(3) + " 200 Connection established\r\n");
outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
outputStreamWriter.write("\r\n");
outputStreamWriter.flush();
Thread remoteToClient = new Thread() {
@Override
public void run() {
forwardData(forwardSocket, clientSocket);
}
};
remoteToClient.start();
try {
if (previousWasR) {
int read = clientSocket.getInputStream().read();
if (read != -1) {
if (read != '\n') {
forwardSocket.getOutputStream().write(read);
}
forwardData(clientSocket, forwardSocket);
} else {
if (!forwardSocket.isOutputShutdown()) {
forwardSocket.shutdownOutput();
}
if (!clientSocket.isInputShutdown()) {
clientSocket.shutdownInput();
}
}
} else {
forwardData(clientSocket, forwardSocket);
}
} finally {
try {
remoteToClient.join();
} catch (InterruptedException e) {
e.printStackTrace(); // TODO: implement catch
}
}
} finally {
forwardSocket.close();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
}
private static void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[4096];
int read;
do {
read = inputStream.read(buffer);
if (read > 0) {
outputStream.write(buffer, 0, read);
if (inputStream.available() < 1) {
outputStream.flush();
}
}
} while (read >= 0);
} finally {
if (!outputSocket.isOutputShutdown()) {
outputSocket.shutdownOutput();
}
}
} finally {
if (!inputSocket.isInputShutdown()) {
inputSocket.shutdownInput();
}
}
} catch (IOException e) {
e.printStackTrace(); // TODO: implement catch
}
}
private String readLine(Socket socket) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int next;
readerLoop:
while ((next = socket.getInputStream().read()) != -1) {
if (previousWasR && next == '\n') {
previousWasR = false;
continue;
}
previousWasR = false;
switch (next) {
case '\r':
previousWasR = true;
break readerLoop;
case '\n':
break readerLoop;
default:
byteArrayOutputStream.write(next);
break;
}
}
return byteArrayOutputStream.toString("ISO-8859-1");
}
}
}
答案 1 :(得分:1)
用于HTTPS协议的URLConnection的默认java SE7实现使用参数
https.proxyHost 和 https.proxyPort
添加到Tomcat:
-Dhttps.proxyHost =“192.168.121.31”-Dhttps.proxyPort =“3128”