Initial commit
This commit is contained in:
12
bonknet_server/Cargo.toml
Normal file
12
bonknet_server/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "bonknet_server"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
rcgen = "0.12.0"
|
||||
tokio-rustls = "0.25.0"
|
||||
rustls-pemfile = "2.0.0"
|
||||
86
bonknet_server/src/bin/init_certs.rs
Normal file
86
bonknet_server/src/bin/init_certs.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use rcgen::{self, BasicConstraints, Certificate, CertificateParams, DnType};
|
||||
|
||||
fn server_root_cert() -> Certificate {
|
||||
let subject_alt_names = vec!["hello.world.example".into()];
|
||||
let mut certparams = CertificateParams::new(subject_alt_names);
|
||||
certparams.is_ca = rcgen::IsCa::Ca(BasicConstraints::Unconstrained);
|
||||
let mut distname = rcgen::DistinguishedName::new();
|
||||
distname.push(DnType::OrganizationName, "Eister Corporation");
|
||||
distname.push(DnType::CommonName, "Bonknet Server Root Cert CA");
|
||||
certparams.distinguished_name = distname;
|
||||
Certificate::from_params(certparams).unwrap()
|
||||
}
|
||||
|
||||
fn server_cert() -> Certificate {
|
||||
let mut params = CertificateParams::new(vec!["entity.other.host".into(), "localhost".into()]);
|
||||
params.distinguished_name.push(DnType::CommonName, "localhost");
|
||||
params.use_authority_key_identifier_extension = true;
|
||||
params.key_usages.push(rcgen::KeyUsagePurpose::DigitalSignature);
|
||||
params
|
||||
.extended_key_usages
|
||||
.push(rcgen::ExtendedKeyUsagePurpose::ServerAuth);
|
||||
Certificate::from_params(params).unwrap()
|
||||
}
|
||||
|
||||
fn client_root_cert() -> Certificate {
|
||||
let subject_alt_names = vec!["hello.world.example".into()];
|
||||
let mut certparams = CertificateParams::new(subject_alt_names);
|
||||
certparams.is_ca = rcgen::IsCa::Ca(BasicConstraints::Unconstrained);
|
||||
let mut distname = rcgen::DistinguishedName::new();
|
||||
distname.push(DnType::OrganizationName, "Eister Corporation");
|
||||
distname.push(DnType::CommonName, "Bonknet Client Root Cert CA");
|
||||
certparams.distinguished_name = distname;
|
||||
Certificate::from_params(certparams).unwrap()
|
||||
}
|
||||
|
||||
fn client_cert() -> Certificate {
|
||||
let mut params = CertificateParams::new(vec!["entity.other.host".into(), "bonk.client.1".into()]);
|
||||
params.distinguished_name.push(DnType::CommonName, "Client 1");
|
||||
params.use_authority_key_identifier_extension = true;
|
||||
params.key_usages.push(rcgen::KeyUsagePurpose::DigitalSignature);
|
||||
params
|
||||
.extended_key_usages
|
||||
.push(rcgen::ExtendedKeyUsagePurpose::ClientAuth);
|
||||
Certificate::from_params(params).unwrap()
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
// SERVER
|
||||
let server_root_cert = server_root_cert();
|
||||
// The certificate is now valid for localhost and the domain "hello.world.example"
|
||||
{
|
||||
let mut certfile = File::create("server_root_cert.pem")?;
|
||||
certfile.write_all(server_root_cert.serialize_pem().unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("server_root_key.pem")?;
|
||||
privkfile.write_all(server_root_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// Now create the leaf
|
||||
let server_leaf_cert = server_cert();
|
||||
{
|
||||
let mut certfile = File::create("server_cert.pem")?;
|
||||
certfile.write_all(server_leaf_cert.serialize_pem_with_signer(&server_root_cert).unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("server_key.pem")?;
|
||||
privkfile.write_all(server_leaf_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// CLIENT
|
||||
let client_root_cert = client_root_cert();
|
||||
// The certificate is now valid for localhost and the domain "hello.world.example"
|
||||
{
|
||||
let mut certfile = File::create("client_root_cert.pem")?;
|
||||
certfile.write_all(client_root_cert.serialize_pem().unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("client_root_key.pem")?;
|
||||
privkfile.write_all(client_root_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
// Now create the leaf
|
||||
let client_leaf_cert = client_cert();
|
||||
{
|
||||
let mut certfile = File::create("client_cert.pem")?;
|
||||
certfile.write_all(client_leaf_cert.serialize_pem_with_signer(&client_root_cert).unwrap().as_bytes())?;
|
||||
let mut privkfile = File::create("client_key.pem")?;
|
||||
privkfile.write_all(client_leaf_cert.serialize_private_key_pem().as_bytes())?;
|
||||
}
|
||||
println!("Certificates created");
|
||||
Ok(())
|
||||
}
|
||||
75
bonknet_server/src/bin/server.rs
Normal file
75
bonknet_server/src/bin/server.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use tokio::net::{TcpListener};
|
||||
use std::io::{BufReader, Error, ErrorKind};
|
||||
use std::sync::{Arc};
|
||||
use tokio_rustls::{TlsAcceptor};
|
||||
use tokio_rustls::rustls::{RootCertStore, ServerConfig};
|
||||
use tokio_rustls::rustls::server::WebPkiClientVerifier;
|
||||
use rustls_pemfile::{read_one, Item};
|
||||
use tokio::io::{AsyncWriteExt, copy, split};
|
||||
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer};
|
||||
|
||||
fn load_cert(filename: &str) -> std::io::Result<CertificateDer> {
|
||||
let cert_file = std::fs::File::open(filename).unwrap();
|
||||
let mut buf = std::io::BufReader::new(cert_file);
|
||||
if let Item::X509Certificate(cert) = read_one(&mut buf).unwrap().unwrap() {
|
||||
Ok(cert)
|
||||
} else {
|
||||
eprintln!("File {} doesn't contain a X509 Certificate", filename);
|
||||
Err(Error::new(ErrorKind::InvalidInput, "no x509 cert"))
|
||||
}
|
||||
}
|
||||
|
||||
fn load_prkey(filename: &str) -> std::io::Result<PrivatePkcs8KeyDer> {
|
||||
let prkey_file = std::fs::File::open(filename).unwrap();
|
||||
let mut buf = BufReader::new(prkey_file);
|
||||
if let Item::Pkcs8Key(pkey) = read_one(&mut buf).unwrap().unwrap() {
|
||||
Ok(pkey)
|
||||
} else {
|
||||
eprintln!("File {} doesn't contain a Pkcs8 Private Key", filename);
|
||||
Err(Error::new(ErrorKind::InvalidInput, "no pkcs8key"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let server_root_cert_der = load_cert("server_root_cert.pem").unwrap();
|
||||
let server_cert_der = load_cert("server_cert.pem").unwrap();
|
||||
let server_prkey_der = load_prkey("server_key.pem").unwrap();
|
||||
// CLIENT ROOT
|
||||
let client_root_cert_der = load_cert("client_root_cert.pem").unwrap();
|
||||
// Client Verifier
|
||||
let mut clientrootstore = RootCertStore::empty();
|
||||
clientrootstore.add(client_root_cert_der).unwrap();
|
||||
let client_verifier = WebPkiClientVerifier::builder(Arc::new(clientrootstore)).build().unwrap();
|
||||
// Configure TLS
|
||||
let tlsconfig = ServerConfig::builder()
|
||||
// .with_no_client_auth()
|
||||
.with_client_cert_verifier(client_verifier)
|
||||
.with_single_cert(vec![server_cert_der.clone(), server_root_cert_der.clone()], server_prkey_der.into())
|
||||
.unwrap();
|
||||
let acceptor = TlsAcceptor::from(Arc::new(tlsconfig));
|
||||
|
||||
let listener = TcpListener::bind("localhost:6379").await.unwrap();
|
||||
|
||||
loop {
|
||||
let (stream, peer_addr) = listener.accept().await.unwrap();
|
||||
let acceptor = acceptor.clone();
|
||||
|
||||
let fut = async move {
|
||||
let stream = acceptor.accept(stream).await?;
|
||||
let (mut reader, mut writer) = split(stream);
|
||||
let n = copy(&mut reader, &mut writer).await?;
|
||||
writer.flush().await?;
|
||||
println!("Echo: {} - {}", peer_addr, n);
|
||||
|
||||
Ok(()) as std::io::Result<()>
|
||||
};
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = fut.await {
|
||||
eprintln!("{:?}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user