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

Add connect_with_stream method #75

Closed
wants to merge 1 commit into from
Closed

Add connect_with_stream method #75

wants to merge 1 commit into from

Conversation

radioactiveAHM
Copy link

This function is similar to connect_with, but it also provides streams (usually TCP streams) as mutable to the callback function. This feature is essential for scenarios where manual TLS client hello fragmenting is necessary, as demonstrated in the following example.

        let tls_conn = h2tls_connector.connect_with_stream(example_com, tcp, |tls, tcp| {
            // Buffer to store TLS Client Hello
            let mut buff = Vec::with_capacity(1024 * 4);
            let mut cur = std::io::Cursor::new(&mut buff);
            // Write TLS Client Hello to Buffer
            let l = tls.write_tls(&mut cur).unwrap();
            let psize = (l - 5) / 2;
            let xtls = [
                [&[22, 3, 1, 0, buff[5..psize].len() as u8], &buff[5..psize]].concat(),
                [&[22, 3, 1, 0, buff[psize..].len() as u8], &buff[psize..]].concat(),
            ]
            .concat();
            tokio::task::block_in_place(move || {
                tokio::runtime::Handle::current().block_on(async {
                    tcp.write(&xtls).await.unwrap();
                });
            });
        })
        .await;

@cpu
Copy link
Member

cpu commented Jun 3, 2024

This feature is essential for scenarios where manual TLS client hello fragmenting is necessary

What kind of scenario necessitates this? Something related to bypassing naive DPI?

@radioactiveAHM
Copy link
Author

This feature is essential for scenarios where manual TLS client hello fragmenting is necessary

What kind of scenario necessitates this? Something related to bypassing naive DPI?

I use this method to bypass the Great Firewall (GFW) censorship, which specifically targets the Server Name Indication (SNI). When I fragment the TLS ClientHello packet, the GFW no longer detects my SNI. This approach is my sole solution for evading GFW restrictions, especially since Rustls does not yet support Encrypted Client Hello (ECH) or Encrypted SNI (ESNI).

@cpu
Copy link
Member

cpu commented Jun 3, 2024

Thanks for providing more detail.

I can't speak for the other maintainers but I'm a bit skeptical about accepting this change since the use-case seems quite narrow and is unlikely to be long-term stable. The GFW may mishandle fragmented client hello messages today but I expect that will change over time as more handshakes start to naturally fragment (e.g. due to the situation described in tldr.fail).

Rustls does not yet support Encrypted Client Hello (ECH) or Encrypted SNI (ESNI).

Our ECH implementation (rustls/rustls#1718) is quickly approaching merge-ability. IMO that seems like a better route towards accomplishing your overall goal.

@radioactiveAHM
Copy link
Author

Thanks for providing more detail.

I can't speak for the other maintainers but I'm a bit skeptical about accepting this change since the use-case seems quite narrow and is unlikely to be long-term stable. The GFW may mishandle fragmented client hello messages today but I expect that will change over time as more handshakes start to naturally fragment (e.g. due to the situation described in tldr.fail).

Rustls does not yet support Encrypted Client Hello (ECH) or Encrypted SNI (ESNI).

Our ECH implementation (rustls/rustls#1718) is quickly approaching merge-ability. IMO that seems like a better route towards accomplishing your overall goal.

You're welcome.

You’re absolutely correct, and there are indeed other use cases. This method serves as a straightforward way to prevent someone, including myself, from encountering issues in the future. Additionally, it proves valuable for early data. At present, my application relies heavily on this approach.

@cpu
Copy link
Member

cpu commented Jun 4, 2024

You’re absolutely correct, and there are indeed other use cases.

What sort of other use cases are you thinking of?

Additionally, it proves valuable for early data.

Can you expand on that? I'm not sure I see the connection.

@quininer
Copy link
Member

quininer commented Jun 5, 2024

You don't really need it, you can access the internals using .get_mut after .connect_with. even for your case, using block_on is not the right way.

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

Successfully merging this pull request may close these issues.

3 participants