繁体   English   中英

Java HTTP/HTTPS 代理服务器

[英]Java HTTP/HTTPS Proxy Server

我正在编写自己的 Java 代理服务器。 当我尝试使用它时,我有正确的输出(我看到所有通过代理服务器的命令),但是我想访问的任何网站都无法正常工作,并且我的浏览器中出现以下错误:ERR_TUNNEL_CONNECTION_FAILED . 我实际上并不擅长网络问题,有些事情我不明白。 所以,下面是我的代码,如果有人告诉我问题出在哪里,我会很高兴:

import java.io.*;
import java.net.*;

public class ProxyServer
{
    private String host;
    private int localPort;
    private int remotePort;
    private ProxyServer(String host, int localPort, int remotePort)
    {
        this.host=host;
        this.localPort=localPort;
        this.remotePort=remotePort;
    }
    public static void main(String[] args) throws IOException
    {
        new ProxyServer("localhost", 8080, 9001).start();
    }
    public void start() throws IOException
    {
        System.out.println("Starting the proxy server for "+this.host+":"+this.localPort+"...");
        ServerSocket ss=new ServerSocket(this.localPort);
        final byte[] request=new byte[4096];
        byte[] response=new byte[4096];
        while(true)
        {
            Socket client=null;
            Socket server=null;
            try
            {
                client=ss.accept();
                final InputStream streamFromClient=client.getInputStream();
                OutputStream streamToClient=client.getOutputStream();
                System.out.println(new BufferedReader(new InputStreamReader(streamFromClient)).readLine());
                try
                {
                    server=new Socket(host, this.remotePort);
                }
                catch(IOException exc)
                {
                    PrintWriter out=new PrintWriter(streamToClient);
                    out.println("Proxy server cannot connect to "+host+":"+this.remotePort+"\n"+exc);
                    out.flush();
                    client.close();
                    continue;
                }
                InputStream streamFromServer=server.getInputStream();
                final OutputStream streamToServer=server.getOutputStream();
                System.out.println(new BufferedReader(new InputStreamReader(streamFromServer)).readLine());
                new Thread
                (
                    ()->
                    {
                        int bytesRead;
                        try
                        {
                            while((bytesRead=streamFromClient.read(request))!=-1)
                            {
                                streamToServer.write(request, 0, bytesRead);
                                streamToServer.flush();
                            }
                        }
                        catch(IOException exc){}
                        try
                        {
                            streamToServer.close();
                        }
                        catch(IOException exc){}
                    }
                ).start();
                int bytesRead;
                try
                {
                    while((bytesRead=streamFromServer.read(response))!=-1)
                    {
                        streamToClient.write(response, 0, bytesRead);
                        streamToClient.flush();
                    }
                }
                catch(IOException exc){}
                streamToClient.close();
            }
            catch(IOException exc)
            {
                System.out.println(exc.getMessage());
            }
            finally
            {
                try
                {
                    if(server!=null) server.close();
                    if(client!=null) client.close();
                }
                catch(IOException exc){}
            }
        }
    }
}

您使用预定义的硬编码目标制作了简单的 tcp 代理:host:remote_port

它不是 HTTP 代理。

因此,您的解决方案应该适用于以下情况:

  1. 您正在 localhost:9001 上运行 squid 或一些适当的 HTTP 代理。
  2. 并且仅将其用作 HTTP 代理(我的意思是,当您配置浏览器时,您不应该告诉它您的应用程序是 https 代理)。

如果您打算制作独立代理,那么您需要分析 HTTP 请求并从请求中获取主机、端口和协议,以了解您应该连接哪个服务器(包括端口)以及您应该使用哪个协议(即 http 或 https)。 当浏览器直接请求服务(没有代理)时,它只发送 URI,当浏览器通过代理发送请求时,它会在请求中使用完整的 URL。

所以请求中的第一行将是这样的:

GET http://google.com[:80]/blah-blah-blah HTTP/1.1
...headers here...

您的代理需要分析 URL 并从中获取主机、端口和 URI。 因此,您需要解析域名并使用修改后的第一行将主机连接到所需的端口。 它看起来像:

GET /blah-blah-blah HTTP/1.1
...headers here...

如果您使用额外的 http 代理服务器侦听 9001 端口,请检查它是否处于运行状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM