outbound/tls: added an option to disable certificate verification

This commit is contained in:
eric
2023-03-30 07:14:00 +08:00
parent 442d684978
commit 1de877aeae
9 changed files with 64 additions and 7 deletions

View File

@@ -172,7 +172,7 @@ chrono = "0.4"
colored = "2.0"
# TLS/rustls/QUIC
tokio-rustls = { version = "0.23", optional = true }
tokio-rustls = { version = "0.23", features = ["dangerous_configuration"], optional = true }
webpki-roots = { version = "0.22", optional = true }
rustls-pemfile = { version = "1.0.2", optional = true }

View File

@@ -267,6 +267,7 @@ impl OutboundManager {
settings.server_name.clone(),
settings.alpn.clone(),
certificate,
settings.insecure,
)?);
HandlerBuilder::default()
.tag(tag.clone())

View File

@@ -1,5 +1,5 @@
// This file is generated by rust-protobuf 3.2.0. Do not edit
// .proto file is parsed by protoc 22.2
// .proto file is parsed by protoc 3.21.12
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702

View File

@@ -63,6 +63,7 @@ pub struct Proxy {
pub ws: Option<bool>,
pub tls: Option<bool>,
pub tls_cert: Option<String>,
pub tls_insecure: Option<bool>,
pub ws_path: Option<String>,
pub ws_host: Option<String>,
@@ -95,6 +96,7 @@ impl Default for Proxy {
ws: Some(false),
tls: Some(false),
tls_cert: None,
tls_insecure: Some(false),
ws_path: None,
ws_host: None,
sni: None,
@@ -391,6 +393,9 @@ pub fn from_lines(lines: Vec<io::Result<String>>) -> Result<Config> {
"tls-cert" => {
proxy.tls_cert = Some(v.to_string());
}
"tls-insecure" => {
proxy.tls_insecure = if v == "true" { Some(true) } else { Some(false) }
}
"ws-path" => {
proxy.ws_path = Some(v.to_string());
}
@@ -923,6 +928,7 @@ pub fn to_internal(conf: &mut Config) -> Result<internal::Config> {
tls_settings.certificate = path;
}
}
tls_settings.insecure = ext_proxy.tls_insecure.unwrap_or_default();
let tls_settings = tls_settings.write_to_bytes().unwrap();
tls_outbound.settings = tls_settings;
tls_outbound.tag = format!("{}_tls_xxx", ext_proxy.tag.clone());
@@ -1068,6 +1074,7 @@ pub fn to_internal(conf: &mut Config) -> Result<internal::Config> {
tls_settings.certificate = path;
}
}
tls_settings.insecure = ext_proxy.tls_insecure.unwrap_or_default();
let tls_settings = tls_settings.write_to_bytes().unwrap();
tls_outbound.settings = tls_settings;
tls_outbound.tag = format!("{}_tls_xxx", ext_proxy.tag.clone());

View File

@@ -1,5 +1,5 @@
// This file is generated by rust-protobuf 3.2.0. Do not edit
// .proto file is parsed by protoc 22.2
// .proto file is parsed by protoc 3.21.12
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702

View File

@@ -123,6 +123,7 @@ message TlsOutboundSettings {
string server_name = 1;
repeated string alpn = 2;
string certificate = 3;
bool insecure = 4;
}
message WebSocketOutboundSettings {

View File

@@ -1,5 +1,5 @@
// This file is generated by rust-protobuf 3.2.0. Do not edit
// .proto file is parsed by protoc 22.2
// .proto file is parsed by protoc 3.21.12
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
@@ -2183,6 +2183,8 @@ pub struct TlsOutboundSettings {
pub alpn: ::std::vec::Vec<::std::string::String>,
// @@protoc_insertion_point(field:TlsOutboundSettings.certificate)
pub certificate: ::std::string::String,
// @@protoc_insertion_point(field:TlsOutboundSettings.insecure)
pub insecure: bool,
// special fields
// @@protoc_insertion_point(special_field:TlsOutboundSettings.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@@ -2219,6 +2221,9 @@ impl ::protobuf::Message for TlsOutboundSettings {
26 => {
self.certificate = is.read_string()?;
},
32 => {
self.insecure = is.read_bool()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@@ -2240,6 +2245,9 @@ impl ::protobuf::Message for TlsOutboundSettings {
if !self.certificate.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.certificate);
}
if self.insecure != false {
my_size += 1 + 1;
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@@ -2255,6 +2263,9 @@ impl ::protobuf::Message for TlsOutboundSettings {
if !self.certificate.is_empty() {
os.write_string(3, &self.certificate)?;
}
if self.insecure != false {
os.write_bool(4, self.insecure)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@@ -2275,6 +2286,7 @@ impl ::protobuf::Message for TlsOutboundSettings {
self.server_name.clear();
self.alpn.clear();
self.certificate.clear();
self.insecure = false;
self.special_fields.clear();
}
@@ -2283,6 +2295,7 @@ impl ::protobuf::Message for TlsOutboundSettings {
server_name: ::std::string::String::new(),
alpn: ::std::vec::Vec::new(),
certificate: ::std::string::String::new(),
insecure: false,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance

View File

@@ -148,6 +148,7 @@ pub struct TlsOutboundSettings {
pub server_name: Option<String>,
pub alpn: Option<Vec<String>>,
pub certificate: Option<String>,
pub insecure: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug)]
@@ -610,7 +611,8 @@ pub fn to_internal(json: &mut Config) -> Result<internal::Config> {
let ext_settings: ObfsOutboundSettings =
serde_json::from_str(ext_outbound.settings.as_ref().unwrap().get())
.unwrap();
if let Some(ext_method) = ext_settings.method { // TODO checks
if let Some(ext_method) = ext_settings.method {
// TODO checks
settings.method = ext_method;
} else {
settings.method = "http".to_string();
@@ -674,6 +676,7 @@ pub fn to_internal(json: &mut Config) -> Result<internal::Config> {
settings.certificate = path;
}
}
settings.insecure = ext_settings.insecure.unwrap_or_default();
}
let settings = settings.write_to_bytes().unwrap();
outbound.settings = settings;

View File

@@ -26,6 +26,32 @@ use {
use crate::{proxy::*, session::Session};
#[cfg(feature = "rustls-tls")]
mod dangerous {
use std::time::SystemTime;
use tokio_rustls::rustls::{
client::{ServerCertVerified, ServerCertVerifier},
Certificate, ServerName,
};
pub(super) struct NotVerified;
impl ServerCertVerifier for NotVerified {
fn verify_server_cert(
&self,
_end_entity: &Certificate,
_intermediates: &[Certificate],
server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
_now: SystemTime,
) -> core::result::Result<ServerCertVerified, rustls::Error> {
log::debug!("TLS cert for {:?} not verified", server_name);
Ok(ServerCertVerified::assertion())
}
}
}
pub struct Handler {
server_name: String,
#[cfg(feature = "rustls-tls")]
@@ -39,6 +65,7 @@ impl Handler {
server_name: String,
alpns: Vec<String>,
certificate: Option<String>,
insecure: bool,
) -> Result<Self> {
#[cfg(feature = "rustls-tls")]
{
@@ -66,12 +93,14 @@ impl Handler {
}),
);
}
let mut config = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_cert_store)
.with_no_client_auth();
if insecure {
let mut dangerous_config = config.dangerous();
dangerous_config.set_certificate_verifier(Arc::new(dangerous::NotVerified));
}
for alpn in alpns {
config.alpn_protocols.push(alpn.as_bytes().to_vec());
}
@@ -96,6 +125,9 @@ impl Handler {
.concat();
builder.set_alpn_protos(&wire).expect("set alpn failed");
}
if insecure {
builder.set_verify(openssl::ssl::SslVerifyMode::NONE);
}
let ssl_connector = builder.build();
Ok(Handler {
server_name,