implement new auth method for server
This commit is contained in:
parent
2c1f8e1a64
commit
8c4171ba14
@ -13,10 +13,11 @@ register-count = { version = "0.1.0", default-features = false, features = ["std
|
||||
rustls = { version = "0.20.8", default-features = false, features = ["quic"] }
|
||||
rustls-pemfile = { version = "1.0.2", default-features = false }
|
||||
serde = { version = "1.0.152", default-features = false, features = ["derive", "std"] }
|
||||
serde_json = { version = "1.0.91", default-features = false, features = ["std"] }
|
||||
serde_json = { version = "1.0.92", default-features = false, features = ["std"] }
|
||||
socket2 = { version = "0.4.7", default-features = false }
|
||||
thiserror = { version = "1.0.38", default-features = false }
|
||||
tokio = { version = "1.25.0", default-features = false, features = ["macros", "net", "parking_lot", "rt-multi-thread", "time"] }
|
||||
tokio-util = { version = "0.7.4", default-features = false, features = ["compat"] }
|
||||
tuic = { path = "../tuic", default-features = false }
|
||||
tuic-quinn = { path = "../tuic-quinn", default-features = false }
|
||||
tuic = { version = "5.0.0-pre-alpha6", default-features = false }
|
||||
tuic-quinn = { version = "0.1.0-pre-alpha2", default-features = false }
|
||||
uuid = { version = "1.3.0", default-features = false, features = ["serde", "std"] }
|
||||
|
@ -3,10 +3,11 @@ use lexopt::{Arg, Error as ArgumentError, Parser};
|
||||
use serde::{de::Error as DeError, Deserialize, Deserializer};
|
||||
use serde_json::Error as SerdeError;
|
||||
use std::{
|
||||
env::ArgsOs, fmt::Display, fs::File, io::Error as IoError, net::SocketAddr, path::PathBuf,
|
||||
str::FromStr, time::Duration,
|
||||
collections::HashMap, env::ArgsOs, fmt::Display, fs::File, io::Error as IoError,
|
||||
net::SocketAddr, path::PathBuf, str::FromStr, time::Duration,
|
||||
};
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
const HELP_MSG: &str = r#"
|
||||
Usage tuic-server [arguments]
|
||||
@ -21,7 +22,8 @@ Arguments:
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
pub server: SocketAddr,
|
||||
pub token: String,
|
||||
#[serde(deserialize_with = "deserialize_users")]
|
||||
pub users: HashMap<Uuid, String>,
|
||||
pub certificate: PathBuf,
|
||||
pub private_key: PathBuf,
|
||||
#[serde(
|
||||
@ -130,6 +132,19 @@ where
|
||||
T::from_str(&s).map_err(DeError::custom)
|
||||
}
|
||||
|
||||
pub fn deserialize_users<'de, D>(deserializer: D) -> Result<HashMap<Uuid, String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let map = HashMap::<Uuid, String>::deserialize(deserializer)?;
|
||||
|
||||
if map.is_empty() {
|
||||
return Err(DeError::custom("users cannot be empty"));
|
||||
}
|
||||
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ConfigError {
|
||||
#[error(transparent)]
|
||||
|
@ -8,6 +8,7 @@ use std::{env, io::Error as IoError, net::SocketAddr, process};
|
||||
use thiserror::Error;
|
||||
use tuic::Address;
|
||||
use tuic_quinn::Error as ModelError;
|
||||
use uuid::Uuid;
|
||||
|
||||
mod config;
|
||||
mod server;
|
||||
@ -52,8 +53,8 @@ pub enum Error {
|
||||
DuplicatedAuth,
|
||||
#[error("token length too short")]
|
||||
ExportKeyingMaterial,
|
||||
#[error("authentication failed")]
|
||||
AuthFailed,
|
||||
#[error("authentication failed: {0}")]
|
||||
AuthFailed(Uuid),
|
||||
#[error("received packet from unexpected source")]
|
||||
UnexpectedPacketSource,
|
||||
#[error("{0} resolved to {1} but IPv6 UDP relay disabled")]
|
||||
|
@ -39,12 +39,13 @@ use tokio::{
|
||||
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
||||
use tuic::Address;
|
||||
use tuic_quinn::{side, Connect, Connection as Model, Packet, Task};
|
||||
use uuid::Uuid;
|
||||
|
||||
const DEFAULT_CONCURRENT_STREAMS: usize = 32;
|
||||
|
||||
pub struct Server {
|
||||
ep: Endpoint,
|
||||
token: Arc<[u8]>,
|
||||
users: Arc<HashMap<Uuid, Vec<u8>>>,
|
||||
udp_relay_ipv6: bool,
|
||||
zero_rtt_handshake: bool,
|
||||
auth_timeout: Duration,
|
||||
@ -115,9 +116,15 @@ impl Server {
|
||||
TokioRuntime,
|
||||
)?;
|
||||
|
||||
let users = cfg
|
||||
.users
|
||||
.into_iter()
|
||||
.map(|(uuid, password)| (uuid, password.into_bytes()))
|
||||
.collect();
|
||||
|
||||
Ok(Self {
|
||||
ep,
|
||||
token: Arc::from(cfg.token.into_bytes().into_boxed_slice()),
|
||||
users: Arc::new(users),
|
||||
udp_relay_ipv6: cfg.udp_relay_ipv6,
|
||||
zero_rtt_handshake: cfg.zero_rtt_handshake,
|
||||
auth_timeout: cfg.auth_timeout,
|
||||
@ -133,7 +140,7 @@ impl Server {
|
||||
|
||||
tokio::spawn(Connection::handle(
|
||||
conn,
|
||||
self.token.clone(),
|
||||
self.users.clone(),
|
||||
self.udp_relay_ipv6,
|
||||
self.zero_rtt_handshake,
|
||||
self.auth_timeout,
|
||||
@ -149,7 +156,7 @@ impl Server {
|
||||
struct Connection {
|
||||
inner: QuinnConnection,
|
||||
model: Model<side::Server>,
|
||||
token: Arc<[u8]>,
|
||||
users: Arc<HashMap<Uuid, Vec<u8>>>,
|
||||
udp_relay_ipv6: bool,
|
||||
is_authed: IsAuthed,
|
||||
udp_sessions: Arc<AsyncMutex<HashMap<u16, UdpSession>>>,
|
||||
@ -165,7 +172,7 @@ struct Connection {
|
||||
impl Connection {
|
||||
async fn handle(
|
||||
conn: Connecting,
|
||||
token: Arc<[u8]>,
|
||||
users: Arc<HashMap<Uuid, Vec<u8>>>,
|
||||
udp_relay_ipv6: bool,
|
||||
zero_rtt_handshake: bool,
|
||||
auth_timeout: Duration,
|
||||
@ -175,7 +182,7 @@ impl Connection {
|
||||
) {
|
||||
match Self::init(
|
||||
conn,
|
||||
token,
|
||||
users,
|
||||
udp_relay_ipv6,
|
||||
zero_rtt_handshake,
|
||||
max_external_pkt_size,
|
||||
@ -203,7 +210,7 @@ impl Connection {
|
||||
|
||||
async fn init(
|
||||
conn: Connecting,
|
||||
token: Arc<[u8]>,
|
||||
users: Arc<HashMap<Uuid, Vec<u8>>>,
|
||||
udp_relay_ipv6: bool,
|
||||
zero_rtt_handshake: bool,
|
||||
max_external_pkt_size: usize,
|
||||
@ -223,7 +230,7 @@ impl Connection {
|
||||
Ok(Self {
|
||||
inner: conn.clone(),
|
||||
model: Model::<side::Server>::new(conn),
|
||||
token,
|
||||
users,
|
||||
udp_relay_ipv6,
|
||||
is_authed: IsAuthed::new(),
|
||||
udp_sessions: Arc::new(AsyncMutex::new(HashMap::new())),
|
||||
@ -263,21 +270,17 @@ impl Connection {
|
||||
async fn pre_process(conn: &Connection, recv: RecvStream) -> Result<Task, Error> {
|
||||
let task = conn.model.accept_uni_stream(recv).await?;
|
||||
|
||||
if let Task::Authenticate(token) = &task {
|
||||
if let Task::Authenticate(auth) = &task {
|
||||
if conn.is_authed() {
|
||||
return Err(Error::DuplicatedAuth);
|
||||
} else {
|
||||
let mut buf = [0; 32];
|
||||
|
||||
conn.inner
|
||||
.export_keying_material(&mut buf, &conn.token, &conn.token)
|
||||
.map_err(|_| Error::ExportKeyingMaterial)?;
|
||||
|
||||
if token == &buf {
|
||||
} else if conn
|
||||
.users
|
||||
.get(&auth.uuid())
|
||||
.map_or(false, |password| auth.validate(password))
|
||||
{
|
||||
conn.set_authed();
|
||||
} else {
|
||||
return Err(Error::AuthFailed);
|
||||
}
|
||||
return Err(Error::AuthFailed(auth.uuid()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,6 +299,7 @@ impl Connection {
|
||||
}
|
||||
|
||||
match pre_process(&self, recv).await {
|
||||
Ok(Task::Authenticate(_)) => {}
|
||||
Ok(Task::Packet(pkt)) => {
|
||||
self.set_udp_relay_mode(UdpRelayMode::Quic);
|
||||
match self.handle_packet(pkt).await {
|
||||
|
Loading…
x
Reference in New Issue
Block a user