-
-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7bc6e30
commit f98c778
Showing
42 changed files
with
943 additions
and
531 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
[package] | ||
name = "rpxy-lib-legacy" | ||
version = "0.6.2" | ||
authors = ["Jun Kurihara"] | ||
homepage = "https://github.com/junkurihara/rust-rpxy" | ||
repository = "https://github.com/junkurihara/rust-rpxy" | ||
license = "MIT" | ||
readme = "../README.md" | ||
edition = "2021" | ||
publish = false | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[features] | ||
default = ["http3-s2n", "sticky-cookie", "cache"] | ||
http3-quinn = ["quinn", "h3", "h3-quinn", "socket2"] | ||
http3-s2n = ["h3", "s2n-quic", "s2n-quic-rustls", "s2n-quic-h3"] | ||
sticky-cookie = ["base64", "sha2", "chrono"] | ||
cache = ["http-cache-semantics", "lru"] | ||
native-roots = ["hyper-rustls/native-tokio"] | ||
|
||
[dependencies] | ||
rand = "0.8.5" | ||
rustc-hash = "1.1.0" | ||
bytes = "1.5.0" | ||
derive_builder = "0.12.0" | ||
futures = { version = "0.3.29", features = ["alloc", "async-await"] } | ||
tokio = { version = "1.34.0", default-features = false, features = [ | ||
"net", | ||
"rt-multi-thread", | ||
"time", | ||
"sync", | ||
"macros", | ||
"fs", | ||
] } | ||
async-trait = "0.1.74" | ||
hot_reload = "0.1.4" # reloading certs | ||
|
||
# Error handling | ||
anyhow = "1.0.75" | ||
thiserror = "1.0.50" | ||
|
||
# http and tls | ||
http = "1.0.0" | ||
http-body-util = "0.1.0" | ||
hyper = { version = "1.0.1", default-features = false } | ||
hyper-util = { version = "0.1.1", features = ["full"] } | ||
hyper-rustls = { version = "0.24.2", default-features = false, features = [ | ||
"tokio-runtime", | ||
"webpki-tokio", | ||
"http1", | ||
"http2", | ||
] } | ||
tokio-rustls = { version = "0.24.1", features = ["early-data"] } | ||
rustls = { version = "0.21.9", default-features = false } | ||
webpki = "0.22.4" | ||
x509-parser = "0.15.1" | ||
|
||
# logging | ||
tracing = { version = "0.1.40" } | ||
|
||
# http/3 | ||
quinn = { version = "0.10.2", optional = true } | ||
h3 = { path = "../submodules/h3/h3/", optional = true } | ||
h3-quinn = { path = "../submodules/h3/h3-quinn/", optional = true } | ||
s2n-quic = { version = "1.31.0", default-features = false, features = [ | ||
"provider-tls-rustls", | ||
], optional = true } | ||
s2n-quic-h3 = { path = "../submodules/s2n-quic-h3/", optional = true } | ||
s2n-quic-rustls = { version = "0.31.0", optional = true } | ||
# for UDP socket wit SO_REUSEADDR when h3 with quinn | ||
socket2 = { version = "0.5.5", features = ["all"], optional = true } | ||
|
||
# cache | ||
http-cache-semantics = { path = "../submodules/rusty-http-cache-semantics/", optional = true } | ||
lru = { version = "0.12.0", optional = true } | ||
|
||
# cookie handling for sticky cookie | ||
chrono = { version = "0.4.31", default-features = false, features = [ | ||
"unstable-locales", | ||
"alloc", | ||
"clock", | ||
], optional = true } | ||
base64 = { version = "0.21.5", optional = true } | ||
sha2 = { version = "0.10.8", default-features = false, optional = true } | ||
|
||
|
||
[dev-dependencies] | ||
# http and tls |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
use async_trait::async_trait; | ||
use rustc_hash::FxHashSet as HashSet; | ||
use rustls::{ | ||
sign::{any_supported_type, CertifiedKey}, | ||
Certificate, OwnedTrustAnchor, PrivateKey, | ||
}; | ||
use std::io; | ||
use x509_parser::prelude::*; | ||
|
||
#[async_trait] | ||
// Trait to read certs and keys anywhere from KVS, file, sqlite, etc. | ||
pub trait CryptoSource { | ||
type Error; | ||
|
||
/// read crypto materials from source | ||
async fn read(&self) -> Result<CertsAndKeys, Self::Error>; | ||
|
||
/// Returns true when mutual tls is enabled | ||
fn is_mutual_tls(&self) -> bool; | ||
} | ||
|
||
/// Certificates and private keys in rustls loaded from files | ||
#[derive(Debug, PartialEq, Eq, Clone)] | ||
pub struct CertsAndKeys { | ||
pub certs: Vec<Certificate>, | ||
pub cert_keys: Vec<PrivateKey>, | ||
pub client_ca_certs: Option<Vec<Certificate>>, | ||
} | ||
|
||
impl CertsAndKeys { | ||
pub fn parse_server_certs_and_keys(&self) -> Result<CertifiedKey, anyhow::Error> { | ||
// for (server_name_bytes_exp, certs_and_keys) in self.inner.iter() { | ||
let signing_key = self | ||
.cert_keys | ||
.iter() | ||
.find_map(|k| { | ||
if let Ok(sk) = any_supported_type(k) { | ||
Some(sk) | ||
} else { | ||
None | ||
} | ||
}) | ||
.ok_or_else(|| { | ||
io::Error::new( | ||
io::ErrorKind::InvalidInput, | ||
"Unable to find a valid certificate and key", | ||
) | ||
})?; | ||
Ok(CertifiedKey::new(self.certs.clone(), signing_key)) | ||
} | ||
|
||
pub fn parse_client_ca_certs(&self) -> Result<(Vec<OwnedTrustAnchor>, HashSet<Vec<u8>>), anyhow::Error> { | ||
let certs = self.client_ca_certs.as_ref().ok_or(anyhow::anyhow!("No client cert"))?; | ||
|
||
let owned_trust_anchors: Vec<_> = certs | ||
.iter() | ||
.map(|v| { | ||
// let trust_anchor = tokio_rustls::webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap(); | ||
let trust_anchor = webpki::TrustAnchor::try_from_cert_der(&v.0).unwrap(); | ||
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( | ||
trust_anchor.subject, | ||
trust_anchor.spki, | ||
trust_anchor.name_constraints, | ||
) | ||
}) | ||
.collect(); | ||
|
||
// TODO: SKID is not used currently | ||
let subject_key_identifiers: HashSet<_> = certs | ||
.iter() | ||
.filter_map(|v| { | ||
// retrieve ca key id (subject key id) | ||
let cert = parse_x509_certificate(&v.0).unwrap().1; | ||
let subject_key_ids = cert | ||
.iter_extensions() | ||
.filter_map(|ext| match ext.parsed_extension() { | ||
ParsedExtension::SubjectKeyIdentifier(skid) => Some(skid), | ||
_ => None, | ||
}) | ||
.collect::<Vec<_>>(); | ||
if !subject_key_ids.is_empty() { | ||
Some(subject_key_ids[0].0.to_owned()) | ||
} else { | ||
None | ||
} | ||
}) | ||
.collect(); | ||
|
||
Ok((owned_trust_anchors, subject_key_identifiers)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
pub const RESPONSE_HEADER_SERVER: &str = "rpxy"; | ||
// pub const LISTEN_ADDRESSES_V4: &[&str] = &["0.0.0.0"]; | ||
// pub const LISTEN_ADDRESSES_V6: &[&str] = &["[::]"]; | ||
pub const TCP_LISTEN_BACKLOG: u32 = 1024; | ||
// pub const HTTP_LISTEN_PORT: u16 = 8080; | ||
// pub const HTTPS_LISTEN_PORT: u16 = 8443; | ||
pub const PROXY_TIMEOUT_SEC: u64 = 60; | ||
pub const UPSTREAM_TIMEOUT_SEC: u64 = 60; | ||
pub const TLS_HANDSHAKE_TIMEOUT_SEC: u64 = 15; // default as with firefox browser | ||
pub const MAX_CLIENTS: usize = 512; | ||
pub const MAX_CONCURRENT_STREAMS: u32 = 64; | ||
pub const CERTS_WATCH_DELAY_SECS: u32 = 60; | ||
pub const LOAD_CERTS_ONLY_WHEN_UPDATED: bool = true; | ||
|
||
// #[cfg(feature = "http3")] | ||
// pub const H3_RESPONSE_BUF_SIZE: usize = 65_536; // 64KB | ||
// #[cfg(feature = "http3")] | ||
// pub const H3_REQUEST_BUF_SIZE: usize = 65_536; // 64KB // handled by quinn | ||
|
||
#[allow(non_snake_case)] | ||
#[cfg(any(feature = "http3-quinn", feature = "http3-s2n"))] | ||
pub mod H3 { | ||
pub const ALT_SVC_MAX_AGE: u32 = 3600; | ||
pub const REQUEST_MAX_BODY_SIZE: usize = 268_435_456; // 256MB | ||
pub const MAX_CONCURRENT_CONNECTIONS: u32 = 4096; | ||
pub const MAX_CONCURRENT_BIDISTREAM: u32 = 64; | ||
pub const MAX_CONCURRENT_UNISTREAM: u32 = 64; | ||
pub const MAX_IDLE_TIMEOUT: u64 = 10; // secs | ||
} | ||
|
||
#[cfg(feature = "sticky-cookie")] | ||
/// For load-balancing with sticky cookie | ||
pub const STICKY_COOKIE_NAME: &str = "rpxy_srv_id"; | ||
|
||
#[cfg(feature = "cache")] | ||
// # of entries in cache | ||
pub const MAX_CACHE_ENTRY: usize = 1_000; | ||
#[cfg(feature = "cache")] | ||
// max size for each file in bytes | ||
pub const MAX_CACHE_EACH_SIZE: usize = 65_535; | ||
#[cfg(feature = "cache")] | ||
// on memory cache if less than or equel to | ||
pub const MAX_CACHE_EACH_SIZE_ON_MEMORY: usize = 4_096; | ||
|
||
// TODO: max cache size in total |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
pub use anyhow::{anyhow, bail, ensure, Context}; | ||
use std::io; | ||
use thiserror::Error; | ||
|
||
pub type Result<T> = std::result::Result<T, RpxyError>; | ||
|
||
/// Describes things that can go wrong in the Rpxy | ||
#[derive(Debug, Error)] | ||
pub enum RpxyError { | ||
#[error("Proxy build error: {0}")] | ||
ProxyBuild(#[from] crate::proxy::ProxyBuilderError), | ||
|
||
#[error("Backend build error: {0}")] | ||
BackendBuild(#[from] crate::backend::BackendBuilderError), | ||
|
||
#[error("MessageHandler build error: {0}")] | ||
HandlerBuild(#[from] crate::handler::HttpMessageHandlerBuilderError), | ||
|
||
#[error("Config builder error: {0}")] | ||
ConfigBuild(&'static str), | ||
|
||
#[error("Http Message Handler Error: {0}")] | ||
Handler(&'static str), | ||
|
||
#[error("Cache Error: {0}")] | ||
Cache(&'static str), | ||
|
||
#[error("Http Request Message Error: {0}")] | ||
Request(&'static str), | ||
|
||
#[error("TCP/UDP Proxy Layer Error: {0}")] | ||
Proxy(String), | ||
|
||
#[allow(unused)] | ||
#[error("LoadBalance Layer Error: {0}")] | ||
LoadBalance(String), | ||
|
||
#[error("I/O Error: {0}")] | ||
Io(#[from] io::Error), | ||
|
||
// #[error("Toml Deserialization Error")] | ||
// TomlDe(#[from] toml::de::Error), | ||
#[cfg(feature = "http3-quinn")] | ||
#[error("Quic Connection Error [quinn]: {0}")] | ||
QuicConn(#[from] quinn::ConnectionError), | ||
|
||
#[cfg(feature = "http3-s2n")] | ||
#[error("Quic Connection Error [s2n-quic]: {0}")] | ||
QUicConn(#[from] s2n_quic::connection::Error), | ||
|
||
#[cfg(feature = "http3-quinn")] | ||
#[error("H3 Error [quinn]: {0}")] | ||
H3(#[from] h3::Error), | ||
|
||
#[cfg(feature = "http3-s2n")] | ||
#[error("H3 Error [s2n-quic]: {0}")] | ||
H3(#[from] s2n_quic_h3::h3::Error), | ||
|
||
#[error("rustls Connection Error: {0}")] | ||
Rustls(#[from] rustls::Error), | ||
|
||
#[error("Hyper Error: {0}")] | ||
Hyper(#[from] hyper::Error), | ||
|
||
#[error("Hyper Http Error: {0}")] | ||
HyperHttp(#[from] hyper::http::Error), | ||
|
||
#[error("Hyper Http HeaderValue Error: {0}")] | ||
HyperHeaderValue(#[from] hyper::header::InvalidHeaderValue), | ||
|
||
#[error("Hyper Http HeaderName Error: {0}")] | ||
HyperHeaderName(#[from] hyper::header::InvalidHeaderName), | ||
|
||
#[error(transparent)] | ||
Other(#[from] anyhow::Error), | ||
} | ||
|
||
#[allow(dead_code)] | ||
#[derive(Debug, Error, Clone)] | ||
pub enum ClientCertsError { | ||
#[error("TLS Client Certificate is Required for Given SNI: {0}")] | ||
ClientCertRequired(String), | ||
|
||
#[error("Inconsistent TLS Client Certificate for Given SNI: {0}")] | ||
InconsistentClientCert(String), | ||
} |
Oops, something went wrong.