-
Notifications
You must be signed in to change notification settings - Fork 487
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
QUIC support #98
base: main
Are you sure you want to change the base?
QUIC support #98
Conversation
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial and simple feedback. Also please check the output of CI Lints
Cargo.toml
Outdated
quinn = { version = "0.8.0", optional = true} | ||
rustls = { version = "0.20", default-features = false, features = ["quic"], optional = true } | ||
rustls-pemfile = { version = "0.2.1", optional = true } | ||
openssl = { version = "0.10.38", optional = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the only usage of openssl
is openssl::pkcs12::Pkcs12
, which is a large library and requires effort to make it compile on multiple platforms. Since we're already using rustls, it will be better to manage to get rid of openssl
. There are some pkcs12 crates on crates.io, if we insist pkcs12 for QUIC. But I wonder what method does QUIC natively provide to work with certificates and so on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm absolutely not a fan of pkcs. I just wanted to stick with the existing pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking into native-tls
I notice that they also use openssl
for parsing p12. So I don't see the benefit of using a different crate when the method I'm using is already being compiled in via native-tls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it matters when you compile with feature quic
and without tls
:)
openssl
is really a pain to compile. Dropping it will possibly make the feature combination server,client,quic
available on more platforms than server,client,tls
.
openssl
already causes trouble for cross compiling rathole
and I have to degrade cross
to work around. Someone requests for a official risc-v release but I can't do it simply because of the cross compiling stuff about openssl
.
tls
chooses to use openssl
only because it supports IP as hostname and that's many people want. I wish to shift all tls dependencies to rustls
at certain point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I just tried out the only really promising crate that does not end up relying on openssl
: https://github.com/hjiayz/p12
Unfortunately it choked on the p12 file I created myself. As I said, I am absolutely not a fan of PKCS12 - precisely because you never known quite which libraries, are compatible with with PKCS12 formats. Unless of course you choose a huge lib like openssl
that has almost everything covered. (See rustls/rustls#150 where they decline to add support n rusttls)
I don't really want to pull in a half baked pkcs12 parser that only works for some users.
I would suggest the following in a separate PR:
- implement reading certs and keys from PEM files directly, as an alternative to supplying pfx file.
- create a new "pfx" feature that pulls in
openssl
for users who want it and enables support for pfx in QUIC transport.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, i think native-tls
depends on openssl
when compiled on Linux platform. When compiled on Mac or Windows, I think it uses platform specific deps instead.
The way I have setup cargo.toml
forces openssl
to be compiled regardless of platform.
I would need to figure out how to do this per platform scoping to fix the builds.
I may have to, at least temporarily, restrict usage of pfx in quic to Linux only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I'm open to the change of specifying the certificate in other ways, if pkcs12 is troublesome to work with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pkcs is often very troublesome. Usually the problem stems from jks keystores that pretend to be p12 stores, yet not entirely compatible.
Also a problem the other way around, when a Java app expects a jks but is provided with an openssl p12.
I will implement reading from pem files.
Can we scope quic-pfx to be available on Linux only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will implement reading from pem files.
Can we scope quic-pfx to be available on Linux only?
If we have an alternative way to use the certificate, I think we can drop pfx entirely in this PR, as you previously suggested
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
native-tls
unfortunately will not support PEM files only.
Only certs can be loaded from PEM files, the keys must still come from pfx.
Seems safe to me 🤔 |
No, |
There are two files, |
Ahh, yeah that file. that was not supposed to be committed. I will delete |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great. Some nitpicking
} | ||
|
||
async fn connect(&self, addr: &str) -> Result<Self::Stream> { | ||
let mut endpoint = quinn::Endpoint::client("[::]:0".parse().unwrap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised that this works for connecting to IPv4 address since it's binding to a V6 address. Some dual stack magic inside?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thibnk there's quite a bit of magic in quinn
. I have not looked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, we can see how the test going on different platforms after you have lint fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the tests failed.
See below for how to handle the address stuff. You can refactor out a function called get_bind_addr_for_udp
or so and call it
Lines 43 to 58 in 1fe3509
/// Create a UDP socket and connect to `addr` | |
pub async fn udp_connect<A: ToSocketAddrs>(addr: A) -> Result<UdpSocket> { | |
let addr = lookup_host(addr) | |
.await? | |
.next() | |
.ok_or(anyhow!("Failed to lookup the host"))?; | |
let bind_addr = match addr { | |
SocketAddr::V4(_) => "0.0.0.0:0", | |
SocketAddr::V6(_) => ":::0", | |
}; | |
let s = UdpSocket::bind(bind_addr).await?; | |
s.connect(addr).await?; | |
Ok(s) | |
} |
Squashed the branch since rebasing was getting unwieldy with so many small commits and reverts |
I see tests failing. Can only test linux locally, and that passes on my desktop... Dunno why the tests are failing |
shows that the client tried to connect to the server, but by the end of the test, it had not succeeded nor returned any feedback. This is possibly caused by a IPv6 bounded socket connecting to a IPv4 address. I think this reveals two potential issues to address:
|
Hi @emillynge What's the status of this? I think we are really close to get this merged. |
I'm on vacation now, and then next week my parental leave is over and I'll have to go to work. I will try to wrap this up in the coming month, but my time is very limited now unfortunately. |
Hey @emillynge may I ask nicely what the situation is with this PR? 👀 |
@emillynge if you don't mind, I can pick up this and finish this PR. |
@cssivision Can I transfer/share ownership of PR and branch somehow? |
@cssivision can fork your repository with the PR branch and open a new one at least. But i think you can also add him as a member to your forked rathole repository so he can push changed. Correct me if i'am wrong |
What is the future of this pull request? @rapiz1 The reason I'm asking this is that I'm thinking about implementing a new feature of QUIC as a transport type for rathole should I submit a whole new pull request? |
a6601fd
to
33b31dd
Compare
78f1157
to
97541af
Compare
Since @juzi5201314 indicated that he would close #64 I now bring this PR.
Many thanks to juzi for his PR, looking at your approach and reading the comments in the PR was very helpful!
This PR is aware of #93 and an effort has been made to ensure
QuicTransport::accept
is cancel safe. But honestly, it is very difficult to determine if that is in fact the case.This PR is standalone and does not immediately require merging of #95 which is much more experimental.
Just to kickstart the review, I want to address some comments in #64
rust_tls vs native_tls
I may be possible to drop in a
native_tls
version ofquinn-proto::crypto
, but that is a lot of work, that I don't think I can put in, for this particular feature. Also, I might have to rewrite certain other parts of quinn as well that seems to, only be available when using therust_tls
feature of thequinn
crate.If the compilation time / executable size is a problem, then I would propose making QUIC a non-default feature.
Releasing UDP sockets in tests
I have spent a long time trying to get the tests working without using a pre-determined sleep between shutdown and restart of the server. This is what I came up with:
rathole::run
does not exit before the currently running server instance coroutine has joinedasync fn close(a: Self::Acceptor)
method to theTransport
trait such that graceful termination of the QUIC connections can be awaitedclose
inServer::run
to ensure that socket is released before coroutine joinsI hope that the above solution is acceptable. The only other option is to rebind to a new random UDP port from a
drop
on theAcceptor
.