mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-08-05 20:19:45 +00:00
fix: remove quinn-plaintext (#2345)
Remove quinn-plaintext to fix connection errors caused by different hash values across platforms. On x64, maintain compatibility with quinn-plaintext.
This commit is contained in:
Generated
+2
-13
@@ -2318,7 +2318,7 @@ dependencies = [
|
|||||||
"prost-reflect-build",
|
"prost-reflect-build",
|
||||||
"prost-wkt-types",
|
"prost-wkt-types",
|
||||||
"quinn",
|
"quinn",
|
||||||
"quinn-plaintext",
|
"quinn-proto",
|
||||||
"quote",
|
"quote",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
@@ -2330,6 +2330,7 @@ dependencies = [
|
|||||||
"rstest",
|
"rstest",
|
||||||
"rust-i18n",
|
"rust-i18n",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
"seahash",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
@@ -7022,18 +7023,6 @@ dependencies = [
|
|||||||
"web-time",
|
"web-time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quinn-plaintext"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f3e617feaeb6493018fa35fc47ae8b630ac8903d8159e9e747018841b99bad3d"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"quinn-proto",
|
|
||||||
"seahash",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn-proto"
|
name = "quinn-proto"
|
||||||
version = "0.11.12"
|
version = "0.11.12"
|
||||||
|
|||||||
+3
-2
@@ -82,7 +82,8 @@ pin-project-lite = "0.2.13"
|
|||||||
atomic_refcell = "0.1.13"
|
atomic_refcell = "0.1.13"
|
||||||
|
|
||||||
quinn = { version = "0.11.8", optional = true, features = ["ring"] }
|
quinn = { version = "0.11.8", optional = true, features = ["ring"] }
|
||||||
quinn-plaintext = { version = "0.3.0", optional = true }
|
quinn-proto = { version = "0.11.12", optional = true }
|
||||||
|
seahash = { version = "4.1.0", optional = true }
|
||||||
|
|
||||||
rustls = { version = "0.23.0", features = [
|
rustls = { version = "0.23.0", features = [
|
||||||
"ring", "tls12"
|
"ring", "tls12"
|
||||||
@@ -373,7 +374,7 @@ full = [
|
|||||||
"zstd",
|
"zstd",
|
||||||
]
|
]
|
||||||
wireguard = ["dep:boringtun", "dep:ring"]
|
wireguard = ["dep:boringtun", "dep:ring"]
|
||||||
quic = ["dep:quinn", "dep:quinn-plaintext", "dep:rustls", "dep:rcgen"]
|
quic = ["dep:quinn", "dep:quinn-proto", "dep:seahash", "dep:rustls", "dep:rcgen"]
|
||||||
kcp = ["dep:kcp-sys"]
|
kcp = ["dep:kcp-sys"]
|
||||||
mimalloc = ["dep:mimalloc"]
|
mimalloc = ["dep:mimalloc"]
|
||||||
aes-gcm = ["dep:aes-gcm"]
|
aes-gcm = ["dep:aes-gcm"]
|
||||||
|
|||||||
+246
-2
@@ -23,6 +23,250 @@ use std::{net::SocketAddr, sync::Arc, time::Duration};
|
|||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
// region config
|
// region config
|
||||||
|
mod crypto {
|
||||||
|
use crate::utils::BoxExt;
|
||||||
|
use bytes::{Buf, BytesMut};
|
||||||
|
use quinn_proto::crypto::{
|
||||||
|
ClientConfig, ExportKeyingMaterialError, KeyPair, Keys, ServerConfig, Session,
|
||||||
|
UnsupportedVersion,
|
||||||
|
};
|
||||||
|
use quinn_proto::transport_parameters::TransportParameters;
|
||||||
|
use quinn_proto::{
|
||||||
|
ConnectError, ConnectionId, Side, TransportError,
|
||||||
|
crypto::{CryptoError, HeaderKey, PacketKey},
|
||||||
|
};
|
||||||
|
use seahash::SeaHasher;
|
||||||
|
use std::any::Any;
|
||||||
|
use std::{hash::Hasher, sync::Arc};
|
||||||
|
use tracing::{error, instrument, trace};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct CryptoKey;
|
||||||
|
|
||||||
|
impl CryptoKey {
|
||||||
|
fn header(self) -> KeyPair<Box<dyn HeaderKey>> {
|
||||||
|
KeyPair {
|
||||||
|
local: Box::new(self),
|
||||||
|
remote: Box::new(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn packet(self) -> KeyPair<Box<dyn PacketKey>> {
|
||||||
|
KeyPair {
|
||||||
|
local: Box::new(self),
|
||||||
|
remote: Box::new(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keys(self) -> Keys {
|
||||||
|
Keys {
|
||||||
|
header: self.header(),
|
||||||
|
packet: self.packet(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeaderKey for CryptoKey {
|
||||||
|
fn decrypt(&self, _: usize, _: &mut [u8]) {}
|
||||||
|
fn encrypt(&self, _: usize, _: &mut [u8]) {}
|
||||||
|
fn sample_size(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CryptoKey {
|
||||||
|
fn checksum(slices: &[&[u8]]) -> u64 {
|
||||||
|
let mut hasher = SeaHasher::default();
|
||||||
|
for slice in slices {
|
||||||
|
hasher.write(&(slice.len() as u64).to_le_bytes());
|
||||||
|
hasher.write(slice);
|
||||||
|
}
|
||||||
|
hasher.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketKey for CryptoKey {
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn encrypt(&self, packet: u64, buf: &mut [u8], header_len: usize) {
|
||||||
|
let (header, rest) = buf.split_at_mut(header_len);
|
||||||
|
let (payload, tag) = rest.split_at_mut(rest.len() - self.tag_len());
|
||||||
|
let checksum = Self::checksum(&[header, payload]);
|
||||||
|
tag.copy_from_slice(&checksum.to_be_bytes());
|
||||||
|
trace!(checksum, ?header, ?payload, ?tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn decrypt(
|
||||||
|
&self,
|
||||||
|
packet: u64,
|
||||||
|
header: &[u8],
|
||||||
|
payload: &mut BytesMut,
|
||||||
|
) -> Result<(), CryptoError> {
|
||||||
|
let tag = payload.split_off(payload.len() - self.tag_len()).get_u64();
|
||||||
|
trace!(tag, ?payload);
|
||||||
|
let checksum = Self::checksum(&[header, payload]);
|
||||||
|
if checksum != tag {
|
||||||
|
error!(tag, checksum, "checksum mismatch");
|
||||||
|
return Err(CryptoError);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tag_len(&self) -> usize {
|
||||||
|
8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn confidentiality_limit(&self) -> u64 {
|
||||||
|
u64::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
fn integrity_limit(&self) -> u64 {
|
||||||
|
1 << 36
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum HandshakeState {
|
||||||
|
EmitInitial,
|
||||||
|
EmitHandshake,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct QuicSession {
|
||||||
|
side: Side,
|
||||||
|
state: HandshakeState,
|
||||||
|
local: TransportParameters,
|
||||||
|
remote: Option<TransportParameters>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QuicSession {
|
||||||
|
fn new(side: Side, params: TransportParameters) -> Self {
|
||||||
|
Self {
|
||||||
|
side,
|
||||||
|
state: HandshakeState::EmitInitial,
|
||||||
|
local: params,
|
||||||
|
remote: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Session for QuicSession {
|
||||||
|
fn initial_keys(&self, _: &ConnectionId, _: Side) -> Keys {
|
||||||
|
CryptoKey.keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handshake_data(&self) -> Option<Box<dyn Any>> {
|
||||||
|
self.remote.map(|params| params.boxed() as _)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peer_identity(&self) -> Option<Box<dyn Any>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn early_crypto(&self) -> Option<(Box<dyn HeaderKey>, Box<dyn PacketKey>)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn early_data_accepted(&self) -> Option<bool> {
|
||||||
|
Some(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn is_handshaking(&self) -> bool {
|
||||||
|
self.remote.is_none() || self.state != HandshakeState::Done
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn read_handshake(&mut self, mut buf: &[u8]) -> Result<bool, TransportError> {
|
||||||
|
if self.remote.is_none() {
|
||||||
|
self.remote = Some(
|
||||||
|
TransportParameters::read(self.side, &mut buf)
|
||||||
|
.expect("failed to read transport parameters"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn transport_parameters(&self) -> Result<Option<TransportParameters>, TransportError> {
|
||||||
|
Ok(self.remote)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn write_handshake(&mut self, buf: &mut Vec<u8>) -> Option<Keys> {
|
||||||
|
match self.state {
|
||||||
|
HandshakeState::EmitInitial => {
|
||||||
|
if self.side.is_client() {
|
||||||
|
self.local.write(buf);
|
||||||
|
}
|
||||||
|
self.state = HandshakeState::EmitHandshake;
|
||||||
|
Some(CryptoKey.keys())
|
||||||
|
}
|
||||||
|
HandshakeState::EmitHandshake => {
|
||||||
|
if self.side.is_server() {
|
||||||
|
self.local.write(buf);
|
||||||
|
}
|
||||||
|
self.state = HandshakeState::Done;
|
||||||
|
Some(CryptoKey.keys())
|
||||||
|
}
|
||||||
|
HandshakeState::Done => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_1rtt_keys(&mut self) -> Option<KeyPair<Box<dyn PacketKey>>> {
|
||||||
|
Some(CryptoKey.packet())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_retry(&self, _: &ConnectionId, _: &[u8], _: &[u8]) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn export_keying_material(
|
||||||
|
&self,
|
||||||
|
_: &mut [u8],
|
||||||
|
_: &[u8],
|
||||||
|
_: &[u8],
|
||||||
|
) -> Result<(), ExportKeyingMaterialError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CryptoConfig;
|
||||||
|
|
||||||
|
impl ClientConfig for CryptoConfig {
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn start_session(
|
||||||
|
self: Arc<Self>,
|
||||||
|
version: u32,
|
||||||
|
server_name: &str,
|
||||||
|
params: &TransportParameters,
|
||||||
|
) -> Result<Box<dyn Session>, ConnectError> {
|
||||||
|
Ok(Box::new(QuicSession::new(Side::Client, *params)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerConfig for CryptoConfig {
|
||||||
|
fn initial_keys(&self, _: u32, _: &ConnectionId) -> Result<Keys, UnsupportedVersion> {
|
||||||
|
Ok(CryptoKey.keys())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn retry_tag(&self, _: u32, _: &ConnectionId, _: &[u8]) -> [u8; 16] {
|
||||||
|
[0u8; 16]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn start_session(
|
||||||
|
self: Arc<Self>,
|
||||||
|
version: u32,
|
||||||
|
params: &TransportParameters,
|
||||||
|
) -> Box<dyn Session> {
|
||||||
|
Box::new(QuicSession::new(Side::Server, *params))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn transport_config() -> Arc<TransportConfig> {
|
pub fn transport_config() -> Arc<TransportConfig> {
|
||||||
let mut config = TransportConfig::default();
|
let mut config = TransportConfig::default();
|
||||||
|
|
||||||
@@ -39,13 +283,13 @@ pub fn transport_config() -> Arc<TransportConfig> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn server_config() -> ServerConfig {
|
pub fn server_config() -> ServerConfig {
|
||||||
let mut config = quinn_plaintext::server_config();
|
let mut config = ServerConfig::with_crypto(Arc::new(crypto::CryptoConfig));
|
||||||
config.transport_config(transport_config());
|
config.transport_config(transport_config());
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_config() -> ClientConfig {
|
pub fn client_config() -> ClientConfig {
|
||||||
let mut config = quinn_plaintext::client_config();
|
let mut config = ClientConfig::new(Arc::new(crypto::CryptoConfig));
|
||||||
config.transport_config(transport_config());
|
config.transport_config(transport_config());
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user