diff --git a/src/tls.rs b/src/tls.rs index f5f538c..d15875c 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -1 +1,2 @@ +pub mod grades; pub mod load; diff --git a/src/tls/grades.rs b/src/tls/grades.rs new file mode 100644 index 0000000..5b2d2c6 --- /dev/null +++ b/src/tls/grades.rs @@ -0,0 +1,75 @@ +use log::{info, warn}; +use pingora::tls::ssl::{select_next_proto, AlpnError, SslRef, SslVersion}; +use pingora_core::listeners::tls::TlsSettings; + +#[derive(Debug)] +pub struct CipherSuite { + pub high: &'static str, + pub medium: &'static str, + pub legacy: &'static str, +} +const CIPHERS: CipherSuite = CipherSuite { + high: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305", + medium: "ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:AES128-GCM-SHA256", + legacy: "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH", +}; + +#[derive(Debug)] +pub enum TlsGrade { + HIGH, + MEDIUM, + LEGACY, +} + +impl TlsGrade { + pub fn from_str(s: &str) -> Option { + match s.to_ascii_lowercase().as_str() { + "high" => Some(TlsGrade::HIGH), + "medium" => Some(TlsGrade::MEDIUM), + "unsafe" => Some(TlsGrade::LEGACY), + _ => None, + } + } +} +pub fn prefer_h2<'a>(_ssl: &mut SslRef, alpn_in: &'a [u8]) -> Result<&'a [u8], AlpnError> { + match select_next_proto("\x02h2\x08http/1.1".as_bytes(), alpn_in) { + Some(p) => Ok(p), + _ => Err(AlpnError::NOACK), + } +} + +pub fn set_tsl_grade(tls_settings: &mut TlsSettings, grade: &str) { + let config_grade = TlsGrade::from_str(grade); + match config_grade { + Some(TlsGrade::HIGH) => { + let _ = tls_settings.set_min_proto_version(Some(SslVersion::TLS1_2)); + // let _ = tls_settings.set_max_proto_version(Some(SslVersion::TLS1_3)); + let _ = tls_settings.set_cipher_list(CIPHERS.high); + // let _ = tls_settings.set_ciphersuites(CIPHERS.high); + let _ = tls_settings.set_cipher_list(CIPHERS.high); + info!("TLS grade: {:?}, => HIGH", tls_settings.options()); + } + Some(TlsGrade::MEDIUM) => { + let _ = tls_settings.set_min_proto_version(Some(SslVersion::TLS1)); + let _ = tls_settings.set_cipher_list(CIPHERS.medium); + // let _ = tls_settings.set_ciphersuites(CIPHERS.medium); + let _ = tls_settings.set_cipher_list(CIPHERS.medium); + info!("TLS grade: {:?}, => MEDIUM", tls_settings.options()); + } + Some(TlsGrade::LEGACY) => { + let _ = tls_settings.set_min_proto_version(Some(SslVersion::SSL3)); + let _ = tls_settings.set_cipher_list(CIPHERS.legacy); + // let _ = tls_settings.set_ciphersuites(CIPHERS.legacy); + let _ = tls_settings.set_cipher_list(CIPHERS.legacy); + warn!("TLS grade: {:?}, => UNSAFE", tls_settings.options()); + } + None => { + // Defaults to MEDIUM + let _ = tls_settings.set_min_proto_version(Some(SslVersion::TLS1)); + let _ = tls_settings.set_cipher_list(CIPHERS.medium); + // let _ = tls_settings.set_ciphersuites(CIPHERS.medium); + let _ = tls_settings.set_cipher_list(CIPHERS.medium); + warn!("TLS grade is not detected defaulting top MEDIUM"); + } + } +} diff --git a/src/tls/load.rs b/src/tls/load.rs index dc8b263..2f3ce59 100644 --- a/src/tls/load.rs +++ b/src/tls/load.rs @@ -1,7 +1,7 @@ +use crate::tls::grades; use dashmap::DashMap; -use log::{error, info, warn}; -use pingora::tls::ssl::{select_next_proto, AlpnError, NameType, SniError, SslAlert, SslContext, SslFiletype, SslMethod, SslRef, SslVersion}; -use pingora_core::listeners::tls::TlsSettings; +use log::error; +use pingora::tls::ssl::{NameType, SniError, SslAlert, SslContext, SslFiletype, SslMethod, SslRef}; use rustls_pemfile::{read_one, Item}; use serde::Deserialize; use std::collections::HashSet; @@ -10,7 +10,6 @@ use std::io::BufReader; use x509_parser::extensions::GeneralName; use x509_parser::nom::Err as NomErr; use x509_parser::prelude::*; - #[derive(Clone, Deserialize, Debug)] pub struct CertificateConfig { pub cert_path: String, @@ -180,79 +179,7 @@ fn create_ssl_context(cert_path: &str, key_path: &str) -> Result Option { - match s.to_ascii_lowercase().as_str() { - "high" => Some(TlsGrade::HIGH), - "medium" => Some(TlsGrade::MEDIUM), - "unsafe" => Some(TlsGrade::LEGACY), - _ => None, - } - } -} -pub fn prefer_h2<'a>(_ssl: &mut SslRef, alpn_in: &'a [u8]) -> Result<&'a [u8], AlpnError> { - match select_next_proto("\x02h2\x08http/1.1".as_bytes(), alpn_in) { - Some(p) => Ok(p), - _ => Err(AlpnError::NOACK), - } -} - -pub fn set_tsl_grade(tls_settings: &mut TlsSettings, grade: &str) { - let config_grade = TlsGrade::from_str(grade); - match config_grade { - Some(TlsGrade::HIGH) => { - let _ = tls_settings.set_min_proto_version(Some(SslVersion::TLS1_2)); - // let _ = tls_settings.set_max_proto_version(Some(SslVersion::TLS1_3)); - let _ = tls_settings.set_cipher_list(CIPHERS.high); - // let _ = tls_settings.set_ciphersuites(CIPHERS.high); - let _ = tls_settings.set_cipher_list(CIPHERS.high); - info!("TLS grade: {:?}, => HIGH", tls_settings.options()); - } - Some(TlsGrade::MEDIUM) => { - let _ = tls_settings.set_min_proto_version(Some(SslVersion::TLS1)); - let _ = tls_settings.set_cipher_list(CIPHERS.medium); - // let _ = tls_settings.set_ciphersuites(CIPHERS.medium); - let _ = tls_settings.set_cipher_list(CIPHERS.medium); - info!("TLS grade: {:?}, => MEDIUM", tls_settings.options()); - } - Some(TlsGrade::LEGACY) => { - let _ = tls_settings.set_min_proto_version(Some(SslVersion::SSL3)); - let _ = tls_settings.set_cipher_list(CIPHERS.legacy); - // let _ = tls_settings.set_ciphersuites(CIPHERS.legacy); - let _ = tls_settings.set_cipher_list(CIPHERS.legacy); - warn!("TLS grade: {:?}, => UNSAFE", tls_settings.options()); - } - None => { - // Defaults to MEDIUM - let _ = tls_settings.set_min_proto_version(Some(SslVersion::TLS1)); - let _ = tls_settings.set_cipher_list(CIPHERS.medium); - // let _ = tls_settings.set_ciphersuites(CIPHERS.medium); - let _ = tls_settings.set_cipher_list(CIPHERS.medium); - warn!("TLS grade is not detected defaulting top MEDIUM"); - } - } -} diff --git a/src/web/start.rs b/src/web/start.rs index 53b23b2..a34f533 100644 --- a/src/web/start.rs +++ b/src/web/start.rs @@ -1,4 +1,5 @@ // use rustls::crypto::ring::default_provider; +use crate::tls::grades; use crate::tls::load; use crate::tls::load::CertificateConfig; use crate::utils::structs::Extraparams; @@ -79,9 +80,9 @@ pub fn run() { let mut tls_settings = TlsSettings::intermediate(&certs_for_callback.load().default_cert_path, &certs_for_callback.load().default_key_path).expect("unable to load or parse cert/key"); - load::set_tsl_grade(&mut tls_settings, grade.as_str()); + grades::set_tsl_grade(&mut tls_settings, grade.as_str()); tls_settings.set_servername_callback(move |ssl_ref: &mut SslRef, ssl_alert: &mut SslAlert| certs_for_callback.load().server_name_callback(ssl_ref, ssl_alert)); - tls_settings.set_alpn_select_callback(load::prefer_h2); + tls_settings.set_alpn_select_callback(grades::prefer_h2); proxy.add_tls_with_settings(&bind_address_tls, None, tls_settings);