From 55c1aa320560192b97accfba1b7bd044307370c2 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sat, 30 Mar 2024 15:37:26 +0800 Subject: [PATCH] feat: config works --- Cargo.lock | 771 +++++++++++++++++++++++++++++++++++++++++----- Cargo.toml | 4 + proxy_config.json | 18 ++ src/app.rs | 75 ++++- src/cert.rs | 74 ++--- src/config.rs | 46 +++ src/main.rs | 74 +++-- src/service.rs | 64 +++- 8 files changed, 944 insertions(+), 182 deletions(-) create mode 100644 proxy_config.json create mode 100644 src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 014ca40..8a8ea2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "getrandom", "once_cell", "version_check", @@ -66,7 +66,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -155,7 +155,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -172,7 +172,7 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -266,6 +266,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "bytes" version = "1.6.0" @@ -282,6 +292,12 @@ dependencies = [ "libc", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -312,6 +328,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "cmake" version = "0.1.50" @@ -358,7 +383,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -367,7 +392,44 @@ version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.8.19", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils 0.7.2", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "lazy_static", + "maybe-uninit", + "memoffset 0.5.6", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "maybe-uninit", ] [[package]] @@ -376,7 +438,18 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.8.19", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "lazy_static", ] [[package]] @@ -530,7 +603,19 @@ version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.55", ] [[package]] @@ -603,6 +688,28 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + [[package]] name = "futures" version = "0.3.30" @@ -634,6 +741,16 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +dependencies = [ + "futures 0.1.31", + "num_cpus", +] + [[package]] name = "futures-executor" version = "0.3.30" @@ -709,7 +826,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -737,7 +854,7 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "futures-core", "futures-sink", @@ -745,7 +862,7 @@ dependencies = [ "http 0.2.12", "indexmap 2.2.6", "slab", - "tokio", + "tokio 1.36.0", "tokio-util", "tracing", ] @@ -756,7 +873,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "futures-core", "futures-sink", @@ -764,7 +881,7 @@ dependencies = [ "http 1.1.0", "indexmap 2.2.6", "slab", - "tokio", + "tokio 1.36.0", "tokio-util", "tracing", ] @@ -794,6 +911,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -841,7 +964,7 @@ checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -850,7 +973,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "itoa", ] @@ -861,7 +984,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "itoa", ] @@ -872,7 +995,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes", + "bytes 1.6.0", "http 0.2.12", "pin-project-lite", ] @@ -901,7 +1024,7 @@ version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-channel", "futures-core", "futures-util", @@ -913,7 +1036,7 @@ dependencies = [ "itoa", "pin-project-lite", "socket2", - "tokio", + "tokio 1.36.0", "tower-service", "tracing", "want", @@ -929,10 +1052,20 @@ dependencies = [ "http 0.2.12", "hyper", "rustls", - "tokio", + "tokio 1.36.0", "tokio-rustls", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.5.0" @@ -963,6 +1096,27 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1004,6 +1158,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1032,6 +1196,15 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + [[package]] name = "lock_api" version = "0.4.11" @@ -1057,18 +1230,42 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "match_cfg" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -1099,6 +1296,25 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.8.11" @@ -1110,6 +1326,40 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio-uds" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +dependencies = [ + "iovec", + "libc", + "mio 0.6.23", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nix" version = "0.24.3" @@ -1117,9 +1367,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -1208,7 +1458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -1293,14 +1543,40 @@ dependencies = [ "sha2", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api 0.3.4", + "parking_lot_core 0.6.3", + "rustc_version 0.2.3", +] + [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "lock_api", - "parking_lot_core", + "lock_api 0.4.11", + "parking_lot_core 0.9.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "rustc_version 0.2.3", + "smallvec 0.6.14", + "winapi 0.3.9", ] [[package]] @@ -1309,10 +1585,10 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "redox_syscall", - "smallvec", + "redox_syscall 0.4.1", + "smallvec 1.13.2", "windows-targets 0.48.5", ] @@ -1380,7 +1656,7 @@ dependencies = [ "ahash", "async-trait", "blake2", - "bytes", + "bytes 1.6.0", "hex", "http 1.1.0", "httparse", @@ -1389,7 +1665,7 @@ dependencies = [ "log", "lru", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "pingora-core", "pingora-error", "pingora-header-serde", @@ -1402,7 +1678,7 @@ dependencies = [ "rustracing", "rustracing_jaeger", "serde", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -1414,11 +1690,11 @@ dependencies = [ "ahash", "async-trait", "brotli", - "bytes", + "bytes 1.6.0", "chrono", "daemonize", "flate2", - "futures", + "futures 0.3.30", "h2 0.4.3", "http 1.1.0", "httparse", @@ -1428,7 +1704,7 @@ dependencies = [ "nix", "once_cell", "openssl-probe", - "parking_lot", + "parking_lot 0.12.1", "percent-encoding", "pingora-error", "pingora-http", @@ -1446,7 +1722,7 @@ dependencies = [ "socket2", "structopt", "thread_local", - "tokio", + "tokio 1.36.0", "tokio-test", "unicase", "zstd", @@ -1464,7 +1740,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97a107e28eb684fe3eac77bcd9ba6921637a6b8b0fa407e8ab1325bbbca705c3" dependencies = [ - "bytes", + "bytes 1.6.0", "http 1.1.0", "httparse", "pingora-error", @@ -1480,7 +1756,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9a47b70126f169be9b5ee3e4824f316fa8414b0ece0eb4eb458eca585f0a3e7" dependencies = [ - "bytes", + "bytes 1.6.0", "http 1.1.0", "pingora-error", ] @@ -1493,7 +1769,7 @@ checksum = "d442809e32d8751d86022bb1f22919508c412c2a943d59a50b8e07b61c4429ef" dependencies = [ "arrayvec", "hashbrown 0.14.3", - "parking_lot", + "parking_lot 0.12.1", "rand", ] @@ -1517,13 +1793,13 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4569e3bef52b0abab239a5cf3287c71307615ca61be7fc7799d71fdaab33d81" dependencies = [ - "crossbeam-queue", + "crossbeam-queue 0.3.11", "log", "lru", - "parking_lot", + "parking_lot 0.12.1", "pingora-timeout", "thread_local", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -1533,8 +1809,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "965df1dcaace662fcac63315123e55294bd6dd6459f20184d6fcb0c3405b30f8" dependencies = [ "async-trait", - "bytes", - "futures", + "bytes 1.6.0", + "futures 0.3.30", "h2 0.4.3", "http 1.1.0", "log", @@ -1546,7 +1822,7 @@ dependencies = [ "pingora-timeout", "regex", "structopt", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -1558,7 +1834,7 @@ dependencies = [ "once_cell", "rand", "thread_local", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -1567,12 +1843,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0be182194d34e1b28608eaa49ee0fb86e5b7ab1d21a1d7a2b4d402446fda47e1" dependencies = [ - "futures", + "futures 0.3.30", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "thread_local", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -1661,11 +1937,11 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fnv", "lazy_static", "memchr", - "parking_lot", + "parking_lot 0.12.1", "protobuf", "thiserror", ] @@ -1682,7 +1958,7 @@ version = "0.1.0" dependencies = [ "async-trait", "base64 0.22.0", - "bytes", + "bytes 1.6.0", "http 1.1.0", "log", "once_cell", @@ -1692,11 +1968,21 @@ dependencies = [ "pingora", "pretty_env_logger", "rcgen", + "serde", + "serde_json", "structopt", "time", - "tokio", + "tokio 1.36.0", + "tokio-dns-unofficial", + "trust-dns-resolver", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.35" @@ -1750,6 +2036,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1795,7 +2087,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", - "bytes", + "bytes 1.6.0", "encoding_rs", "futures-core", "futures-util", @@ -1818,7 +2110,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "system-configuration", - "tokio", + "tokio 1.36.0", "tokio-rustls", "tower-service", "url", @@ -1829,6 +2121,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -1851,7 +2153,7 @@ dependencies = [ "spin 0.5.2", "untrusted 0.7.1", "web-sys", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1861,7 +2163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.0", "getrandom", "libc", "spin 0.9.8", @@ -1907,13 +2209,22 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.22", ] [[package]] @@ -2019,12 +2330,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "sentry" version = "0.26.0" @@ -2037,7 +2363,7 @@ dependencies = [ "sentry-contexts", "sentry-core", "sentry-panic", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -2060,7 +2386,7 @@ checksum = "db80ceff16bb1a4b2689b8758e5e61e405fc4d8ff9f2d1b5b845b76ce37fa34e" dependencies = [ "hostname", "libc", - "rustc_version", + "rustc_version 0.4.0", "sentry-core", "uname", ] @@ -2127,9 +2453,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -2177,7 +2503,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -2210,6 +2536,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -2271,7 +2606,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -2389,7 +2724,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -2449,6 +2784,30 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "mio 0.6.23", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", +] + [[package]] name = "tokio" version = "1.36.0" @@ -2456,9 +2815,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", - "bytes", + "bytes 1.6.0", "libc", - "mio", + "mio 0.8.11", "num_cpus", "pin-project-lite", "signal-hook-registry", @@ -2467,6 +2826,71 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "tokio-io", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures 0.1.31", + "tokio-executor", +] + +[[package]] +name = "tokio-dns-unofficial" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" +dependencies = [ + "futures 0.1.31", + "futures-cpupool", + "lazy_static", + "tokio 0.1.22", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", +] + +[[package]] +name = "tokio-fs" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +dependencies = [ + "futures 0.1.31", + "tokio-io", + "tokio-threadpool", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "log", +] + [[package]] name = "tokio-macros" version = "2.2.0" @@ -2487,7 +2911,26 @@ dependencies = [ "futures-util", "openssl", "openssl-sys", - "tokio", + "tokio 1.36.0", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "lazy_static", + "log", + "mio 0.6.23", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", ] [[package]] @@ -2497,7 +2940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", - "tokio", + "tokio 1.36.0", ] [[package]] @@ -2508,7 +2951,31 @@ checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", - "tokio", + "tokio 1.36.0", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures 0.1.31", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "iovec", + "mio 0.6.23", + "tokio-io", + "tokio-reactor", ] [[package]] @@ -2518,23 +2985,85 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" dependencies = [ "async-stream", - "bytes", + "bytes 1.6.0", "futures-core", - "tokio", + "tokio 1.36.0", "tokio-stream", ] +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue 0.2.3", + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "lazy_static", + "log", + "num_cpus", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures 0.1.31", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "log", + "mio 0.6.23", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-uds" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "iovec", + "libc", + "log", + "mio 0.6.23", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + [[package]] name = "tokio-util" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-core", "futures-sink", "pin-project-lite", - "tokio", + "tokio 1.36.0", "tracing", ] @@ -2551,9 +3080,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -2592,6 +3133,52 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "trust-dns-proto" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "smallvec 1.13.2", + "thiserror", + "tinyvec", + "tokio 1.36.0", + "tracing", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" +dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot 0.12.1", + "rand", + "resolv-conf", + "smallvec 1.13.2", + "thiserror", + "tokio 1.36.0", + "tracing", + "trust-dns-proto", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -2680,7 +3267,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -2734,7 +3321,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -2759,7 +3346,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -2810,6 +3397,18 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -2820,6 +3419,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2832,7 +3437,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2979,10 +3584,20 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "x509-parser" version = "0.15.1" diff --git a/Cargo.toml b/Cargo.toml index 17799fc..cf12606 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,7 @@ p384 = "0.13.0" p521 = "0.13.3" once_cell = "1.19.0" bytes = "1.6.0" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" +tokio-dns-unofficial = "0.4.0" +trust-dns-resolver = { version = "0.23.2", features = ["tokio"] } diff --git a/proxy_config.json b/proxy_config.json new file mode 100644 index 0000000..f9dd51f --- /dev/null +++ b/proxy_config.json @@ -0,0 +1,18 @@ +{ + "groups": [ + { + "port": 4430, + "lookup_dns": true, + "tls": { + "intermediate_cert": "__ignore_intermediate_cert.pem", + "intermediate_key": "__ignore_intermediate_pri_key.pem" + }, + "proxy_map": { + "hatter.ink": { + "address": "101.132.122.240:443", + "tls": true + } + } + } + ] +} \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index 037690a..297ebaf 100644 --- a/src/app.rs +++ b/src/app.rs @@ -6,16 +6,54 @@ use http::HeaderName; use pingora::{Error, ErrorType}; use pingora::http::ResponseHeader; use pingora::prelude::{HttpPeer, ProxyHttp, Result, Session}; +use trust_dns_resolver::config::{ResolverConfig, ResolverOpts}; +use trust_dns_resolver::proto::rr::RData; +use trust_dns_resolver::TokioAsyncResolver; use super::service::HostConfig; pub struct ProxyApp { + tls: bool, + lookup_dns: bool, host_configs: Vec, + tokio_async_resolver: TokioAsyncResolver, } impl ProxyApp { - pub fn new(host_configs: Vec) -> Self { - ProxyApp { host_configs } + pub fn new(tls: bool, lookup_dns: bool, host_configs: Vec) -> Self { + let tokio_async_resolver = TokioAsyncResolver::tokio( + ResolverConfig::default(), + ResolverOpts::default(), + ); + ProxyApp { + tls, + lookup_dns, + host_configs, + tokio_async_resolver, + } + } + + async fn lookup_ipv4(&self, hostname: &str) -> Option { + let ips = self.tokio_async_resolver.ipv4_lookup(hostname).await; + log::debug!("lookup {} --> {:#?}", hostname, ips); + match ips { + Ok(ips) => { + let records = ips.as_lookup().records(); + if records.len() > 0 { + let record = &records[0]; + if let Some(rdata) = record.data() { + match rdata { + RData::A(a) => { + return Some(a.0.to_string()); + } + _ => {} + } + } + } + } + Err(_) => {} + } + None } } @@ -45,15 +83,30 @@ impl ProxyHttp for ProxyApp { let host_config = self .host_configs .iter() - .find(|x| x.proxy_hostname == hostname) - .unwrap_or_else(|| panic!("find config for: {} failed", hostname)); - let peer = HttpPeer::new( - host_config.proxy_addr.as_str(), - host_config.proxy_tls, - host_config.proxy_hostname.clone(), - ); - log::info!("Find peer: {:?}", peer._address); - Ok(Box::new(peer)) + .find(|x| x.proxy_hostname == hostname); + if let Some(host_config) = host_config { + let peer = HttpPeer::new( + host_config.proxy_addr.as_str(), + host_config.proxy_tls, + host_config.proxy_hostname.clone(), + ); + log::info!("Find peer: {} --> {:?}", hostname, host_config.proxy_addr); + return Ok(Box::new(peer)); + } + + if self.lookup_dns { + if let Some(address) = self.lookup_ipv4(&hostname).await { + let peer = HttpPeer::new( + format!("{}:{}", address, if self.tls { 443 } else { 80 }), + self.tls, + hostname.to_string(), + ); + log::info!("Find peer: {} --> {:?}", hostname, address); + return Ok(Box::new(peer)); + } + } + + panic!("Cannot find peer: {}", hostname); } async fn request_filter(&self, session: &mut Session, _ctx: &mut Self::CTX) -> Result diff --git a/src/cert.rs b/src/cert.rs index b2821d6..950537a 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -1,61 +1,35 @@ -use std::collections::HashMap; use std::fs; -use once_cell::sync::Lazy; use rcgen::{Certificate, CertificateParams, DnType, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose}; use time::{Duration, OffsetDateTime}; -use tokio::sync::RwLock; - -const INTERMEDIATE_CERT_ENV_VAR: &str = "INTERMEDIATE_CERT"; -const INTERMEDIATE_KEY_ENV_VAR: &str = "INTERMEDIATE_KEY"; - -static INTERMEDIATE_CA: Lazy<(Certificate, String)> = Lazy::new(|| { - let cert_fn = std::env::var(INTERMEDIATE_CERT_ENV_VAR) - .unwrap_or("__ignore_intermediate_cert.pem".to_string()); - let key_fn = std::env::var(INTERMEDIATE_KEY_ENV_VAR) - .unwrap_or("__ignore_intermediate_pri_key.pem".to_string()); - let cert_pem = fs::read_to_string(cert_fn).expect("Read cert file failed"); - let key_pem = fs::read_to_string(key_fn).expect("Read key file failed"); - let key_pem = parse_pkcs8(&key_pem); - let key_pair = KeyPair::from_pem(&key_pem).expect("Parse keypair failed"); - // 底层逻辑限制,P256 与 SHA256 搭配,P384 与 SHA384 搭配 - let certificate_params = CertificateParams::from_ca_cert_pem(&cert_pem, key_pair) - .expect("Cert and keypair mismatch"); - let cert = Certificate::from_params(certificate_params) - .expect("Parse cert params failed"); - (cert, cert_pem) -}); #[derive(Debug, Clone)] pub struct Cert { pub cert_pem: String, - pub intermediate_pem: String, pub key_pem: String, } -static CERTIFICATE_CACHE_MAP: Lazy>> = Lazy::new(|| { - RwLock::new(HashMap::new()) -}); +pub fn load_certificate(cert_fn: &str, key_fn: &str) -> Result<(Certificate, String), String> { + let cert_pem = fs::read_to_string(cert_fn).map_err(|e| format!("Read file: {} failed: {}", cert_fn, e))?; + let key_pem = fs::read_to_string(key_fn).map_err(|e| format!("Read file: {} failed: {}", key_fn, e))?; + let key_pem = parse_pkcs8(&key_pem); + let key_pair = KeyPair::from_pem(&key_pem).map_err(|e| format!("Parse key: {} failed: {}", key_fn, e))?; + // 底层逻辑限制,P256 与 SHA256 搭配,P384 与 SHA384 搭配 + let certificate_params = CertificateParams::from_ca_cert_pem(&cert_pem, key_pair) + .map_err(|e| format!("Cert and keypair match failed: {}", e))?; + let cert = Certificate::from_params(certificate_params) + .map_err(|e| format!("Parse cert params failed: {}", e))?; + Ok((cert, cert_pem)) +} -pub async fn issue_certificate(domain: &str) -> Cert { - { - if let Some(cert) = CERTIFICATE_CACHE_MAP.read().await.get(domain) { - return cert.clone(); - } - } - let cert = new_end_entity(domain); - let cert_pem = cert.serialize_pem_with_signer(&INTERMEDIATE_CA.0).expect("Sign cert failed"); +pub fn issue_certificate(intermediate_certificate: &Certificate, domain: &str) -> Result { + let cert = new_end_entity(domain)?; + let cert_pem = cert.serialize_pem_with_signer(intermediate_certificate).map_err(|e| format!("Sign cert failed: {}", e))?; let key_pem = cert.serialize_private_key_pem(); - let intermediate_pem = INTERMEDIATE_CA.1.clone(); - let cert = Cert { + Ok(Cert { cert_pem, - intermediate_pem, key_pem, - }; - { - CERTIFICATE_CACHE_MAP.write().await.insert(domain.to_string(), cert.clone()); - } - cert + }) } fn parse_pkcs8(pem: &str) -> String { @@ -89,9 +63,9 @@ fn parse_pkcs8(pem: &str) -> String { pem.to_string() } -fn new_end_entity(domain: &str) -> Certificate { +fn new_end_entity(domain: &str) -> Result { let mut params = CertificateParams::new(vec![domain.into()]); - let (start, end) = validity_period(); + let (start, end) = validity_period()?; params.distinguished_name.push(DnType::CommonName, domain); params.use_authority_key_identifier_extension = true; params.key_usages.push(KeyUsagePurpose::DigitalSignature); @@ -100,11 +74,11 @@ fn new_end_entity(domain: &str) -> Certificate { params.extended_key_usages.push(ExtendedKeyUsagePurpose::ClientAuth); params.not_before = start; params.not_after = end; - Certificate::from_params(params).expect("Generate domain certificate failed") + Ok(Certificate::from_params(params).map_err(|e| format!("New cert failed: {}", e))?) } -fn validity_period() -> (OffsetDateTime, OffsetDateTime) { - let start = OffsetDateTime::now_utc().checked_sub(Duration::hours(1)).unwrap(); - let end = OffsetDateTime::now_utc().checked_add(Duration::days(90)).unwrap(); - (start, end) +fn validity_period() -> Result<(OffsetDateTime, OffsetDateTime), String> { + let start = OffsetDateTime::now_utc().checked_sub(Duration::hours(1)).expect("SHOULD NOT HAPPEN!"); + let end = OffsetDateTime::now_utc().checked_add(Duration::days(90)).expect("SHOULD NOT HAPPEN!"); + Ok((start, end)) } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..e40a2e0 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,46 @@ +use std::collections::HashMap; +use std::fs; + +use serde::Deserialize; +use serde::Serialize; + +#[derive(Debug, Serialize, Deserialize)] +pub struct ProxyConfig { + pub prometheus: Option, + pub groups: Vec, +} + +impl ProxyConfig { + pub fn load(file_name: &str) -> Result { + let file_content = match fs::read_to_string(file_name) { + Ok(file_content) => file_content, + Err(e) => return Err(format!("read file: {} failed: {}", file_name, e)), + }; + let proxy_config: ProxyConfig = match serde_json::from_str(&file_content) { + Ok(proxy_config) => proxy_config, + Err(e) => return Err(format!("parse file: {} failed: {}", file_name, e)), + }; + Ok(proxy_config) + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ProxyGroup { + pub port: u16, + pub lookup_dns: Option, + pub tls: Option, + pub proxy_map: Option>, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ProxyItem { + pub address: String, + pub tls: Option, + pub sni: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ProxyTls { + pub intermediate_cert: String, + pub intermediate_key: String, +} diff --git a/src/main.rs b/src/main.rs index 02677da..a09ec36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,11 +6,13 @@ use pingora::{ use pretty_env_logger::env_logger::Builder; use structopt::StructOpt; +use crate::config::ProxyConfig; use crate::service::HostConfig; mod app; mod service; mod cert; +mod config; pub fn main() { init_logger(); @@ -19,38 +21,54 @@ pub fn main() { let mut my_server = Server::new(opt).unwrap(); my_server.bootstrap(); - let proxy_service_tcp = service::proxy_service_tcp( - &my_server.configuration, - "0.0.0.0:8800", - vec![], - ); + let proxy_config = ProxyConfig::load("proxy_config.json").unwrap_or_else(|e| { + panic!("Load proxy_config.json failed: {}", e); + }); - let proxy_service_ssl2 = service::proxy_service_tls( - &my_server.configuration, - "0.0.0.0:4430", - vec![ - HostConfig { - proxy_addr: "101.132.122.240:443".to_owned(), - proxy_tls: true, - proxy_hostname: "hatter.ink".to_owned(), - }, - HostConfig { - proxy_addr: "1.1.1.1:443".to_owned(), - proxy_tls: true, - proxy_hostname: "one.one.one.one".to_owned(), - }, - ], - ); + let mut services: Vec> = vec![]; + for group in &proxy_config.groups { + let listen_address = format!("0.0.0.0:{}", group.port); + let mut host_configs = vec![]; + if let Some(proxy_map) = &group.proxy_map { + for (hostname, proxy_item) in proxy_map { + host_configs.push(HostConfig { + proxy_addr: proxy_item.address.clone(), + proxy_tls: proxy_item.tls.unwrap_or(false), + proxy_hostname: proxy_item.sni.clone().unwrap_or_else(|| hostname.clone()), + }); + } + } + let lookup_tls = group.lookup_dns.unwrap_or(false); + match &group.tls { + None => { + let proxy_service_tcp = service::proxy_service_tcp( + &my_server.configuration, + &listen_address, + lookup_tls, + host_configs, + ); + services.push(Box::new(proxy_service_tcp)); + } + Some(proxy_tls) => { + let proxy_service_ssl = service::proxy_service_tls( + &my_server.configuration, + &listen_address, + lookup_tls, + &proxy_tls, + host_configs, + ); + services.push(Box::new(proxy_service_ssl)); + } + } + } - let mut prometheus_service_http = ListeningService::prometheus_http_service(); - prometheus_service_http.add_tcp("127.0.0.1:6150"); + if let Some(true) = proxy_config.prometheus { + let mut prometheus_service_http = ListeningService::prometheus_http_service(); + prometheus_service_http.add_tcp("127.0.0.1:6150"); + services.push(Box::new(prometheus_service_http)); + } info!("start listen..."); - let services: Vec> = vec![ - Box::new(proxy_service_tcp), - Box::new(proxy_service_ssl2), - Box::new(prometheus_service_http), - ]; my_server.add_services(services); my_server.run_forever(); } diff --git a/src/service.rs b/src/service.rs index c9b1ef1..4b203e6 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::sync::Arc; use async_trait::async_trait; @@ -10,15 +11,41 @@ use pingora::tls::ext; use pingora::tls::pkey::PKey; use pingora::tls::ssl::{NameType, SslRef}; use pingora::tls::x509::X509; +use rcgen::Certificate; +use tokio::sync::RwLock; use crate::app::ProxyApp; use crate::cert; +use crate::cert::Cert; +use crate::config::ProxyTls; -struct Callback(); +struct Callback { + intermediate_certificate: Certificate, + intermediate_certificate_pem: String, + certificate_cache_map: RwLock>, +} impl Callback { - fn new() -> Self { - Self() + fn new(proxy_tls: &ProxyTls) -> Result { + let (cert, cert_pem) = cert::load_certificate(&proxy_tls.intermediate_cert, &proxy_tls.intermediate_key)?; + Ok(Self { + intermediate_certificate: cert, + intermediate_certificate_pem: cert_pem, + certificate_cache_map: Default::default(), + }) + } + + async fn issue_certificate(&self, hostname: &str) -> Result { + { + if let Some(cert) = self.certificate_cache_map.read().await.get(hostname) { + return Ok(cert.clone()); + } + } + let cert = cert::issue_certificate(&self.intermediate_certificate, &hostname)?; + { + self.certificate_cache_map.write().await.insert(hostname.to_string(), cert.clone()); + } + Ok(cert) } } @@ -28,22 +55,26 @@ impl TlsAccept for Callback { let sni_provided = ssl.servername(NameType::HOST_NAME).expect("get sni failed").to_string(); log::info!("SNI provided: {}", sni_provided); - let cert = cert::issue_certificate(&sni_provided).await; + let cert = self.issue_certificate(&sni_provided).await + .unwrap_or_else(|e| panic!("Issue certificate failed: {}", e)); let x509_cert = X509::from_pem(cert.cert_pem.as_bytes()) - .unwrap_or_else(|_| panic!("parse cert: {} failed", cert.cert_pem)); - let x509_intermediate_cert = X509::from_pem(cert.intermediate_pem.as_bytes()) - .unwrap_or_else(|_| panic!("parse intermediate cert: {} failed", cert.intermediate_pem)); + .unwrap_or_else(|e| panic!("parse cert: {} failed: {}", cert.cert_pem, e)); + let x509_intermediate_cert = X509::from_pem(self.intermediate_certificate_pem.as_bytes()) + .unwrap_or_else(|e| panic!("parse intermediate cert: {} failed: {}", self.intermediate_certificate_pem, e)); let private_key = PKey::private_key_from_pem(cert.key_pem.as_bytes()) - .unwrap_or_else(|_| panic!("parse key: {} failed", cert.key_pem)); + .unwrap_or_else(|e| panic!("parse key: {} failed: {}", cert.key_pem, e)); - ext::ssl_use_certificate(ssl, &x509_cert).unwrap_or_else(|_| panic!("apply certificate for: {} failed", sni_provided)); - ext::ssl_add_chain_cert(ssl, &x509_intermediate_cert).unwrap_or_else(|_| panic!("apply intermediate certificate for: {} failed", sni_provided)); - ext::ssl_use_private_key(ssl, &private_key).unwrap_or_else(|_| panic!("apply key for: {} failed", sni_provided)); + ext::ssl_use_certificate(ssl, &x509_cert) + .unwrap_or_else(|e| panic!("apply certificate for: {} failed: {}", sni_provided, e)); + ext::ssl_add_chain_cert(ssl, &x509_intermediate_cert) + .unwrap_or_else(|e| panic!("apply intermediate certificate for: {} failed: {}", sni_provided, e)); + ext::ssl_use_private_key(ssl, &private_key) + .unwrap_or_else(|e| panic!("apply key for: {} failed: {}", sni_provided, e)); } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct HostConfig { pub proxy_addr: String, pub proxy_tls: bool, @@ -53,9 +84,10 @@ pub struct HostConfig { pub fn proxy_service_tcp( server_conf: &Arc, listen_addr: &str, + lookup_dns: bool, host_configs: Vec, ) -> impl pingora::services::Service { - let proxy_app = ProxyApp::new(host_configs.clone()); + let proxy_app = ProxyApp::new(false, lookup_dns, host_configs); let mut service = http_proxy_service(server_conf, proxy_app); service.add_tcp(listen_addr); @@ -66,12 +98,14 @@ pub fn proxy_service_tcp( pub fn proxy_service_tls( server_conf: &Arc, listen_addr: &str, + lookup_dns: bool, + proxy_tls: &ProxyTls, host_configs: Vec, ) -> impl pingora::services::Service { - let proxy_app = ProxyApp::new(host_configs.clone()); + let proxy_app = ProxyApp::new(true, lookup_dns, host_configs); let mut service = http_proxy_service(server_conf, proxy_app); - let cb = Box::new(Callback::new()); + let cb = Box::new(Callback::new(proxy_tls).unwrap()); let tls_settings = TlsSettings::with_callbacks(cb).unwrap(); service.add_tls_with_settings(listen_addr, None, tls_settings);