monkeyWie / proxyee

HTTP proxy server,support HTTPS&websocket.MITM impl,intercept and tamper HTTPS traffic.
MIT License
1.5k stars 566 forks source link

1.7.6版本下,无法拦截HTTPS的响应,只能拦截HTTP的相应 || In version 1.7.6, HTTPS responses cannot be intercepted, only HTTP responses can be intercepted. #296

Open cjy1708 opened 3 weeks ago

cjy1708 commented 3 weeks ago

使用这些代码,在match方法的return上打断点,发现使用HTTP请求会被拦截,但是使用HTTPS请求则不会被拦截。

fun main() {
    val config = HttpProxyServerConfig()
    config.isHandleSsl = true
    HttpProxyServer().apply {
        serverConfig(config)

        proxyInterceptInitializer(object : HttpProxyInterceptInitializer() {
            override fun init(pipeline: HttpProxyInterceptPipeline) {
                pipeline.addLast(CertDownIntercept())
                pipeline.addLast(object : FullResponseIntercept() {
                    override fun match(
                        httpRequest: HttpRequest,
                        httpResponse: HttpResponse,
                        pipeline: HttpProxyInterceptPipeline
                    ): Boolean {
                        return true
                    }

                    override fun handleResponse(
                        httpRequest: HttpRequest?,
                        httpResponse: FullHttpResponse?,
                        pipeline: HttpProxyInterceptPipeline?
                    ) {
                        super.handleResponse(httpRequest, httpResponse, pipeline)
                    }
                })
            }
        })
        start(9999)
    }
}

排查源码发现,收到HTTPS请求时,setInterceptPipeline(buildPipeline())没有被调用。

@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
    if (msg instanceof HttpRequest) {
        // 省略

        if (getStatus() == 0) {
            // 省略
            setStatus(1);
            if (HttpMethod.CONNECT.name().equalsIgnoreCase(request.method().name())) {// 建立代理握手
                setStatus(2);
                HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpProxyServer.SUCCESS);
                ctx.writeAndFlush(response);
                ctx.channel().pipeline().remove("httpCodec");
                // fix issue #42
                ReferenceCountUtil.release(msg);
                return;
            }
        }
        setInterceptPipeline(buildPipeline());
        // 省略
    }
}

到这里直接跳过了后面的代码执行,不会执行setInterceptPipeline(buildPipeline());部分。

请问是我的调用出现问题了吗?还是其他版本没有出现这个问题?


Using these codes, break the point on the return of the match method and find that requests using HTTP will be intercepted, but requests using HTTPS will not be intercepted.

fun main() {
    val config = HttpProxyServerConfig()
    config.isHandleSsl = true
    HttpProxyServer().apply {
        serverConfig(config)

        proxyInterceptInitializer(object : HttpProxyInterceptInitializer() {
            override fun init(pipeline: HttpProxyInterceptPipeline) {
                pipeline.addLast(CertDownIntercept())
                pipeline.addLast(object : FullResponseIntercept() {
                    override fun match(
                        httpRequest: HttpRequest,
                        httpResponse: HttpResponse,
                        pipeline: HttpProxyInterceptPipeline
                    ): Boolean {
                        return true
                    }

                    override fun handleResponse(
                        httpRequest: HttpRequest?,
                        httpResponse: FullHttpResponse?,
                        pipeline: HttpProxyInterceptPipeline?
                    ) {
                        super.handleResponse(httpRequest, httpResponse, pipeline)
                    }
                })
            }
        })
        start(9999)
    }
}

After checking the source code, we found that setInterceptPipeline(buildPipeline()) was not called when receiving an HTTPS request.

@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
    if (msg instanceof HttpRequest) {
        // Omit

        if (getStatus() == 0) {
            // Omit
            setStatus(1);
            if (HttpMethod.CONNECT.name().equalsIgnoreCase(request.method().name())) {// Establish proxy handshake
                setStatus(2);
                HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpProxyServer.SUCCESS);
                ctx.writeAndFlush(response);
                ctx.channel().pipeline().remove("httpCodec");
                // fix issue #42
                ReferenceCountUtil.release(msg);
                return;
            }
        }
        setInterceptPipeline(buildPipeline());
        // Omit
    }
}

The subsequent code execution is skipped here, and the setInterceptPipeline(buildPipeline()); part will not be executed.

Is there something wrong with my call? Or does this problem not occur in other versions?