Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client remote connections fail to Cloudflare (on Windows x64) #299

Open
Jire opened this issue May 13, 2024 · 1 comment
Open

Client remote connections fail to Cloudflare (on Windows x64) #299

Jire opened this issue May 13, 2024 · 1 comment

Comments

@Jire
Copy link

Jire commented May 13, 2024

qlog

�{"qlog_version":"0.3","qlog_format":"JSON-SEQ","title":"testTitle","description":"test id=4daa99b8d91a40905c8e17805f9ba0f636de3791","trace":{"vantage_point":{"type":"client"},"title":"testTitle","description":"test id=4daa99b8d91a40905c8e17805f9ba0f636de3791","configuration":{"time_offset":0.0}}}
�{"time":0.0,"name":"transport:parameters_set","data":{"owner":"local","tls_cipher":"None","disable_active_migration":false,"max_idle_timeout":5000,"max_udp_payload_size":65527,"ack_delay_exponent":3,"max_ack_delay":25,"active_connection_id_limit":2,"initial_max_data":10000000,"initial_max_stream_data_bidi_local":1000000,"initial_max_stream_data_bidi_remote":1000000,"initial_max_stream_data_uni":1000000,"initial_max_streams_bidi":100,"initial_max_streams_uni":100}}
�{"time":0.5261,"name":"transport:packet_sent","data":{"header":{"packet_type":"initial","packet_number":0,"version":"1","scil":20,"dcil":16,"scid":"4daa99b8d91a40905c8e17805f9ba0f636de3791","dcid":"ae7a95cc31400e7f45e73de419708b65"},"raw":{"length":316,"payload_length":253},"send_at_time":0.5261,"frames":[{"frame_type":"crypto","offset":0,"length":249}]}}
�{"time":0.5261,"name":"recovery:metrics_updated","data":{"smoothed_rtt":333.0,"rtt_variance":166.5,"congestion_window":12000,"bytes_in_flight":316,"ssthresh":18446744073709551615}}
�{"time":7.5481,"name":"transport:packet_received","data":{"header":{"packet_type":"initial","packet_number":0,"version":"1","scil":20,"dcil":20,"scid":"019c09f8632ac8a9139e80f8a22ade62d89d9b78","dcid":"4daa99b8d91a40905c8e17805f9ba0f636de3791"},"raw":{"length":1200,"payload_length":23},"frames":[{"frame_type":"ack","ack_delay":0.068,"acked_ranges":[[0,0]]}]}}
�{"time":7.5481,"name":"recovery:metrics_updated","data":{"min_rtt":7.022,"smoothed_rtt":7.022,"latest_rtt":7.022,"rtt_variance":3.511,"bytes_in_flight":0}}
�{"time":8.7484,"name":"transport:packet_received","data":{"header":{"packet_type":"initial","packet_number":1,"version":"1","scil":20,"dcil":20,"scid":"019c09f8632ac8a9139e80f8a22ade62d89d9b78","dcid":"4daa99b8d91a40905c8e17805f9ba0f636de3791"},"raw":{"length":1200,"payload_length":22},"frames":[{"frame_type":"connection_close","error_space":"transport_error","error_code":296,"reason":""}]}}

Reproduce with this on Windows x64:

import io.netty.bootstrap.Bootstrap
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioDatagramChannel
import io.netty.handler.ssl.util.InsecureTrustManagerFactory
import io.netty.incubator.codec.http3.*
import io.netty.incubator.codec.quic.*
import io.netty.util.ReferenceCountUtil
import java.net.InetSocketAddress
import java.util.concurrent.TimeUnit

object JS5ProxyServer {

    @JvmStatic
    fun main(args: Array<String>) {
        val hostName = "areos.io"
        val js5Port = 443

        val group = NioEventLoopGroup(1)

        try {
            val context = QuicSslContextBuilder.forClient()
                .trustManager(InsecureTrustManagerFactory.INSTANCE)
                .applicationProtocols(*Http3.supportedApplicationProtocols())
                .build()
            val codec = Http3.newQuicClientCodecBuilder()
                .sslContext(context)
                .initialMaxStreamsBidirectional(100)
                .initialMaxStreamsUnidirectional(100)
                .initialMaxData(10000000)
                .initialMaxStreamDataBidirectionalLocal(1000000)
                .initialMaxStreamDataBidirectionalRemote(1000000)
                .initialMaxStreamDataUnidirectional(1000000)
                .maxIdleTimeout(5000, TimeUnit.MILLISECONDS)
                .build()

            val bs = Bootstrap()
            val channel = bs.group(group)
                .channel(NioDatagramChannel::class.java)
                .handler(codec)
                .bind(0)
                .sync()
                .channel()

            val quicChannel = QuicChannel.newBootstrap(channel)
                .handler(Http3ClientConnectionHandler())
                .remoteAddress(InetSocketAddress(hostName, js5Port))
                .option(
                    QuicChannelOption.QLOG,
                    QLogConfiguration("quiclog.txt", "testTitle", "test")
                )
                .connect()
                .get()

            val streamChannel = Http3.newRequestStream(quicChannel,
                object : Http3RequestStreamInboundHandler() {
                    override fun channelRead(ctx: ChannelHandlerContext, frame: Http3HeadersFrame) {
                        println("header frame: $frame")

                        ReferenceCountUtil.release(frame)
                    }

                    override fun channelRead(ctx: ChannelHandlerContext, frame: Http3DataFrame) {
                        println("data frame: $frame")

                        ReferenceCountUtil.release(frame)
                    }

                    override fun channelInputClosed(ctx: ChannelHandlerContext) {
                        println("channel input closed")

                        ctx.close()
                    }
                }).sync().now

            streamChannel
                .pipeline()
                .addLast(
                    Http3FrameToHttpObjectCodec(false, false)
                )

            val headers = DefaultHttp3Headers(false)
                .method("GET")
                .path("/flat-cache/0-0.dat")
                .authority("$hostName:$js5Port")
                .scheme("https")
            val headersFrame = DefaultHttp3HeadersFrame(headers)
            streamChannel.writeAndFlush(headersFrame)
                .addListener(QuicStreamChannel.SHUTDOWN_OUTPUT).sync()

            // Wait for the stream channel and quic channel to be closed (this will happen after we received the FIN).
            // After this is done we will close the underlying datagram channel.
            streamChannel.closeFuture().sync()

            // After we received the response lets also close the underlying QUIC channel and datagram channel.
            quicChannel.close().sync()
            channel.close().sync()
        } finally {
            group.shutdownGracefully()
        }
    }

}
@normanmaurer
Copy link
Member

Unfortunately I have no windows installation to test this with. That said I wonder if you need to set the correct hostname when creating the SSlEngine:

 Http3.newQuicClientCodecBuilder().sslEngineProvider(q -> sslContext.newEngine(q.alloc(), hostname, port))

This way the correct SNI hostname is used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants