diff --git a/Cargo.lock b/Cargo.lock index 092b055..b8827f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -88,15 +88,15 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.12", "time", ] [[package]] name = "asn1-rs-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", @@ -129,9 +129,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.13.1" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" +checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" dependencies = [ "aws-lc-sys", "zeroize", @@ -139,9 +139,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" +checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" dependencies = [ "bindgen", "cc", @@ -256,9 +256,9 @@ checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" @@ -268,9 +268,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.27" +version = "1.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" dependencies = [ "jobserver", "libc", @@ -305,9 +305,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", "clap_derive", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -327,9 +327,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck", "proc-macro2", @@ -422,9 +422,9 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "der-parser" -version = "9.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ "asn1-rs", "displaydoc", @@ -688,9 +688,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "h2" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", "bytes", @@ -776,6 +776,7 @@ dependencies = [ "native-tls", "rcgen", "reqwest", + "rustls-pki-types", "thiserror 2.0.12", "tokio", "tokio-native-tls", @@ -853,9 +854,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "base64", "bytes", @@ -869,7 +870,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", "system-configuration", "tokio", "tower-service", @@ -986,14 +987,25 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", ] +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -1280,9 +1292,9 @@ dependencies = [ [[package]] name = "oid-registry" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" dependencies = [ "asn1-rs", ] @@ -1429,9 +1441,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "prettyplease" -version = "0.2.34" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", "syn", @@ -1463,9 +1475,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rcgen" -version = "0.13.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +checksum = "0068c5b3cab1d4e271e0bb6539c87563c43411cad90b057b15c79958fbeb41f7" dependencies = [ "pem", "ring", @@ -1477,9 +1489,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec" dependencies = [ "bitflags", ] @@ -1530,9 +1542,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.20" +version = "0.12.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" dependencies = [ "base64", "bytes", @@ -1627,22 +1639,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "rustls" -version = "0.23.28" +version = "0.23.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" +checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" dependencies = [ "aws-lc-rs", "log", @@ -1664,9 +1676,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.3" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "aws-lc-rs", "ring", @@ -1758,9 +1770,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -1827,6 +1839,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1847,9 +1869,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.103" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -1912,7 +1934,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.7", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -2008,17 +2030,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.45.1" +version = "1.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", - "socket2", + "slab", + "socket2 0.5.10", "tokio-macros", "windows-sys 0.52.0", ] @@ -2346,9 +2370,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] @@ -2473,9 +2497,9 @@ dependencies = [ [[package]] name = "windows-registry" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ "windows-link", "windows-result", @@ -2666,9 +2690,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -2690,9 +2714,9 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "x509-parser" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" dependencies = [ "asn1-rs", "data-encoding", @@ -2702,7 +2726,7 @@ dependencies = [ "oid-registry", "ring", "rusticata-macros", - "thiserror 1.0.69", + "thiserror 2.0.12", "time", ] diff --git a/Cargo.toml b/Cargo.toml index 53b6b6c..7c8255e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ hyper = { version = "1.0.1", features = ["http1", "http2", "server", "client"] } futures = "0.3.29" bytes = "1.7.1" http-body-util = "0.1.0" -rcgen = "0.13.1" +rcgen = "0.14.3" tokio-rustls = "0.26.1" tracing = "0.1.40" hyper-util = { version = "0.1.11", features = ["tokio"] } @@ -51,7 +51,8 @@ webpki-roots = { version = "1.0.1", optional = true } axum = { version = "0.8.3", features = ["http2"] } clap = { version = "4.5.35", features = ["derive"] } ctor = "0.4.1" -rcgen = { version = "0.13.1", features = ["x509-parser"] } +rcgen = { version = "0.14.3", features = ["x509-parser", "pem"] } reqwest = { version = "0.12.15", features = ["native-tls-alpn"] } +rustls-pki-types = "1.12.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } winnow = "0.7.4" diff --git a/README.md b/README.md index 621fe19..8c6c9ae 100644 --- a/README.md +++ b/README.md @@ -20,35 +20,50 @@ use tracing_subscriber::EnvFilter; #[derive(Parser)] struct Opt { #[clap(flatten)] - external_cert: Option, + external_issuer: Option, } #[derive(Args, Debug)] -struct ExternalCert { +struct ExternalIssuer { #[arg(required = false)] cert: PathBuf, #[arg(required = false)] private_key: PathBuf, } -fn make_root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn make_root_issuer() -> rcgen::Issuer<'static, rcgen::KeyPair> { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + let cert = params.self_signed(&signing_key).unwrap(); + + println!(); + println!("Trust this cert if you want to use HTTPS"); + println!(); + println!("{}", cert.pem()); + println!(); + + /* + Save this cert to ca.crt and use it with curl like this: + curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt + */ + + println!("Private key"); + println!("{}", signing_key.serialize_pem()); + + rcgen::Issuer::new(params, signing_key) } #[tokio::main] @@ -59,29 +74,25 @@ async fn main() { .with_env_filter(EnvFilter::from_default_env()) .init(); - let root_cert = if let Some(external_cert) = opt.external_cert { + let root_issuer = if let Some(external_issuer) = opt.external_issuer { // Use existing key - let param = rcgen::CertificateParams::from_ca_cert_pem( - &std::fs::read_to_string(&external_cert.cert).unwrap(), + let signing_key = rcgen::KeyPair::from_pem( + &std::fs::read_to_string(&external_issuer.private_key).unwrap(), ) .unwrap(); - let key_pair = - rcgen::KeyPair::from_pem(&std::fs::read_to_string(&external_cert.private_key).unwrap()) - .unwrap(); - - let cert = param.self_signed(&key_pair).unwrap(); - rcgen::CertifiedKey { cert, key_pair } + rcgen::Issuer::from_ca_cert_pem( + &std::fs::read_to_string(&external_issuer.cert).unwrap(), + signing_key, + ) + .unwrap() } else { - make_root_cert() + make_root_issuer() }; - let root_cert_pem = root_cert.cert.pem(); - let root_cert_key = root_cert.key_pair.serialize_pem(); - let proxy = MitmProxy::new( // This is the root cert that will be used to sign the fake certificates - Some(root_cert), + Some(root_issuer), Some(Cache::new(128)), ); @@ -112,20 +123,6 @@ async fn main() { println!("HTTP Proxy is listening on http://127.0.0.1:3003"); - println!(); - println!("Trust this cert if you want to use HTTPS"); - println!(); - println!("{}", root_cert_pem); - println!(); - - /* - Save this cert to ca.crt and use it with curl like this: - curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt - */ - - println!("Private key"); - println!("{}", root_cert_key); - server.await; } ``` diff --git a/examples/dev_proxy.rs b/examples/dev_proxy.rs index 0352b97..cfd5241 100644 --- a/examples/dev_proxy.rs +++ b/examples/dev_proxy.rs @@ -13,35 +13,50 @@ use http_mitm_proxy::{ #[derive(Parser)] struct Opt { #[clap(flatten)] - external_cert: Option, + external_issuer: Option, } #[derive(Args, Debug)] -struct ExternalCert { +struct ExternalIssuer { #[arg(required = false)] cert: PathBuf, #[arg(required = false)] private_key: PathBuf, } -fn make_root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn make_root_issuer() -> rcgen::Issuer<'static, rcgen::KeyPair> { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + let cert = params.self_signed(&signing_key).unwrap(); + + println!(); + println!("Trust this cert if you want to use HTTPS"); + println!(); + println!("{}", cert.pem()); + println!(); + + /* + Save this cert to ca.crt and use it with curl like this: + curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt + */ + + println!("Private key"); + println!("{}", signing_key.serialize_pem()); + + rcgen::Issuer::new(params, signing_key) } #[tokio::main] @@ -56,29 +71,25 @@ async fn main() { .unwrap(); tokio::spawn(async { axum::serve(listener, app).await }); - let root_cert = if let Some(external_cert) = opt.external_cert { + let root_issuer = if let Some(external_issuer) = opt.external_issuer { // Use existing key - let param = rcgen::CertificateParams::from_ca_cert_pem( - &std::fs::read_to_string(&external_cert.cert).unwrap(), + let signing_key = rcgen::KeyPair::from_pem( + &std::fs::read_to_string(&external_issuer.private_key).unwrap(), ) .unwrap(); - let key_pair = - rcgen::KeyPair::from_pem(&std::fs::read_to_string(&external_cert.private_key).unwrap()) - .unwrap(); - - let cert = param.self_signed(&key_pair).unwrap(); - rcgen::CertifiedKey { cert, key_pair } + rcgen::Issuer::from_ca_cert_pem( + &std::fs::read_to_string(&external_issuer.cert).unwrap(), + signing_key, + ) + .unwrap() } else { - make_root_cert() + make_root_issuer() }; - let root_cert_pem = root_cert.cert.pem(); - let root_cert_key = root_cert.key_pair.serialize_pem(); - let proxy = MitmProxy::new( // This is the root cert that will be used to sign the fake certificates - Some(root_cert), + Some(root_issuer), Some(Cache::new(128)), ); @@ -107,8 +118,7 @@ async fn main() { req.headers_mut().insert( hyper::header::HOST, hyper::header::HeaderValue::from_maybe_shared(format!( - "127.0.0.1:{}", - port + "127.0.0.1:{port}" )) .unwrap(), ); @@ -117,8 +127,7 @@ async fn main() { parts.scheme = Some(hyper::http::uri::Scheme::HTTP); parts.authority = Some( hyper::http::uri::Authority::from_maybe_shared(format!( - "127.0.0.1:{}", - port + "127.0.0.1:{port}" )) .unwrap(), ); @@ -136,19 +145,5 @@ async fn main() { println!("HTTP Proxy is listening on http://127.0.0.1:3003"); - println!(); - println!("Trust this cert if you want to use HTTPS"); - println!(); - println!("{}", root_cert_pem); - println!(); - - /* - Save this cert to ca.crt and use it with curl like this: - curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt - */ - - println!("Private key"); - println!("{}", root_cert_key); - proxy.await; } diff --git a/examples/https.rs b/examples/https.rs index a20b1e0..a3fdd6d 100644 --- a/examples/https.rs +++ b/examples/https.rs @@ -3,45 +3,64 @@ use std::{path::PathBuf, sync::Arc}; use clap::{Args, Parser}; use http_mitm_proxy::{DefaultClient, MitmProxy, hyper::service::service_fn, moka::sync::Cache}; use hyper_util::rt::{TokioExecutor, TokioIo}; +use rustls_pki_types::pem::PemObject; use tokio::net::TcpListener; use tokio_rustls::{ TlsAcceptor, - rustls::{self, ServerConfig, pki_types::PrivatePkcs8KeyDer}, + rustls::{ + self, ServerConfig, + pki_types::{CertificateDer, PrivatePkcs8KeyDer}, + }, }; use tracing_subscriber::EnvFilter; #[derive(Parser)] struct Opt { #[clap(flatten)] - external_cert: Option, + external_issuer: Option, } #[derive(Args, Debug)] -struct ExternalCert { +struct ExternalIssuer { #[arg(required = false)] cert: PathBuf, #[arg(required = false)] private_key: PathBuf, } -fn make_root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn make_root_issuer() -> (rcgen::Issuer<'static, rcgen::KeyPair>, Vec) { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + let cert = params.self_signed(&signing_key).unwrap(); + + println!(); + println!("Trust this cert if you want to use HTTPS"); + println!(); + println!("{}", cert.pem()); + println!(); + + /* + Save this cert to ca.crt and use it with curl like this: + curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt + */ + + println!("Private key"); + println!("{}", signing_key.serialize_pem()); + + (rcgen::Issuer::new(params, signing_key), cert.der().to_vec()) } #[tokio::main] @@ -53,33 +72,35 @@ async fn main() { .with_line_number(true) .init(); - let root_cert = if let Some(external_cert) = opt.external_cert { + let (root_issuer, cert_der) = if let Some(external_issuer) = opt.external_issuer { // Use existing key - let param = rcgen::CertificateParams::from_ca_cert_pem( - &std::fs::read_to_string(&external_cert.cert).unwrap(), + let signing_key = rcgen::KeyPair::from_pem( + &std::fs::read_to_string(&external_issuer.private_key).unwrap(), ) .unwrap(); - let key_pair = - rcgen::KeyPair::from_pem(&std::fs::read_to_string(&external_cert.private_key).unwrap()) - .unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let cert_pem = std::fs::read_to_string(&external_issuer.cert).unwrap(); + let cert = rustls_pki_types::CertificateDer::from_pem_slice(cert_pem.as_bytes()).unwrap(); - rcgen::CertifiedKey { cert, key_pair } + ( + rcgen::Issuer::from_ca_cert_pem( + &std::fs::read_to_string(&external_issuer.cert).unwrap(), + signing_key, + ) + .unwrap(), + cert.to_vec(), + ) } else { - make_root_cert() + make_root_issuer() }; - let root_cert_pem = root_cert.cert.pem(); - let root_cert_key = root_cert.key_pair.serialize_pem(); - // Reusing the same root cert for proxy server let mut server_config = ServerConfig::builder() .with_no_client_auth() .with_single_cert( - vec![root_cert.cert.der().clone()], + vec![CertificateDer::from(cert_der)], rustls::pki_types::PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( - root_cert.key_pair.serialize_der(), + root_issuer.key().serialize_der(), )), ) .unwrap(); @@ -87,7 +108,7 @@ async fn main() { let proxy = MitmProxy::new( // This is the root cert that will be used to sign the fake certificates - Some(root_cert), + Some(root_issuer), Some(Cache::new(128)), ); let proxy = Arc::new(proxy); @@ -152,19 +173,5 @@ async fn main() { println!("HTTPS Proxy is listening on https://127.0.0.1:3003"); - println!(); - println!("Trust this cert if you want to use HTTPS"); - println!(); - println!("{}", root_cert_pem); - println!(); - - /* - You can test HTTPS proxy with curl like this: - curl -x https://localhost:3003 https://example.com --insecure --proxy-insecure - */ - - println!("Private key"); - println!("{}", root_cert_key); - server.await; } diff --git a/examples/proxy.rs b/examples/proxy.rs index 57e0b11..add36c3 100644 --- a/examples/proxy.rs +++ b/examples/proxy.rs @@ -7,35 +7,50 @@ use tracing_subscriber::EnvFilter; #[derive(Parser)] struct Opt { #[clap(flatten)] - external_cert: Option, + external_issuer: Option, } #[derive(Args, Debug)] -struct ExternalCert { +struct ExternalIssuer { #[arg(required = false)] cert: PathBuf, #[arg(required = false)] private_key: PathBuf, } -fn make_root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn make_root_issuer() -> rcgen::Issuer<'static, rcgen::KeyPair> { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + let cert = params.self_signed(&signing_key).unwrap(); + + println!(); + println!("Trust this cert if you want to use HTTPS"); + println!(); + println!("{}", cert.pem()); + println!(); + + /* + Save this cert to ca.crt and use it with curl like this: + curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt + */ + + println!("Private key"); + println!("{}", signing_key.serialize_pem()); + + rcgen::Issuer::new(params, signing_key) } #[tokio::main] @@ -46,29 +61,25 @@ async fn main() { .with_env_filter(EnvFilter::from_default_env()) .init(); - let root_cert = if let Some(external_cert) = opt.external_cert { + let root_issuer = if let Some(external_issuer) = opt.external_issuer { // Use existing key - let param = rcgen::CertificateParams::from_ca_cert_pem( - &std::fs::read_to_string(&external_cert.cert).unwrap(), + let signing_key = rcgen::KeyPair::from_pem( + &std::fs::read_to_string(&external_issuer.private_key).unwrap(), ) .unwrap(); - let key_pair = - rcgen::KeyPair::from_pem(&std::fs::read_to_string(&external_cert.private_key).unwrap()) - .unwrap(); - - let cert = param.self_signed(&key_pair).unwrap(); - rcgen::CertifiedKey { cert, key_pair } + rcgen::Issuer::from_ca_cert_pem( + &std::fs::read_to_string(&external_issuer.cert).unwrap(), + signing_key, + ) + .unwrap() } else { - make_root_cert() + make_root_issuer() }; - let root_cert_pem = root_cert.cert.pem(); - let root_cert_key = root_cert.key_pair.serialize_pem(); - let proxy = MitmProxy::new( // This is the root cert that will be used to sign the fake certificates - Some(root_cert), + Some(root_issuer), Some(Cache::new(128)), ); @@ -99,19 +110,5 @@ async fn main() { println!("HTTP Proxy is listening on http://127.0.0.1:3003"); - println!(); - println!("Trust this cert if you want to use HTTPS"); - println!(); - println!("{}", root_cert_pem); - println!(); - - /* - Save this cert to ca.crt and use it with curl like this: - curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt - */ - - println!("Private key"); - println!("{}", root_cert_key); - server.await; } diff --git a/examples/reqwest_proxy.rs b/examples/reqwest_proxy.rs index cc60cc3..6d4719e 100644 --- a/examples/reqwest_proxy.rs +++ b/examples/reqwest_proxy.rs @@ -13,35 +13,50 @@ use tracing_subscriber::EnvFilter; #[derive(Parser)] struct Opt { #[clap(flatten)] - external_cert: Option, + external_issuer: Option, } #[derive(Args, Debug)] -struct ExternalCert { +struct ExternalIssuer { #[arg(required = false)] cert: PathBuf, #[arg(required = false)] private_key: PathBuf, } -fn make_root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn make_root_issuer() -> rcgen::Issuer<'static, rcgen::KeyPair> { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + let cert = params.self_signed(&signing_key).unwrap(); + + println!(); + println!("Trust this cert if you want to use HTTPS"); + println!(); + println!("{}", cert.pem()); + println!(); + + /* + Save this cert to ca.crt and use it with curl like this: + curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt + */ + + println!("Private key"); + println!("{}", signing_key.serialize_pem()); + + rcgen::Issuer::new(params, signing_key) } #[tokio::main] @@ -52,29 +67,25 @@ async fn main() { .with_env_filter(EnvFilter::from_default_env()) .init(); - let root_cert = if let Some(external_cert) = opt.external_cert { + let root_issuer = if let Some(external_issuer) = opt.external_issuer { // Use existing key - let param = rcgen::CertificateParams::from_ca_cert_pem( - &std::fs::read_to_string(&external_cert.cert).unwrap(), + let signing_key = rcgen::KeyPair::from_pem( + &std::fs::read_to_string(&external_issuer.private_key).unwrap(), ) .unwrap(); - let key_pair = - rcgen::KeyPair::from_pem(&std::fs::read_to_string(&external_cert.private_key).unwrap()) - .unwrap(); - - let cert = param.self_signed(&key_pair).unwrap(); - rcgen::CertifiedKey { cert, key_pair } + rcgen::Issuer::from_ca_cert_pem( + &std::fs::read_to_string(&external_issuer.cert).unwrap(), + signing_key, + ) + .unwrap() } else { - make_root_cert() + make_root_issuer() }; - let root_cert_pem = root_cert.cert.pem(); - let root_cert_key = root_cert.key_pair.serialize_pem(); - let proxy = MitmProxy::new( // This is the root cert that will be used to sign the fake certificates - Some(root_cert), + Some(root_issuer), Some(Cache::new(128)), ); @@ -106,20 +117,6 @@ async fn main() { println!("HTTP Proxy is listening on http://127.0.0.1:3003"); - println!(); - println!("Trust this cert if you want to use HTTPS"); - println!(); - println!("{}", root_cert_pem); - println!(); - - /* - Save this cert to ca.crt and use it with curl like this: - curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt - */ - - println!("Private key"); - println!("{}", root_cert_key); - server.await; } diff --git a/examples/websocket.rs b/examples/websocket.rs index 4c3706f..22c3432 100644 --- a/examples/websocket.rs +++ b/examples/websocket.rs @@ -12,35 +12,50 @@ use winnow::Parser as _; #[derive(Parser)] struct Opt { #[clap(flatten)] - external_cert: Option, + external_issuer: Option, } #[derive(Args, Debug)] -struct ExternalCert { +struct ExternalIssuer { #[arg(required = false)] cert: PathBuf, #[arg(required = false)] private_key: PathBuf, } -fn make_root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn make_root_issuer() -> rcgen::Issuer<'static, rcgen::KeyPair> { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + let cert = params.self_signed(&signing_key).unwrap(); + + println!(); + println!("Trust this cert if you want to use HTTPS"); + println!(); + println!("{}", cert.pem()); + println!(); + + /* + Save this cert to ca.crt and use it with curl like this: + curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt + */ + + println!("Private key"); + println!("{}", signing_key.serialize_pem()); + + rcgen::Issuer::new(params, signing_key) } #[tokio::main] @@ -52,29 +67,25 @@ async fn main() { .with_line_number(true) .init(); - let root_cert = if let Some(external_cert) = opt.external_cert { + let root_issuer = if let Some(external_issuer) = opt.external_issuer { // Use existing key - let param = rcgen::CertificateParams::from_ca_cert_pem( - &std::fs::read_to_string(&external_cert.cert).unwrap(), + let signing_key = rcgen::KeyPair::from_pem( + &std::fs::read_to_string(&external_issuer.private_key).unwrap(), ) .unwrap(); - let key_pair = - rcgen::KeyPair::from_pem(&std::fs::read_to_string(&external_cert.private_key).unwrap()) - .unwrap(); - - let cert = param.self_signed(&key_pair).unwrap(); - rcgen::CertifiedKey { cert, key_pair } + rcgen::Issuer::from_ca_cert_pem( + &std::fs::read_to_string(&external_issuer.cert).unwrap(), + signing_key, + ) + .unwrap() } else { - make_root_cert() + make_root_issuer() }; - let root_cert_pem = root_cert.cert.pem(); - let root_cert_key = root_cert.key_pair.serialize_pem(); - let proxy = MitmProxy::new( // This is the root cert that will be used to sign the fake certificates - Some(root_cert), + Some(root_issuer), Some(Cache::new(128)), ); @@ -177,20 +188,6 @@ async fn main() { println!("HTTP Proxy is listening on http://127.0.0.1:3003"); - println!(); - println!("Trust this cert if you want to use HTTPS"); - println!(); - println!("{}", root_cert_pem); - println!(); - - /* - Save this cert to ca.crt and use it with curl like this: - curl https://www.google.com -x http://127.0.0.1:3003 --cacert ca.crt - */ - - println!("Private key"); - println!("{}", root_cert_key); - server.await; } diff --git a/src/default_client.rs b/src/default_client.rs index 9a99ec0..6de439e 100644 --- a/src/default_client.rs +++ b/src/default_client.rs @@ -82,20 +82,20 @@ impl DefaultClient { #[cfg(feature = "native-tls-client")] pub fn new() -> Self { Self::try_new().unwrap_or_else(|err| { - panic!("Failed to create DefaultClient: {}", err); + panic!("Failed to create DefaultClient: {err}"); }) } #[cfg(feature = "native-tls-client")] pub fn try_new() -> Result { let tls_connector_no_alpn = native_tls::TlsConnector::builder().build().map_err(|e| { - Error::TlsConnectorError(format!("Failed to build no-ALPN connector: {}", e)) + Error::TlsConnectorError(format!("Failed to build no-ALPN connector: {e}")) })?; let tls_connector_alpn_h2 = native_tls::TlsConnector::builder() .request_alpns(&["h2", "http/1.1"]) .build() .map_err(|e| { - Error::TlsConnectorError(format!("Failed to build ALPN-H2 connector: {}", e)) + Error::TlsConnectorError(format!("Failed to build ALPN-H2 connector: {e}")) })?; Ok(Self { diff --git a/src/lib.rs b/src/lib.rs index 6c15df2..c8e47e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,31 +30,31 @@ pub use default_client::DefaultClient; #[derive(Clone)] /// The main struct to run proxy server -pub struct MitmProxy { - /// Root certificate to sign fake certificates. You may need to trust this certificate on client application to use HTTPS. +pub struct MitmProxy { + /// Root issuer to sign fake certificates. You may need to trust this issuer on client application to use HTTPS. /// /// If None, proxy will just tunnel HTTPS traffic and will not observe HTTPS traffic. - pub root_cert: Option, + pub root_issuer: Option, /// Cache to store generated certificates. If None, cache will not be used. - /// If root_cert is None, cache will not be used. + /// If root_issuer is None, cache will not be used. /// /// The key of cache is hostname. pub cert_cache: Option>, } -impl MitmProxy { +impl MitmProxy { /// Create a new MitmProxy - pub fn new(root_cert: Option, cache: Option>) -> Self { + pub fn new(root_issuer: Option, cache: Option>) -> Self { Self { - root_cert, + root_issuer, cert_cache: cache, } } } -impl MitmProxy +impl MitmProxy where - C: Borrow + Send + Sync + 'static, + I: Borrow> + Send + Sync + 'static, { /// Bind to a socket address and return a future that runs the proxy server. /// URL for requests that passed to service are full URL including scheme. @@ -242,19 +242,19 @@ where } fn get_certified_key(&self, host: String) -> Option { - self.root_cert.as_ref().and_then(|root_cert| { + self.root_issuer.as_ref().and_then(|root_issuer| { if let Some(cache) = self.cert_cache.as_ref() { // Try to get from cache, but handle generation errors gracefully cache .try_get_with(host.clone(), move || { - generate_cert(host, root_cert.borrow()) + generate_cert(host, root_issuer.borrow()) }) .map_err(|err| { tracing::error!("Failed to generate certificate for host: {}", err); }) .ok() } else { - generate_cert(host, root_cert.borrow()) + generate_cert(host, root_issuer.borrow()) .map_err(|err| { tracing::error!("Failed to generate certificate for host: {}", err); }) diff --git a/src/tls.rs b/src/tls.rs index 0b7242e..213f738 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -7,7 +7,7 @@ pub struct CertifiedKeyDer { pub fn generate_cert( host: String, - root_cert: &rcgen::CertifiedKey, + issuer: &rcgen::Issuer, ) -> Result { let mut cert_params = rcgen::CertificateParams::new(vec![host.clone()])?; cert_params @@ -27,7 +27,7 @@ pub fn generate_cert( let key_pair = rcgen::KeyPair::generate()?; - let cert = cert_params.signed_by(&key_pair, &root_cert.cert, &root_cert.key_pair)?; + let cert = cert_params.signed_by(&key_pair, issuer)?; Ok(CertifiedKeyDer { cert_der: cert.der().to_vec(), diff --git a/tests/test.rs b/tests/test.rs index 05692e1..bf35b5a 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -31,24 +31,23 @@ fn get_port() -> u16 { PORT.fetch_add(1, std::sync::atomic::Ordering::Relaxed) } -fn root_cert() -> rcgen::CertifiedKey { - let mut param = rcgen::CertificateParams::default(); +fn root_cert() -> rcgen::Issuer<'static, rcgen::KeyPair> { + let mut params = rcgen::CertificateParams::default(); - param.distinguished_name = rcgen::DistinguishedName::new(); - param.distinguished_name.push( + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( rcgen::DnType::CommonName, rcgen::DnValue::Utf8String("".to_string()), ); - param.key_usages = vec![ + params.key_usages = vec![ rcgen::KeyUsagePurpose::KeyCertSign, rcgen::KeyUsagePurpose::CrlSign, ]; - param.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - let key_pair = rcgen::KeyPair::generate().unwrap(); - let cert = param.self_signed(&key_pair).unwrap(); + let signing_key = rcgen::KeyPair::generate().unwrap(); - rcgen::CertifiedKey { cert, key_pair } + rcgen::Issuer::new(params, signing_key) } async fn bind_app(app: Router) -> (u16, impl std::future::Future) { @@ -63,17 +62,17 @@ async fn bind_app(app: Router) -> (u16, impl std::future::Future) { fn client(proxy_port: u16) -> reqwest::Client { reqwest::Client::builder() - .proxy(reqwest::Proxy::http(format!("http://127.0.0.1:{}", proxy_port)).unwrap()) - .proxy(reqwest::Proxy::https(format!("http://127.0.0.1:{}", proxy_port)).unwrap()) + .proxy(reqwest::Proxy::http(format!("http://127.0.0.1:{proxy_port}")).unwrap()) + .proxy(reqwest::Proxy::https(format!("http://127.0.0.1:{proxy_port}")).unwrap()) .build() .unwrap() } -fn client_tls(proxy_port: u16, cert: &rcgen::CertifiedKey) -> reqwest::Client { +fn client_tls(proxy_port: u16, cert: &rcgen::Certificate) -> reqwest::Client { reqwest::Client::builder() - .proxy(reqwest::Proxy::http(format!("http://127.0.0.1:{}", proxy_port)).unwrap()) - .proxy(reqwest::Proxy::https(format!("http://127.0.0.1:{}", proxy_port)).unwrap()) - .add_root_certificate(reqwest::Certificate::from_der(cert.cert.der()).unwrap()) + .proxy(reqwest::Proxy::http(format!("http://127.0.0.1:{proxy_port}")).unwrap()) + .proxy(reqwest::Proxy::https(format!("http://127.0.0.1:{proxy_port}")).unwrap()) + .add_root_certificate(reqwest::Certificate::from_der(cert.der()).unwrap()) .build() .unwrap() } @@ -106,7 +105,7 @@ where async fn setup_tls( app: Router, service: S, - root_cert: Arc, + root_cert: Arc>, ) -> (u16, u16) where B: Body + Send + Sync + 'static, @@ -146,7 +145,7 @@ async fn test_simple_http() { let client = client(proxy_port); let res = client - .get(format!("http://127.0.0.1:{}/", port)) + .get(format!("http://127.0.0.1:{port}/")) .send() .await .unwrap(); @@ -185,7 +184,7 @@ async fn test_modify_http() { let client = client(proxy_port); let res = client - .get(format!("http://127.0.0.1:{}/", port)) + .get(format!("http://127.0.0.1:{port}/")) .send() .await .unwrap(); @@ -217,7 +216,7 @@ async fn test_sse_http() { let client = client(proxy_port); let res = client - .get(format!("http://127.0.0.1:{}/sse", port)) + .get(format!("http://127.0.0.1:{port}/sse")) .send() .await .unwrap(); @@ -233,7 +232,25 @@ async fn test_simple_https() { const BODY: &str = "Hello, World!"; let app = Router::new().route("/", get(|| async move { BODY })); - let cert = Arc::new(root_cert()); + let mut params = rcgen::CertificateParams::default(); + + params.distinguished_name = rcgen::DistinguishedName::new(); + params.distinguished_name.push( + rcgen::DnType::CommonName, + rcgen::DnValue::Utf8String("".to_string()), + ); + params.key_usages = vec![ + rcgen::KeyUsagePurpose::KeyCertSign, + rcgen::KeyUsagePurpose::CrlSign, + ]; + params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); + + let signing_key = rcgen::KeyPair::generate().unwrap(); + + let cert = params.self_signed(&signing_key).unwrap(); + + let issuer = rcgen::Issuer::new(params, signing_key); + let issuer = Arc::new(issuer); let proxy_client = proxy_client(); let (proxy_port, port) = setup_tls( @@ -249,14 +266,14 @@ async fn test_simple_https() { proxy_client.send_request(req).await.map(|t| t.0) } }), - cert.clone(), + issuer.clone(), ) .await; let client = client_tls(proxy_port, &cert); let res = client - .get(format!("https://127.0.0.1:{}/", port)) + .get(format!("https://127.0.0.1:{port}/")) .send() .await .unwrap();