Skip to content

Commit

Permalink
up
Browse files Browse the repository at this point in the history
  • Loading branch information
ibigbug committed Dec 26, 2023
1 parent e395c17 commit 8821b8c
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 54 deletions.
23 changes: 18 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions clash_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ hickory-server = { version = "0.24", features = ["dns-over-rustls", "dns-over-ht
hickory-proto = { version = "0.24", features = ["dns-over-rustls", "dns-over-https-rustls"]}

# DoH
rustls = { version = "0.21", features=["dangerous_configuration"] }
rustls-pemfile = "1.0.4"
webpki-roots = "0.25"
rustls = { version = "0.22" }
rustls-pemfile = "2"
webpki-roots = "0.26"
dhcproto = "0.11"

rand = "0.8"
Expand Down
40 changes: 21 additions & 19 deletions clash_lib/src/app/dns/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use std::{

use ipnet::AddrParseError;
use regex::Regex;
use rustls::{Certificate, PrivateKey};

use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use url::Url;

use crate::{
Expand Down Expand Up @@ -50,13 +51,13 @@ pub struct FallbackFilter {

#[derive(Clone, Debug)]
pub struct DoHConfig {
pub certificate_and_key: (Vec<Certificate>, PrivateKey),
pub certificate_and_key: Arc<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>,
pub dns_hostname: Option<String>,
}

#[derive(Clone, Debug)]
pub struct DoTConfig {
pub certificate_and_key: (Vec<Certificate>, PrivateKey),
pub certificate_and_key: Arc<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>,
}

#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -279,37 +280,38 @@ impl TryFrom<&crate::config::def::Config> for Config {
"doh" => {
let mut buf_read: Box<dyn std::io::BufRead> =
Box::new(BufReader::new(TEST_CERT.as_bytes()));
let certs = rustls_pemfile::certs(&mut buf_read)
.unwrap()
.into_iter()
.map(Certificate)
.collect::<Vec<_>>();
let certs: Result<Vec<_>, _> =
rustls_pemfile::certs(&mut buf_read).collect();

let mut buf_read: Box<dyn std::io::BufRead> =
Box::new(BufReader::new(TEST_KEY.as_bytes()));
let mut keys =
rustls_pemfile::pkcs8_private_keys(&mut buf_read).unwrap();
let mut keys: Result<Vec<_>, _> =
rustls_pemfile::pkcs8_private_keys(&mut buf_read).collect();

let c = DoHConfig {
certificate_and_key: (certs, PrivateKey(keys.remove(0))),
certificate_and_key: Arc::new((
certs.unwrap(),
keys.unwrap().remove(0).into(),
)),
dns_hostname: Some("dns.example.com".to_owned()),
};
doh = Some((addr, c))
}
"dot" => {
let mut buf_read: Box<dyn std::io::BufRead> =
Box::new(BufReader::new(TEST_CERT.as_bytes()));
let certs = rustls_pemfile::certs(&mut buf_read)
.unwrap()
.into_iter()
.map(Certificate)
.collect::<Vec<_>>();
let certs: Result<Vec<_>, _> =
rustls_pemfile::certs(&mut buf_read).collect();

let mut buf_read: Box<dyn std::io::BufRead> =
Box::new(BufReader::new(TEST_KEY.as_bytes()));
let mut keys =
rustls_pemfile::pkcs8_private_keys(&mut buf_read).unwrap();
let mut keys: Result<Vec<_>, _> =
rustls_pemfile::pkcs8_private_keys(&mut buf_read).collect();
let c = DoTConfig {
certificate_and_key: (certs, PrivateKey(keys.remove(0))),
certificate_and_key: Arc::new((
certs.unwrap(),
keys.unwrap().remove(0).into(),
)),
};
dot = Some((addr, c))
}
Expand Down
1 change: 0 additions & 1 deletion clash_lib/src/app/dns/dns_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ async fn dns_stream_builder(
}
DnsConfig::Tls(addr, host, iface) => {
let mut tls_config = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(GLOBAL_ROOT_STORE.clone())
.with_no_client_auth();
tls_config.alpn_protocols = vec!["dot".into()];
Expand Down
95 changes: 69 additions & 26 deletions clash_lib/src/common/tls.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,84 @@
use once_cell::sync::Lazy;

use rustls::{
client::{ServerCertVerified, ServerCertVerifier, WebPkiVerifier},
OwnedTrustAnchor, RootCertStore,
client::{
danger::{ServerCertVerified, ServerCertVerifier},
WebPkiServerVerifier,
},
RootCertStore,
};
use tracing::warn;

use rustls::{Certificate, ServerName};
use std::{sync::Arc, time::SystemTime};
use std::sync::Arc;

pub static GLOBAL_ROOT_STORE: Lazy<Arc<RootCertStore>> = Lazy::new(global_root_store);

fn global_root_store() -> Arc<RootCertStore> {
let mut root_store = RootCertStore::empty();
root_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| {
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}));
let root_store = RootCertStore {
roots: webpki_roots::TLS_SERVER_ROOTS.into(),
};

Arc::new(root_store)
}

/// Warning: NO validation on certs.
#[derive(Debug)]
pub struct DummyTlsVerifier;

impl ServerCertVerifier for DummyTlsVerifier {
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
unimplemented!()
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
unimplemented!()
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
unimplemented!()
}

fn verify_server_cert(
&self,
_end_entity: &Certificate,
_intermediates: &[Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: SystemTime,
) -> Result<ServerCertVerified, rustls::Error> {
end_entity: &rustls::pki_types::CertificateDer<'_>,
intermediates: &[rustls::pki_types::CertificateDer<'_>],
server_name: &rustls::pki_types::ServerName<'_>,
ocsp_response: &[u8],
now: rustls::pki_types::UnixTime,
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
Ok(ServerCertVerified::assertion())
}
}

#[derive(Debug)]
pub struct NoHostnameTlsVerifier;

impl ServerCertVerifier for NoHostnameTlsVerifier {
fn verify_server_cert(
&self,
end_entity: &Certificate,
intermediates: &[Certificate],
server_name: &ServerName,
scts: &mut dyn Iterator<Item = &[u8]>,
end_entity: &rustls::pki_types::CertificateDer<'_>,
intermediates: &[rustls::pki_types::CertificateDer<'_>],
server_name: &rustls::pki_types::ServerName<'_>,
ocsp_response: &[u8],
now: SystemTime,
now: rustls::pki_types::UnixTime,
) -> Result<ServerCertVerified, rustls::Error> {
let verifier = WebPkiVerifier::new(rustls::RootCertStore { roots: vec![] }, None);
let verifier = WebPkiServerVerifier::builder(global_root_store())
.build()
.unwrap();
match verifier.verify_server_cert(
end_entity,
intermediates,
server_name,
scts,
ocsp_response,
now,
) {
Expand All @@ -71,4 +92,26 @@ impl ServerCertVerifier for NoHostnameTlsVerifier {
other => other,
}
}

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
unimplemented!()
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &rustls::pki_types::CertificateDer<'_>,
dss: &rustls::DigitallySignedStruct,
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
unimplemented!()
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
unimplemented!()
}
}

0 comments on commit 8821b8c

Please sign in to comment.