From c3372f029602557305dacb715b0b76d2e698fa42 Mon Sep 17 00:00:00 2001 From: zu1k Date: Sun, 23 Oct 2022 19:43:25 +0800 Subject: [PATCH 1/5] feat: http support transparent proxy --- Cargo.lock | 375 +++++++++++++++++++++++++++------------- Cargo.toml | 2 +- crates/core/Cargo.toml | 2 +- crates/core/src/ca.rs | 55 ++++-- crates/core/src/mitm.rs | 47 +++-- 5 files changed, 323 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6fd28cc..f4b02c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9a8f622bcf6ff3df478e9deba3e03e4e04b300f8e6a139e192c05fa3490afc7" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "asn1-rs" @@ -23,7 +23,23 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33" dependencies = [ - "asn1-rs-derive", + "asn1-rs-derive 0.1.0", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4" +dependencies = [ + "asn1-rs-derive 0.4.0", "asn1-rs-impl", "displaydoc", "nom", @@ -45,6 +61,18 @@ dependencies = [ "synstructure", ] +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "asn1-rs-impl" version = "0.1.0" @@ -87,9 +115,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", @@ -121,9 +149,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bit-set" @@ -157,9 +185,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytecount" @@ -264,26 +292,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.21" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed5341b2301a26ab80be5cbdced622e80ed808483c52e45e3310a877d3b37d7" +checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap", "once_cell", "strsim", "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.18" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3" dependencies = [ "heck", "proc-macro-error", @@ -294,9 +320,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ "os_str_bytes", ] @@ -312,9 +338,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" dependencies = [ "time", "version_check", @@ -366,26 +392,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -445,7 +469,21 @@ version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82" dependencies = [ - "asn1-rs", + "asn1-rs 0.3.1", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der-parser" +version = "8.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" +dependencies = [ + "asn1-rs 0.5.1", "displaydoc", "nom", "num-bigint", @@ -455,9 +493,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer", "crypto-common", @@ -476,9 +514,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "atty", "humantime", @@ -544,9 +582,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "futures" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", @@ -559,9 +597,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -569,15 +607,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-executor" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" dependencies = [ "futures-core", "futures-task", @@ -586,9 +624,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-lite" @@ -607,9 +645,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", @@ -618,21 +656,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-channel", "futures-core", @@ -658,9 +696,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -709,7 +747,7 @@ dependencies = [ "moka", "openssl", "rand", - "rcgen", + "rcgen 0.10.0", "rustls", "serde", "thiserror", @@ -940,9 +978,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "js-sys" @@ -971,9 +1009,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "libquickjs-sys" @@ -987,9 +1025,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -1049,7 +1087,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -1172,20 +1210,29 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a" dependencies = [ - "asn1-rs", + "asn1-rs 0.3.1", +] + +[[package]] +name = "oid-registry" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761" +dependencies = [ + "asn1-rs 0.5.1", ] [[package]] name = "once_cell" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if", @@ -1224,9 +1271,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg", "cc", @@ -1260,15 +1307,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1344,9 +1391,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -1421,9 +1468,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -1446,7 +1493,20 @@ dependencies = [ "pem", "ring", "time", - "x509-parser", + "x509-parser 0.13.2", + "yasna", +] + +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem", + "ring", + "time", + "x509-parser 0.14.0", "yasna", ] @@ -1511,9 +1571,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.6" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" dependencies = [ "log", "ring", @@ -1564,7 +1624,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -1617,27 +1677,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -1646,9 +1706,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" dependencies = [ "itoa", "ryu", @@ -1657,9 +1717,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.11" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89f31df3f50926cdf2855da5fd8812295c34752cb20438dae42a67f79e021ac3" +checksum = "6d232d893b10de3eb7258ff01974d6ee20663d8e833263c99409d4b13a0209da" dependencies = [ "indexmap", "itoa", @@ -1670,9 +1730,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", @@ -1714,9 +1774,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" @@ -1742,9 +1802,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -1792,26 +1852,20 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - [[package]] name = "thiserror" -version = "1.0.34" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1b05ca9d106ba7d2e31a9dab4a64e7be2cce415321966ea3132c49a656e252" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.34" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8f2591983642de85c921015f3f070c665a197ed69e417af436115e3a1407487" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -1820,9 +1874,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" dependencies = [ "itoa", "libc", @@ -1838,9 +1892,9 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tokio" -version = "1.21.0" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89797afd69d206ccd11fb0ea560a44bbb87731d020670e79416d442919257d42" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -1848,7 +1902,6 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", "pin-project-lite", "signal-hook-registry", "socket2", @@ -1910,9 +1963,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", @@ -1921,9 +1974,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] @@ -1939,7 +1992,7 @@ name = "trust_cert" version = "0.0.4" dependencies = [ "nix", - "rcgen", + "rcgen 0.9.3", "windows", ] @@ -1977,21 +2030,21 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unsafe-libyaml" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931179334a56395bcf64ba5e0ff56781381c1a5832178280c7d7f91d1679aeb0" +checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" [[package]] name = "untrusted" @@ -2001,9 +2054,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "uuid" -version = "1.1.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83" dependencies = [ "getrandom", ] @@ -2227,6 +2280,27 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" @@ -2239,6 +2313,12 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" @@ -2251,6 +2331,12 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" @@ -2263,6 +2349,12 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" @@ -2275,6 +2367,18 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" @@ -2287,19 +2391,44 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "x509-parser" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" dependencies = [ - "asn1-rs", + "asn1-rs 0.3.1", + "base64", + "data-encoding", + "der-parser 7.0.0", + "lazy_static", + "nom", + "oid-registry 0.4.0", + "ring", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs 0.5.1", "base64", "data-encoding", - "der-parser", + "der-parser 8.1.0", "lazy_static", "nom", - "oid-registry", + "oid-registry 0.6.0", "ring", "rusticata-macros", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 14e37b4..8f4b7c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ mitm-core = { path = "crates/core", package = "good-mitm-core" } rule = { path = "crates/rule", package = "good-mitm-rule" } anyhow = "1.0" -clap = { version = "3.0", features = ["derive"] } +clap = { version = "4", features = ["derive"] } thiserror = "1" log = "0.4" env_logger = "0.9" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 2bde842..5205644 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -19,7 +19,7 @@ hyper-tls = { version = "0.5", optional = true } log = "0.4" moka = { version = "0.9", features = ["future"] } openssl = { version = "0.10", features = ["vendored"], optional = true } -rcgen = { version = "0.9", features = ["x509-parser"] } +rcgen = { version = "0.10", features = ["x509-parser"] } serde = { version = "1.0", features = ["derive"] } thiserror = "1" time = "0.3" diff --git a/crates/core/src/ca.rs b/crates/core/src/ca.rs index 35cee60..e0ef501 100644 --- a/crates/core/src/ca.rs +++ b/crates/core/src/ca.rs @@ -1,11 +1,14 @@ use crate::error::Error; -use http::uri::Authority; -use moka::future::Cache; +use moka::sync::Cache; use rand::{thread_rng, Rng}; use rcgen::{ BasicConstraints, Certificate, CertificateParams, DistinguishedName, DnType, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose, RcgenError, SanType, }; +use rustls::{ + server::{ClientHello, ResolvesServerCert}, + sign::CertifiedKey, +}; use std::sync::Arc; use time::{ext::NumericalDuration, OffsetDateTime}; use tokio_rustls::rustls::{self, ServerConfig}; @@ -23,7 +26,7 @@ pub struct CertificateAuthority { private_key: rustls::PrivateKey, ca_cert: rustls::Certificate, ca_cert_string: String, - cache: Cache>, + cache: Cache>, } impl CertificateAuthority { @@ -68,28 +71,23 @@ impl CertificateAuthority { Ok(ca) } - pub(crate) async fn gen_server_config(&self, authority: &Authority) -> Arc { - if let Some(server_cfg) = self.cache.get(authority) { + pub(crate) fn get_certified_key(&self, server_name: &str) -> Arc { + if let Some(server_cfg) = self.cache.get(server_name) { return server_cfg; } - let certs = vec![self.gen_cert(authority)]; - - let server_cfg = ServerConfig::builder() - .with_safe_defaults() - .with_no_client_auth() - .with_single_cert(certs, self.private_key.clone()) - .expect("Failed to set certificate"); - let server_cfg = Arc::new(server_cfg); + let certs = vec![self.gen_cert(server_name)]; + let key = rustls::sign::any_supported_type(&self.private_key) + .expect("parse any supported private key"); + let certified_key = Arc::new(CertifiedKey::new(certs, key)); self.cache - .insert(authority.clone(), Arc::clone(&server_cfg)) - .await; + .insert(server_name.to_string(), certified_key.clone()); - server_cfg + certified_key } - fn gen_cert(&self, authority: &Authority) -> rustls::Certificate { + fn gen_cert(&self, server_name: &str) -> rustls::Certificate { let mut params = rcgen::CertificateParams::default(); params.serial_number = Some(thread_rng().gen::()); @@ -97,9 +95,9 @@ impl CertificateAuthority { params.not_after = OffsetDateTime::now_utc().saturating_add((CERT_TTL_DAYS as i64).days()); params .subject_alt_names - .push(SanType::DnsName(authority.host().to_string())); + .push(SanType::DnsName(server_name.to_string())); let mut distinguished_name = DistinguishedName::new(); - distinguished_name.push(DnType::CommonName, authority.host()); + distinguished_name.push(DnType::CommonName, server_name); params.distinguished_name = distinguished_name; params.key_usages = vec![KeyUsagePurpose::DigitalSignature]; @@ -136,4 +134,23 @@ impl CertificateAuthority { pub fn get_cert(&self) -> String { self.ca_cert_string.clone() } + + pub fn gen_server_config(self: Arc) -> Arc { + let server_cfg = ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_cert_resolver(self); + Arc::new(server_cfg) + } +} + +impl ResolvesServerCert for CertificateAuthority { + fn resolve(&self, client_hello: ClientHello) -> Option> { + if let Some(name) = client_hello.server_name() { + Some(self.get_certified_key(name)) + } else { + // This kind of resolver requires SNI + None + } + } } diff --git a/crates/core/src/mitm.rs b/crates/core/src/mitm.rs index f9f0059..7e8e18b 100644 --- a/crates/core/src/mitm.rs +++ b/crates/core/src/mitm.rs @@ -3,7 +3,11 @@ use crate::{ handler::{CustomContextData, HttpHandler, MitmFilter}, http_client::HttpClient, }; -use http::{header, uri::PathAndQuery, HeaderValue, Uri}; +use http::{ + header, + uri::{PathAndQuery, Scheme}, + HeaderValue, Uri, +}; use hyper::{ body::HttpBody, server::conn::Http, service::service_fn, upgrade::Upgraded, Body, Method, Request, Response, @@ -61,26 +65,39 @@ where allow_all_cros(&mut res); Ok(res) } - Err(err) => Err(err), + Err(err) => { + error!("proxy request failed: {err:?}"); + Err(err) + } } } - async fn process_request(self, req: Request) -> Result, hyper::Error> { + async fn process_request(self, mut req: Request) -> Result, hyper::Error> { let mut ctx = HttpContext { uri: None, should_modify_response: false, ..Default::default() }; - if req.uri().path().starts_with("/mitm/cert") - || req - .headers() - .get(http::header::HOST) - .unwrap() - .to_str() - .unwrap_or_default() - .contains("cert.mitm") - { + let host = req + .headers() + .get(http::header::HOST) + .map(|h| h.to_str()) + .unwrap() + .map(|h| h.to_owned()) + .unwrap_or_default(); + + let uri = req.uri_mut(); + if uri.authority().is_none() { + *uri = http::uri::Uri::builder() + .scheme(uri.scheme().unwrap_or(&Scheme::HTTP).as_str()) + .authority(host.as_str()) + .path_and_query(uri.path_and_query().map_or("/", |p| p.as_str())) + .build() + .unwrap(); + } + + if req.uri().path().starts_with("/mitm/cert") || host.contains("cert.mitm") { return Ok(self.get_cert_res()); } @@ -91,7 +108,7 @@ where { let header_mut = req.headers_mut(); - header_mut.remove(http::header::HOST); + // header_mut.remove(http::header::HOST); header_mut.remove(http::header::ACCEPT_ENCODING); header_mut.remove(http::header::CONTENT_LENGTH); } @@ -125,6 +142,7 @@ where should_modify_response: false, ..Default::default() }; + if self.mitm_filter.filter(&ctx, &req).await { tokio::task::spawn(async move { let authority = req @@ -135,7 +153,8 @@ where match hyper::upgrade::on(req).await { Ok(upgraded) => { - let server_config = self.ca.gen_server_config(&authority).await; + let server_config = self.ca.clone().gen_server_config(); + let stream = TlsAcceptor::from(server_config) .accept(upgraded) .await From 6721eaea67dc8a298c383105ad75d357c6718ceb Mon Sep 17 00:00:00 2001 From: zu1k Date: Sun, 23 Oct 2022 19:46:14 +0800 Subject: [PATCH 2/5] deps: update trust_cert deps --- Cargo.lock | 147 +++++------------------------------ crates/trust_cert/Cargo.toml | 4 +- 2 files changed, 20 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4b02c7..4cf3731 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,29 +17,13 @@ version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" -[[package]] -name = "asn1-rs" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33" -dependencies = [ - "asn1-rs-derive 0.1.0", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time", -] - [[package]] name = "asn1-rs" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4" dependencies = [ - "asn1-rs-derive 0.4.0", + "asn1-rs-derive", "asn1-rs-impl", "displaydoc", "nom", @@ -49,18 +33,6 @@ dependencies = [ "time", ] -[[package]] -name = "asn1-rs-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "asn1-rs-derive" version = "0.4.0" @@ -463,27 +435,13 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" -[[package]] -name = "der-parser" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82" -dependencies = [ - "asn1-rs 0.3.1", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "der-parser" version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1" dependencies = [ - "asn1-rs 0.5.1", + "asn1-rs", "displaydoc", "nom", "num-bigint", @@ -747,7 +705,7 @@ dependencies = [ "moka", "openssl", "rand", - "rcgen 0.10.0", + "rcgen", "rustls", "serde", "thiserror", @@ -1204,22 +1162,13 @@ dependencies = [ "libc", ] -[[package]] -name = "oid-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a" -dependencies = [ - "asn1-rs 0.3.1", -] - [[package]] name = "oid-registry" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761" dependencies = [ - "asn1-rs 0.5.1", + "asn1-rs", ] [[package]] @@ -1484,19 +1433,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "rcgen" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" -dependencies = [ - "pem", - "ring", - "time", - "x509-parser 0.13.2", - "yasna", -] - [[package]] name = "rcgen" version = "0.10.0" @@ -1506,7 +1442,7 @@ dependencies = [ "pem", "ring", "time", - "x509-parser 0.14.0", + "x509-parser", "yasna", ] @@ -1992,7 +1928,7 @@ name = "trust_cert" version = "0.0.4" dependencies = [ "nix", - "rcgen 0.9.3", + "rcgen", "windows", ] @@ -2256,15 +2192,17 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.39.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +checksum = "0286ba339aa753e70765d521bb0242cc48e1194562bfa2a2ad7ac8a6de28f5d5" dependencies = [ - "windows_aarch64_msvc 0.39.0", - "windows_i686_gnu 0.39.0", - "windows_i686_msvc 0.39.0", - "windows_x86_64_gnu 0.39.0", - "windows_x86_64_msvc 0.39.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", ] [[package]] @@ -2307,12 +2245,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" -[[package]] -name = "windows_aarch64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" - [[package]] name = "windows_aarch64_msvc" version = "0.42.0" @@ -2325,12 +2257,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" -[[package]] -name = "windows_i686_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" - [[package]] name = "windows_i686_gnu" version = "0.42.0" @@ -2343,12 +2269,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" -[[package]] -name = "windows_i686_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" - [[package]] name = "windows_i686_msvc" version = "0.42.0" @@ -2361,12 +2281,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" -[[package]] -name = "windows_x86_64_gnu" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" - [[package]] name = "windows_x86_64_gnu" version = "0.42.0" @@ -2385,50 +2299,25 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" -[[package]] -name = "windows_x86_64_msvc" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" - [[package]] name = "windows_x86_64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" -[[package]] -name = "x509-parser" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" -dependencies = [ - "asn1-rs 0.3.1", - "base64", - "data-encoding", - "der-parser 7.0.0", - "lazy_static", - "nom", - "oid-registry 0.4.0", - "ring", - "rusticata-macros", - "thiserror", - "time", -] - [[package]] name = "x509-parser" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" dependencies = [ - "asn1-rs 0.5.1", + "asn1-rs", "base64", "data-encoding", - "der-parser 8.1.0", + "der-parser", "lazy_static", "nom", - "oid-registry 0.6.0", + "oid-registry", "ring", "rusticata-macros", "thiserror", diff --git a/crates/trust_cert/Cargo.toml b/crates/trust_cert/Cargo.toml index 33e5c43..a98f3b4 100644 --- a/crates/trust_cert/Cargo.toml +++ b/crates/trust_cert/Cargo.toml @@ -8,10 +8,10 @@ repository = "https://github.com/zu1k/good-mitm" license = "MIT" [dependencies] -rcgen = { version = "0.9", features = ["x509-parser"] } +rcgen = { version = "0.10", features = ["x509-parser"] } [target.'cfg(unix)'.dependencies] nix = { version = "0.25", default-features = false, features = ["user"] } [target.'cfg(windows)'.dependencies] -windows = { version = "0.39", features = ["Win32_Security_Cryptography", "Win32_Foundation"] } +windows = { version = "0.42", features = ["Win32_Security_Cryptography", "Win32_Foundation"] } From 86fb6d748322cc6b952cf2746f3dd98eb2b24e4b Mon Sep 17 00:00:00 2001 From: zu1k Date: Sun, 23 Oct 2022 21:12:36 +0800 Subject: [PATCH 3/5] feat: https support transparent proxy --- crates/core/Cargo.toml | 2 +- crates/core/src/ca.rs | 9 ++--- crates/core/src/lib.rs | 27 ++++++++++++++ crates/core/src/mitm.rs | 83 +++++++++++++++++++++++++++++++++-------- src/main.rs | 29 ++++++++++++-- 5 files changed, 124 insertions(+), 26 deletions(-) diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 5205644..dd29d1a 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -12,7 +12,7 @@ async-trait = "0.1" bytes = { version = "1", features = ["serde"] } cfg-if = "1" http = "0.2" -hyper = { version = "0.14", features = ["client", "http1", "server", "stream", "tcp"] } +hyper = { version = "0.14", features = ["http1", "http2", "server", "stream", "tcp", "runtime"] } hyper-proxy = { version = "0.9" } hyper-rustls = { version = "0.23" } hyper-tls = { version = "0.5", optional = true } diff --git a/crates/core/src/ca.rs b/crates/core/src/ca.rs index e0ef501..8d3b5fa 100644 --- a/crates/core/src/ca.rs +++ b/crates/core/src/ca.rs @@ -146,11 +146,8 @@ impl CertificateAuthority { impl ResolvesServerCert for CertificateAuthority { fn resolve(&self, client_hello: ClientHello) -> Option> { - if let Some(name) = client_hello.server_name() { - Some(self.get_certified_key(name)) - } else { - // This kind of resolver requires SNI - None - } + client_hello + .server_name() + .map(|name| self.get_certified_key(name)) } } diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index be74753..f55c26e 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -9,6 +9,7 @@ use hyper::{ use hyper_proxy::Proxy as UpstreamProxy; use mitm::MitmProxy; use std::{future::Future, marker::PhantomData, net::SocketAddr, sync::Arc}; +use tokio::net::TcpListener; use typed_builder::TypedBuilder; pub use ca::CertificateAuthority; @@ -63,6 +64,8 @@ where let http_handler = Arc::clone(&http_handler); let mitm_filter = Arc::clone(&mitm_filter); + // TODO: conn tls or http? + async move { Ok::<_, Error>(service_fn(move |req| { MitmProxy { @@ -87,4 +90,28 @@ where .await .map_err(Error::from) } + + pub async fn start_https_transparent_proxy(self) -> Result<(), Error> { + let client = gen_client(self.upstream_proxy)?; + let ca = Arc::new(self.ca); + let http_handler = Arc::new(self.handler); + let mitm_filter = Arc::new(MitmFilter::new(self.mitm_filters)); + + let tcp_listener = TcpListener::bind(self.listen_addr).await?; + + loop { + let (tcp_stream, _) = tcp_listener.accept().await?; + MitmProxy { + ca: Arc::clone(&ca), + client: client.clone(), + + http_handler: Arc::clone(&http_handler), + mitm_filter: Arc::clone(&mitm_filter), + + custom_contex_data: Default::default(), + } + .serve_tls(tcp_stream) + .await; + } + } } diff --git a/crates/core/src/mitm.rs b/crates/core/src/mitm.rs index 7e8e18b..bd2b5f1 100644 --- a/crates/core/src/mitm.rs +++ b/crates/core/src/mitm.rs @@ -14,7 +14,10 @@ use hyper::{ }; use log::*; use std::{marker::PhantomData, sync::Arc}; -use tokio::net::TcpStream; +use tokio::{ + io::{AsyncRead, AsyncWrite}, + net::TcpStream, +}; use tokio_rustls::TlsAcceptor; /// Enum representing either an HTTP request or response. @@ -136,6 +139,50 @@ where Ok(res) } + // async fn process_connect(self, req: Request) -> Result, hyper::Error> { + // let ctx = HttpContext { + // uri: None, + // should_modify_response: false, + // ..Default::default() + // }; + + // if self.mitm_filter.filter(&ctx, &req).await { + // tokio::task::spawn(async move { + // let authority = req + // .uri() + // .authority() + // .expect("URI does not contain authority") + // .clone(); + + // match hyper::upgrade::on(req).await { + // Ok(upgraded) => { + // let server_config = self.ca.clone().gen_server_config(); + + // let stream = TlsAcceptor::from(server_config) + // .accept(upgraded) + // .await + // .expect("Failed to establish TLS connection with client"); + + // if let Err(e) = self.serve_tls_stream(stream).await { + // let e_string = e.to_string(); + // if !e_string.starts_with("error shutting down connection") { + // debug!("res:: {}", e); + // } + // } + // } + // Err(e) => debug!("upgrade error for {}: {}", authority, e), + // }; + // }); + // } else { + // tokio::task::spawn(async move { + // let remote_addr = host_addr(req.uri()).unwrap(); + // let upgraded = hyper::upgrade::on(req).await.unwrap(); + // tunnel(upgraded, remote_addr).await + // }); + // } + // Ok(Response::new(Body::empty())) + // } + async fn process_connect(self, req: Request) -> Result, hyper::Error> { let ctx = HttpContext { uri: None, @@ -153,19 +200,7 @@ where match hyper::upgrade::on(req).await { Ok(upgraded) => { - let server_config = self.ca.clone().gen_server_config(); - - let stream = TlsAcceptor::from(server_config) - .accept(upgraded) - .await - .expect("Failed to establish TLS connection with client"); - - if let Err(e) = self.serve_https(stream).await { - let e_string = e.to_string(); - if !e_string.starts_with("error shutting down connection") { - debug!("res:: {}", e); - } - } + self.serve_tls(upgraded).await; } Err(e) => debug!("upgrade error for {}: {}", authority, e), }; @@ -180,9 +215,25 @@ where Ok(Response::new(Body::empty())) } - async fn serve_https( + pub async fn serve_tls(self, stream: IO) { + let server_config = self.ca.clone().gen_server_config(); + + let stream = TlsAcceptor::from(server_config) + .accept(stream) + .await + .expect("Failed to establish TLS connection with client"); + + if let Err(e) = self.serve_tls_stream(stream).await { + let e_string = e.to_string(); + if !e_string.starts_with("error shutting down connection") { + debug!("res:: {}", e); + } + } + } + + async fn serve_tls_stream( self, - stream: tokio_rustls::server::TlsStream, + stream: tokio_rustls::server::TlsStream, ) -> Result<(), hyper::Error> { let service = service_fn(|mut req| { if req.version() == http::Version::HTTP_10 || req.version() == http::Version::HTTP_11 { diff --git a/src/main.rs b/src/main.rs index 3bbe82a..59e322f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use log::*; use mitm_core::{CertificateAuthority, Proxy}; use rule::RuleHttpHandler; use rustls_pemfile as pemfile; -use std::{fs, sync::Arc}; +use std::{fs, net::SocketAddr, sync::Arc}; use good_mitm::*; @@ -97,7 +97,7 @@ async fn run(opts: &Run) -> Result<()> { let http_handler = RuleHttpHandler::new(rules); let proxy = Proxy::builder() - .ca(ca) + .ca(ca.clone()) .listen_addr(opts.bind.parse().expect("bind address not valid!")) .upstream_proxy( opts.proxy @@ -105,9 +105,32 @@ async fn run(opts: &Run) -> Result<()> { .map(|proxy| hyper_proxy::Proxy::new(Intercept::All, proxy.parse().unwrap())), ) .shutdown_signal(shutdown_signal()) + .mitm_filters(mitm_filters.clone()) + .handler(http_handler.clone()) + .build(); + + tokio::spawn(proxy.start_proxy()); + + let mut bind: SocketAddr = opts.bind.parse().expect("bind address not valid!"); + bind.set_port(bind.port() + 1); + info!("Https Transparent Proxy listen on: {}", bind); + let proxy2 = Proxy::builder() + .ca(ca) + .listen_addr(bind) + .upstream_proxy( + opts.proxy + .clone() + .map(|proxy| hyper_proxy::Proxy::new(Intercept::All, proxy.parse().unwrap())), + ) + .shutdown_signal(shutdown_signal()) .mitm_filters(mitm_filters) .handler(http_handler) .build(); - proxy.start_proxy().await?; + + tokio::spawn(proxy2.start_https_transparent_proxy()); + + tokio::signal::ctrl_c() + .await + .expect("failed to listen for event"); Ok(()) } From ba2db24a3a3b9f6d821421ddb667c1f91da97fc0 Mon Sep 17 00:00:00 2001 From: zu1k Date: Sat, 29 Oct 2022 12:42:12 +0800 Subject: [PATCH 4/5] fix: handle errors inside serve_tls --- Cargo.lock | 56 ++++++----- crates/core/src/mitm.rs | 163 ++++++++++---------------------- docs/guide/transparent_proxy.md | 15 +++ 3 files changed, 97 insertions(+), 137 deletions(-) create mode 100644 docs/guide/transparent_proxy.md diff --git a/Cargo.lock b/Cargo.lock index 4cf3731..3723f5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,16 +58,16 @@ dependencies = [ [[package]] name = "async-io" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7" dependencies = [ + "async-lock", "autocfg", "concurrent-queue", "futures-lite", "libc", "log", - "once_cell", "parking", "polling", "slab", @@ -78,11 +78,12 @@ dependencies = [ [[package]] name = "async-lock" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", + "futures-lite", ] [[package]] @@ -736,9 +737,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -967,9 +968,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.135" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libquickjs-sys" @@ -1038,14 +1039,14 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -1234,9 +1235,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.3.0" +version = "6.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9" [[package]] name = "parking" @@ -1290,15 +1291,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "polling" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899b00b9c8ab553c743b3e11e87c5c7d423b2a2de229ba95b24a756344748011" +checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2" dependencies = [ "autocfg", "cfg-if", @@ -1810,21 +1811,32 @@ dependencies = [ [[package]] name = "time" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" +checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" dependencies = [ "itoa", "libc", "num_threads", + "serde", + "time-core", "time-macros", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +dependencies = [ + "time-core", +] [[package]] name = "tokio" diff --git a/crates/core/src/mitm.rs b/crates/core/src/mitm.rs index bd2b5f1..b5b8870 100644 --- a/crates/core/src/mitm.rs +++ b/crates/core/src/mitm.rs @@ -3,11 +3,7 @@ use crate::{ handler::{CustomContextData, HttpHandler, MitmFilter}, http_client::HttpClient, }; -use http::{ - header, - uri::{PathAndQuery, Scheme}, - HeaderValue, Uri, -}; +use http::{header, uri::Scheme, HeaderValue, Uri}; use hyper::{ body::HttpBody, server::conn::Http, service::service_fn, upgrade::Upgraded, Body, Method, Request, Response, @@ -60,7 +56,7 @@ where let res = if req.method() == Method::CONNECT { self.process_connect(req).await } else { - self.process_request(req).await + self.process_request(req, Scheme::HTTP).await }; match res { @@ -75,34 +71,39 @@ where } } - async fn process_request(self, mut req: Request) -> Result, hyper::Error> { + async fn process_request( + self, + mut req: Request, + scheme: Scheme, + ) -> Result, hyper::Error> { + if req.uri().path().starts_with("/mitm/cert") { + return Ok(self.get_cert_res()); + } + let mut ctx = HttpContext { uri: None, should_modify_response: false, ..Default::default() }; - let host = req - .headers() - .get(http::header::HOST) - .map(|h| h.to_str()) - .unwrap() - .map(|h| h.to_owned()) - .unwrap_or_default(); - - let uri = req.uri_mut(); - if uri.authority().is_none() { - *uri = http::uri::Uri::builder() - .scheme(uri.scheme().unwrap_or(&Scheme::HTTP).as_str()) - .authority(host.as_str()) - .path_and_query(uri.path_and_query().map_or("/", |p| p.as_str())) - .build() - .unwrap(); - } + // if req.uri().authority().is_none() { + if req.version() == http::Version::HTTP_10 || req.version() == http::Version::HTTP_11 { + let (mut parts, body) = req.into_parts(); + + if let Some(Ok(authority)) = parts + .headers + .get(http::header::HOST) + .map(|host| host.to_str()) + { + let mut uri = parts.uri.into_parts(); + uri.scheme = Some(scheme.clone()); + uri.authority = authority.try_into().ok(); + parts.uri = Uri::from_parts(uri).expect("build uri"); + } - if req.uri().path().starts_with("/mitm/cert") || host.contains("cert.mitm") { - return Ok(self.get_cert_res()); - } + req = Request::from_parts(parts, body); + }; + // } let mut req = match self.http_handler.handle_request(&mut ctx, req).await { RequestOrResponse::Request(req) => req, @@ -111,7 +112,7 @@ where { let header_mut = req.headers_mut(); - // header_mut.remove(http::header::HOST); + header_mut.remove(http::header::HOST); header_mut.remove(http::header::ACCEPT_ENCODING); header_mut.remove(http::header::CONTENT_LENGTH); } @@ -139,50 +140,6 @@ where Ok(res) } - // async fn process_connect(self, req: Request) -> Result, hyper::Error> { - // let ctx = HttpContext { - // uri: None, - // should_modify_response: false, - // ..Default::default() - // }; - - // if self.mitm_filter.filter(&ctx, &req).await { - // tokio::task::spawn(async move { - // let authority = req - // .uri() - // .authority() - // .expect("URI does not contain authority") - // .clone(); - - // match hyper::upgrade::on(req).await { - // Ok(upgraded) => { - // let server_config = self.ca.clone().gen_server_config(); - - // let stream = TlsAcceptor::from(server_config) - // .accept(upgraded) - // .await - // .expect("Failed to establish TLS connection with client"); - - // if let Err(e) = self.serve_tls_stream(stream).await { - // let e_string = e.to_string(); - // if !e_string.starts_with("error shutting down connection") { - // debug!("res:: {}", e); - // } - // } - // } - // Err(e) => debug!("upgrade error for {}: {}", authority, e), - // }; - // }); - // } else { - // tokio::task::spawn(async move { - // let remote_addr = host_addr(req.uri()).unwrap(); - // let upgraded = hyper::upgrade::on(req).await.unwrap(); - // tunnel(upgraded, remote_addr).await - // }); - // } - // Ok(Response::new(Body::empty())) - // } - async fn process_connect(self, req: Request) -> Result, hyper::Error> { let ctx = HttpContext { uri: None, @@ -218,54 +175,30 @@ where pub async fn serve_tls(self, stream: IO) { let server_config = self.ca.clone().gen_server_config(); - let stream = TlsAcceptor::from(server_config) - .accept(stream) - .await - .expect("Failed to establish TLS connection with client"); - - if let Err(e) = self.serve_tls_stream(stream).await { - let e_string = e.to_string(); - if !e_string.starts_with("error shutting down connection") { - debug!("res:: {}", e); + match TlsAcceptor::from(server_config).accept(stream).await { + Ok(stream) => { + if let Err(e) = self.serve_stream(stream, Scheme::HTTPS).await { + let e_string = e.to_string(); + if !e_string.starts_with("error shutting down connection") { + debug!("res:: {}", e); + } + } + } + Err(err) => { + error!("Tls accept failed: {err}") } } } - async fn serve_tls_stream( - self, - stream: tokio_rustls::server::TlsStream, - ) -> Result<(), hyper::Error> { - let service = service_fn(|mut req| { - if req.version() == http::Version::HTTP_10 || req.version() == http::Version::HTTP_11 { - let authority = req - .headers() - .get(http::header::HOST) - .expect("Host is a required header") - .to_str() - .expect("Failed to convert host to str"); - - let uri = http::uri::Builder::new() - .scheme(http::uri::Scheme::HTTPS) - .authority(authority) - .path_and_query( - req.uri() - .path_and_query() - .unwrap_or(&PathAndQuery::from_static("/")) - .to_owned(), - ) - .build() - .expect("Failed to build URI"); - - let (mut parts, body) = req.into_parts(); - parts.uri = uri; - req = Request::from_parts(parts, body) - }; - - self.clone().process_request(req) - }); - + async fn serve_stream(self, stream: S, scheme: Scheme) -> Result<(), hyper::Error> + where + S: AsyncRead + AsyncWrite + Unpin + Send + 'static, + { Http::new() - .serve_connection(stream, service) + .serve_connection( + stream, + service_fn(|req| self.clone().process_request(req, scheme.clone())), + ) .with_upgrades() .await } diff --git a/docs/guide/transparent_proxy.md b/docs/guide/transparent_proxy.md new file mode 100644 index 0000000..498d214 --- /dev/null +++ b/docs/guide/transparent_proxy.md @@ -0,0 +1,15 @@ +# 透明代理 + +See https://docs.mitmproxy.org/stable/howto-transparent/ for docs. + +```shell +sudo sysctl -w net.ipv4.ip_forward=1 +sudo sysctl -w net.ipv6.conf.all.forwarding=1 +sudo sysctl -w net.ipv4.conf.all.send_redirects=0 + +sudo useradd --create-home mitm +sudo -u mitm -H bash -c 'good-mitm run -r rules/log.yaml -b 0.0.0.0:8080' + +iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 80 -j REDIRECT --to-port 8080 +iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 443 -j REDIRECT --to-port 8081 +``` From 18a6cd453133c2788f498132c9eb372804ae784a Mon Sep 17 00:00:00 2001 From: zu1k Date: Sat, 29 Oct 2022 13:32:06 +0800 Subject: [PATCH 5/5] fix: block on tcp loop --- crates/core/src/lib.rs | 67 +++++++++------------------------ crates/core/src/mitm.rs | 25 ++++++++---- docs/_sidebar.md | 1 + docs/guide/transparent_proxy.md | 6 +-- src/main.rs | 20 +--------- 5 files changed, 41 insertions(+), 78 deletions(-) diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index f55c26e..6b52977 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,11 +1,6 @@ use error::Error; use handler::{CustomContextData, HttpHandler, MitmFilter}; use http_client::gen_client; -use hyper::{ - server::conn::AddrStream, - service::{make_service_fn, service_fn}, - Server, -}; use hyper_proxy::Proxy as UpstreamProxy; use mitm::MitmProxy; use std::{future::Future, marker::PhantomData, net::SocketAddr, sync::Arc}; @@ -54,64 +49,38 @@ where pub async fn start_proxy(self) -> Result<(), Error> { let client = gen_client(self.upstream_proxy)?; let ca = Arc::new(self.ca); - let http_handler = Arc::new(self.handler); let mitm_filter = Arc::new(MitmFilter::new(self.mitm_filters)); - let make_service = make_service_fn(move |_conn: &AddrStream| { + let tcp_listener = TcpListener::bind(self.listen_addr).await?; + loop { let client = client.clone(); let ca = Arc::clone(&ca); let http_handler = Arc::clone(&http_handler); let mitm_filter = Arc::clone(&mitm_filter); - // TODO: conn tls or http? - - async move { - Ok::<_, Error>(service_fn(move |req| { - MitmProxy { - ca: Arc::clone(&ca), + if let Ok((tcp_stream, _)) = tcp_listener.accept().await { + tokio::spawn(async move { + let mitm_proxy = MitmProxy { + ca: ca.clone(), client: client.clone(), - http_handler: Arc::clone(&http_handler), mitm_filter: Arc::clone(&mitm_filter), - custom_contex_data: Default::default(), + }; + + let mut tls_content_type = [0; 1]; + if tcp_stream.peek(&mut tls_content_type).await.is_ok() { + if tls_content_type[0] <= 0x40 { + // ASCII < 'A', assuming tls + mitm_proxy.serve_tls(tcp_stream).await; + } else { + // assuming http + _ = mitm_proxy.serve_stream(tcp_stream).await; + } } - .proxy(req) - })) - } - }); - - Server::bind(&self.listen_addr) - .http1_preserve_header_case(true) - .http1_title_case_headers(true) - .serve(make_service) - .with_graceful_shutdown(self.shutdown_signal) - .await - .map_err(Error::from) - } - - pub async fn start_https_transparent_proxy(self) -> Result<(), Error> { - let client = gen_client(self.upstream_proxy)?; - let ca = Arc::new(self.ca); - let http_handler = Arc::new(self.handler); - let mitm_filter = Arc::new(MitmFilter::new(self.mitm_filters)); - - let tcp_listener = TcpListener::bind(self.listen_addr).await?; - - loop { - let (tcp_stream, _) = tcp_listener.accept().await?; - MitmProxy { - ca: Arc::clone(&ca), - client: client.clone(), - - http_handler: Arc::clone(&http_handler), - mitm_filter: Arc::clone(&mitm_filter), - - custom_contex_data: Default::default(), + }); } - .serve_tls(tcp_stream) - .await; } } } diff --git a/crates/core/src/mitm.rs b/crates/core/src/mitm.rs index b5b8870..b0c9025 100644 --- a/crates/core/src/mitm.rs +++ b/crates/core/src/mitm.rs @@ -52,7 +52,10 @@ where H: HttpHandler, D: CustomContextData, { - pub(crate) async fn proxy(self, req: Request) -> Result, hyper::Error> { + pub(crate) async fn proxy_req( + self, + req: Request, + ) -> Result, hyper::Error> { let res = if req.method() == Method::CONNECT { self.process_connect(req).await } else { @@ -177,7 +180,16 @@ where match TlsAcceptor::from(server_config).accept(stream).await { Ok(stream) => { - if let Err(e) = self.serve_stream(stream, Scheme::HTTPS).await { + if let Err(e) = Http::new() + .http1_preserve_header_case(true) + .http1_title_case_headers(true) + .serve_connection( + stream, + service_fn(|req| self.clone().process_request(req, Scheme::HTTPS)), + ) + .with_upgrades() + .await + { let e_string = e.to_string(); if !e_string.starts_with("error shutting down connection") { debug!("res:: {}", e); @@ -190,15 +202,14 @@ where } } - async fn serve_stream(self, stream: S, scheme: Scheme) -> Result<(), hyper::Error> + pub async fn serve_stream(self, stream: S) -> Result<(), hyper::Error> where S: AsyncRead + AsyncWrite + Unpin + Send + 'static, { Http::new() - .serve_connection( - stream, - service_fn(|req| self.clone().process_request(req, scheme.clone())), - ) + .http1_preserve_header_case(true) + .http1_title_case_headers(true) + .serve_connection(stream, service_fn(|req| self.clone().proxy_req(req))) .with_upgrades() .await } diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 174bb3c..5ac0b37 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -1,6 +1,7 @@ * [介绍](/) * [指南](guide/README.md) * [证书准备](guide/0_cert.md) + * [透明代理](guide/transparent_proxy.md) * [Rule 规则](rule/README.md) * [Filter 筛选器](rule/filter.md) * [Action 动作](rule/action.md) diff --git a/docs/guide/transparent_proxy.md b/docs/guide/transparent_proxy.md index 498d214..fc67087 100644 --- a/docs/guide/transparent_proxy.md +++ b/docs/guide/transparent_proxy.md @@ -8,8 +8,8 @@ sudo sysctl -w net.ipv6.conf.all.forwarding=1 sudo sysctl -w net.ipv4.conf.all.send_redirects=0 sudo useradd --create-home mitm -sudo -u mitm -H bash -c 'good-mitm run -r rules/log.yaml -b 0.0.0.0:8080' +sudo -u mitm -H bash -c 'good-mitm run -r rules/log.yaml -b 0.0.0.0:34567' -iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 80 -j REDIRECT --to-port 8080 -iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 443 -j REDIRECT --to-port 8081 +iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 80 -j REDIRECT --to-port 34567 +iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 443 -j REDIRECT --to-port 34567 ``` diff --git a/src/main.rs b/src/main.rs index 59e322f..f244ca2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use log::*; use mitm_core::{CertificateAuthority, Proxy}; use rule::RuleHttpHandler; use rustls_pemfile as pemfile; -use std::{fs, net::SocketAddr, sync::Arc}; +use std::{fs, sync::Arc}; use good_mitm::*; @@ -111,24 +111,6 @@ async fn run(opts: &Run) -> Result<()> { tokio::spawn(proxy.start_proxy()); - let mut bind: SocketAddr = opts.bind.parse().expect("bind address not valid!"); - bind.set_port(bind.port() + 1); - info!("Https Transparent Proxy listen on: {}", bind); - let proxy2 = Proxy::builder() - .ca(ca) - .listen_addr(bind) - .upstream_proxy( - opts.proxy - .clone() - .map(|proxy| hyper_proxy::Proxy::new(Intercept::All, proxy.parse().unwrap())), - ) - .shutdown_signal(shutdown_signal()) - .mitm_filters(mitm_filters) - .handler(http_handler) - .build(); - - tokio::spawn(proxy2.start_https_transparent_proxy()); - tokio::signal::ctrl_c() .await .expect("failed to listen for event");