mirror of
https://github.com/outbackdingo/openlan-cgw.git
synced 2026-01-27 10:19:56 +00:00
Added function to retrieve CN name from peer certificate
This commit is contained in:
@@ -35,6 +35,7 @@ flate2 = "1.0.28"
|
||||
base64 = "0.22.0"
|
||||
rustls-pemfile = "2.1.2"
|
||||
rustls-pki-types = "1.7.0"
|
||||
x509-parser = "0.16.0"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.10"
|
||||
|
||||
33
run_cgw.sh
33
run_cgw.sh
@@ -33,6 +33,8 @@ DEFAULT_REDIS_DB_PORT=6379
|
||||
|
||||
CONTAINTER_CERTS_VOLUME="/etc/cgw/certs"
|
||||
|
||||
DEFAULT_ALLOW_CERT_MISMATCH="no"
|
||||
|
||||
export CGW_LOG_LEVEL="${CGW_LOG_LEVEL:-$DEFAULT_LOG_LEVEL}"
|
||||
export CGW_ID="${CGW_ID:-$DEFAULT_ID}"
|
||||
export CGW_WSS_IP="${CGW_WSS_IP:-$DEFAULT_WSS_IP}"
|
||||
@@ -55,22 +57,24 @@ export CGW_DB_PASSWORD="${CGW_DB_PASS:-$DEFAULT_DB_PASW}"
|
||||
export CGW_REDIS_IP="${CGW_REDIS_DB_IP:-$DEFAULT_REDIS_DB_IP}"
|
||||
export CGW_REDIS_PORT="${CGW_REDIS_DB_PORT:-$DEFAULT_REDIS_DB_PORT}"
|
||||
export CGW_CERTS_PATH="${CGW_CERTS_PATH:-$DEFAULT_CERTS_PATH}"
|
||||
export CGW_ALLOW_CERT_MISMATCH="${CGW_ALLOW_CERT_MISMATCH:-$DEFAULT_ALLOW_CERT_MISMATCH}"
|
||||
|
||||
echo "Starting CGW..."
|
||||
echo "CGW LOG LEVEL : $CGW_LOG_LEVEL"
|
||||
echo "CGW ID : $CGW_ID"
|
||||
echo "CGW WSS THREAD NUM: $CGW_WSS_THREAD_NUM"
|
||||
echo "CGW WSS IP/PORT : $CGW_WSS_IP:$CGW_WSS_PORT"
|
||||
echo "CGW WSS CAS : $CGW_WSS_CAS"
|
||||
echo "CGW WSS CERT : $CGW_WSS_CERT"
|
||||
echo "CGW WSS KEY : $CGW_WSS_KEY"
|
||||
echo "CGW GRPC : $CGW_GRPC_IP:$CGW_GRPC_PORT"
|
||||
echo "CGW KAFKA IP/PORT : $CGW_KAFKA_IP:$CGW_KAFKA_PORT"
|
||||
echo "CGW KAFKA TOPIC : $CGW_KAFKA_CONSUME_TOPIC:$CGW_KAFKA_PRODUCE_TOPIC"
|
||||
echo "CGW DB NAME : $CGW_DB_NAME"
|
||||
echo "CGW DB IP/PORT : $CGW_DB_IP:$CGW_DB_PORT"
|
||||
echo "CGW REDIS : $CGW_REDIS_IP:$CGW_REDIS_PORT"
|
||||
echo "CGW CERTS PATH : $CGW_CERTS_PATH"
|
||||
echo "CGW LOG LEVEL : $CGW_LOG_LEVEL"
|
||||
echo "CGW ID : $CGW_ID"
|
||||
echo "CGW WSS THREAD NUM : $CGW_WSS_THREAD_NUM"
|
||||
echo "CGW WSS IP/PORT : $CGW_WSS_IP:$CGW_WSS_PORT"
|
||||
echo "CGW WSS CAS : $CGW_WSS_CAS"
|
||||
echo "CGW WSS CERT : $CGW_WSS_CERT"
|
||||
echo "CGW WSS KEY : $CGW_WSS_KEY"
|
||||
echo "CGW GRPC : $CGW_GRPC_IP:$CGW_GRPC_PORT"
|
||||
echo "CGW KAFKA IP/PORT : $CGW_KAFKA_IP:$CGW_KAFKA_PORT"
|
||||
echo "CGW KAFKA TOPIC : $CGW_KAFKA_CONSUME_TOPIC:$CGW_KAFKA_PRODUCE_TOPIC"
|
||||
echo "CGW DB NAME : $CGW_DB_NAME"
|
||||
echo "CGW DB IP/PORT : $CGW_DB_IP:$CGW_DB_PORT"
|
||||
echo "CGW REDIS : $CGW_REDIS_IP:$CGW_REDIS_PORT"
|
||||
echo "CGW CERTS PATH : $CGW_CERTS_PATH"
|
||||
echo "CGW ALLOW CERT MISMATCH: $CGW_ALLOW_CERT_MISMATCH"
|
||||
|
||||
docker run \
|
||||
-v $CGW_CERTS_PATH:$CONTAINTER_CERTS_VOLUME \
|
||||
@@ -95,4 +99,5 @@ docker run \
|
||||
-e CGW_DB_PASSWORD \
|
||||
-e CGW_REDIS_IP \
|
||||
-e CGW_REDIS_PORT \
|
||||
-e CGW_ALLOW_CERT_MISMATCH \
|
||||
-d -t --network=host --name $2 $1 ucentral-cgw
|
||||
|
||||
@@ -71,7 +71,7 @@ impl CGWConnectionProcessor {
|
||||
conn_processor
|
||||
}
|
||||
|
||||
pub async fn start(mut self, tls_stream: TlsStream<TcpStream>) {
|
||||
pub async fn start(mut self, tls_stream: TlsStream<TcpStream>, client_cn: String, allow_mismatch: bool) {
|
||||
let ws_stream = tokio_tungstenite::accept_async(tls_stream)
|
||||
.await
|
||||
.expect("error during the websocket handshake occurred");
|
||||
@@ -126,6 +126,26 @@ impl CGWConnectionProcessor {
|
||||
}
|
||||
};
|
||||
|
||||
let device_serial = eui48::MacAddress::parse_str(&evt.serial).unwrap();
|
||||
let device_cn = eui48::MacAddress::parse_str(client_cn.as_str()).unwrap();
|
||||
|
||||
if !allow_mismatch {
|
||||
if device_serial != device_cn {
|
||||
error!(
|
||||
"The client MAC address {} and clinet certificate CN {} check failed!",
|
||||
device_serial.to_hex_string(),
|
||||
device_cn.to_hex_string()
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
debug!(
|
||||
"The client MAC address {} and clinet certificate CN {} chech passed!",
|
||||
device_serial.to_hex_string(),
|
||||
device_cn.to_hex_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Done Parse Connect Event");
|
||||
|
||||
let mut caps: CGWDeviceCapabilities = Default::default();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::cgw_device::{
|
||||
cgw_detect_device_chages, CGWDevice, CGWDeviceCapabilities, CGWDeviceState, OldNew,
|
||||
};
|
||||
use crate::cgw_tls::cgw_tls_get_cn_from_stream;
|
||||
use crate::cgw_ucentral_messages_queue_manager::{
|
||||
CGWUCentralMessagesQueueItem, CGW_MESSAGES_QUEUE,
|
||||
};
|
||||
@@ -28,7 +29,6 @@ use tokio::{
|
||||
},
|
||||
time::{sleep, Duration},
|
||||
};
|
||||
use tokio_rustls::server::TlsStream;
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
@@ -90,6 +90,9 @@ pub enum CGWConnectionNBAPIReqMsg {
|
||||
}
|
||||
|
||||
pub struct CGWConnectionServer {
|
||||
// Allow client certificate mismatch
|
||||
allow_mismatch: bool,
|
||||
|
||||
local_cgw_id: i32,
|
||||
// CGWConnectionServer write into this mailbox,
|
||||
// and other correspondig Server task Reads RX counterpart
|
||||
@@ -234,6 +237,7 @@ impl CGWConnectionServer {
|
||||
let nb_api_c = CGWNBApiClient::new(app_args, &nb_api_tx);
|
||||
|
||||
let server = Arc::new(CGWConnectionServer {
|
||||
allow_mismatch: app_args.allow_mismatch,
|
||||
local_cgw_id: app_args.cgw_id,
|
||||
connmap: CGWConnMap::new(),
|
||||
wss_rx_tx_runtime: wss_runtime_handle,
|
||||
@@ -1090,19 +1094,30 @@ impl CGWConnectionServer {
|
||||
// Only ACK connection. We will either drop it or accept it once processor starts
|
||||
// (we'll handle it via "mailbox" notify handle in process_internal_mbox)
|
||||
let server_clone = self.clone();
|
||||
let mut client_cn: String = String::new();
|
||||
|
||||
self.wss_rx_tx_runtime.spawn(async move {
|
||||
// Accept the TLS connection.
|
||||
let tls_stream = match tls_acceptor.accept(socket).await {
|
||||
Ok(a) => a,
|
||||
Ok(a) => match cgw_tls_get_cn_from_stream(&a).await {
|
||||
Some(cn) => {
|
||||
client_cn = cn;
|
||||
a
|
||||
}
|
||||
None => {
|
||||
warn!("Failed to get client certificate CN!");
|
||||
return;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
warn!("Err {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let allow_mismatch = server_clone.allow_mismatch;
|
||||
let conn_processor = CGWConnectionProcessor::new(server_clone, conn_idx, addr);
|
||||
conn_processor.start(tls_stream).await;
|
||||
conn_processor.start(tls_stream, client_cn, allow_mismatch).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ use std::{
|
||||
fs::File,
|
||||
io::{BufReader, Error, ErrorKind},
|
||||
};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_rustls::server::TlsStream;
|
||||
use x509_parser::parse_x509_certificate;
|
||||
|
||||
pub async fn cgw_tls_read_certs(cert_file: &str) -> Result<Vec<CertificateDer<'static>>, Error> {
|
||||
let file = match File::open(cert_file) {
|
||||
@@ -28,3 +31,24 @@ pub async fn cgw_tls_read_private_key(
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
}
|
||||
|
||||
pub async fn cgw_tls_get_cn_from_stream(stream: &TlsStream<TcpStream>) -> Option<String> {
|
||||
if let Some(certs) = stream.get_ref().1.peer_certificates() {
|
||||
let first_cert = certs.get(0).unwrap();
|
||||
|
||||
match parse_x509_certificate(first_cert.as_ref()) {
|
||||
Ok(parsed_cert) => {
|
||||
for rdn in parsed_cert.1.subject().iter_common_name() {
|
||||
if let Ok(cn) = rdn.as_str() {
|
||||
return Some(cn.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ const CGW_DEFAULT_DB_USERNAME: &str = "cgw";
|
||||
const CGW_DEFAULT_DB_PASSWORD: &str = "123";
|
||||
const CGW_DEFAULT_REDIS_IP: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
|
||||
const CGW_DEFAULT_REDIS_PORT: u16 = 5432;
|
||||
const CGW_DEFAULT_ALLOW_CERT_MISMATCH: &str = "no";
|
||||
|
||||
const CGW_CERTIFICATES_PATH: &str = "/etc/cgw/certs";
|
||||
|
||||
@@ -146,6 +147,9 @@ pub struct AppArgs {
|
||||
redis_db_ip: Ipv4Addr,
|
||||
/// PORT to connect to DB (REDIS)
|
||||
redis_db_port: u16,
|
||||
|
||||
/// Allow Missmatch
|
||||
allow_mismatch: bool,
|
||||
}
|
||||
|
||||
impl AppArgs {
|
||||
@@ -230,6 +234,9 @@ impl AppArgs {
|
||||
Err(_) => CGW_DEFAULT_REDIS_PORT,
|
||||
};
|
||||
|
||||
let mismatch: String = env::var("CGW_ALLOW_CERT_MISMATCH").unwrap_or(CGW_DEFAULT_ALLOW_CERT_MISMATCH.to_string());
|
||||
let allow_mismatch = mismatch == "yes";
|
||||
|
||||
AppArgs {
|
||||
log_level,
|
||||
cgw_id,
|
||||
@@ -252,6 +259,7 @@ impl AppArgs {
|
||||
db_password,
|
||||
redis_db_ip,
|
||||
redis_db_port,
|
||||
allow_mismatch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user