From cd7e5ad034b75d659d4d87a752ab7b11cf75de12 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 7 Dec 2021 15:20:45 +0100 Subject: Got a reverse proxy --- Cargo.lock | 642 ++++++++++++++++++++++++++++++++++++++++++++++----- Cargo.toml | 8 +- src/cert.rs | 6 +- src/cert_store.rs | 23 +- src/https.rs | 126 ++++++++++ src/main.rs | 8 +- src/reverse_proxy.rs | 114 +++++++++ 7 files changed, 863 insertions(+), 64 deletions(-) create mode 100644 src/https.rs create mode 100644 src/reverse_proxy.rs diff --git a/Cargo.lock b/Cargo.lock index cd91d8b..5c7e156 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,7 +42,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -75,6 +75,23 @@ version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "either", + "iovec", +] + [[package]] name = "bytes" version = "1.1.0" @@ -87,6 +104,12 @@ version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +[[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" @@ -104,7 +127,7 @@ dependencies = [ "num-traits", "serde", "time 0.1.43", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -113,6 +136,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "const_fn" version = "0.4.8" @@ -162,19 +194,73 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[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", + "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", + "lazy_static", + "maybe-uninit", + "memoffset", + "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", + "maybe-uninit", +] + +[[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]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "encoding_rs" version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -230,6 +316,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", + "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.18" @@ -261,6 +369,16 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +[[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.18" @@ -325,26 +443,44 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] +[[package]] +name = "h2" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +dependencies = [ + "byteorder", + "bytes 0.4.12", + "fnv", + "futures 0.1.31", + "http 0.1.21", + "indexmap", + "log", + "slab", + "string", + "tokio-io", +] + [[package]] name = "h2" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" dependencies = [ - "bytes", + "bytes 1.1.0", "fnv", "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.5", "indexmap", "slab", - "tokio", + "tokio 1.14.0", "tokio-util", "tracing", ] @@ -364,25 +500,48 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +dependencies = [ + "bytes 0.4.12", + "fnv", + "itoa", +] + [[package]] name = "http" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ - "bytes", + "bytes 1.1.0", "fnv", "itoa", ] +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "http 0.1.21", + "tokio-buf", +] + [[package]] name = "http-body" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ - "bytes", - "http", + "bytes 1.1.0", + "http 0.2.5", "pin-project-lite", ] @@ -407,28 +566,70 @@ dependencies = [ "quick-error", ] +[[package]] +name = "hyper" +version = "0.12.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" +dependencies = [ + "bytes 0.4.12", + "futures 0.1.31", + "futures-cpupool", + "h2 0.1.26", + "http 0.1.21", + "http-body 0.1.0", + "httparse", + "iovec", + "itoa", + "log", + "net2", + "rustc_version", + "time 0.1.43", + "tokio 0.1.22", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want 0.2.0", +] + [[package]] name = "hyper" version = "0.14.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" dependencies = [ - "bytes", + "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.7", + "http 0.2.5", + "http-body 0.4.4", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", - "tokio", + "tokio 1.14.0", "tower-service", "tracing", - "want", + "want 0.3.0", +] + +[[package]] +name = "hyper-reverse-proxy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "474f19c624c13005d914fc4a73aa2a2921b0371f5f7b748146f5130685492ce8" +dependencies = [ + "futures 0.1.31", + "hyper 0.12.36", + "lazy_static", + "unicase", ] [[package]] @@ -437,10 +638,10 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes", - "hyper", + "bytes 1.1.0", + "hyper 0.14.15", "native-tls", - "tokio", + "tokio 1.14.0", "tokio-native-tls", ] @@ -465,6 +666,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "ipnet" version = "2.3.1" @@ -486,6 +696,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" @@ -498,13 +718,22 @@ version = "0.2.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -513,18 +742,52 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[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.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[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 0.2.2", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.7.14" @@ -533,9 +796,21 @@ checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", - "miow", + "miow 0.3.7", "ntapi", - "winapi", + "winapi 0.3.9", +] + +[[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]] @@ -544,7 +819,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -565,13 +840,24 @@ dependencies = [ "tempfile", ] +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "ntapi" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -616,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -642,6 +928,32 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api", + "parking_lot_core", + "rustc_version", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "rustc_version", + "smallvec", + "winapi 0.3.9", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -771,6 +1083,12 @@ dependencies = [ "rand_core", ] +[[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.2.10" @@ -803,7 +1121,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -813,13 +1131,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bea77bc708afa10e59905c3d4af7c8fd43c9214251673095ff8b14345fcbc5" dependencies = [ "base64", - "bytes", + "bytes 1.1.0", "encoding_rs", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 0.2.5", + "http-body 0.4.4", + "hyper 0.14.15", "hyper-tls", "ipnet", "js-sys", @@ -832,7 +1150,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "tokio", + "tokio 1.14.0", "tokio-native-tls", "url", "wasm-bindgen", @@ -853,7 +1171,7 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -912,9 +1230,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi", + "winapi 0.3.9", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "sct" version = "0.6.1" @@ -1037,6 +1361,15 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] + [[package]] name = "socket2" version = "0.4.2" @@ -1044,7 +1377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1111,6 +1444,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +dependencies = [ + "bytes 0.4.12", +] + [[package]] name = "syn" version = "1.0.82" @@ -1128,12 +1470,12 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "rand", - "redox_syscall", + "redox_syscall 0.2.10", "remove_dir_all", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1152,7 +1494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1167,7 +1509,7 @@ dependencies = [ "stdweb", "time-macros", "version_check", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1208,6 +1550,24 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[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-current-thread", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-threadpool", + "tokio-timer", +] + [[package]] name = "tokio" version = "1.14.0" @@ -1215,16 +1575,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" dependencies = [ "autocfg", - "bytes", + "bytes 1.1.0", "libc", "memchr", - "mio", + "mio 0.7.14", "num_cpus", "once_cell", "pin-project-lite", "signal-hook-registry", "tokio-macros", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +dependencies = [ + "bytes 0.4.12", + "either", + "futures 0.1.31", +] + +[[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-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils", + "futures 0.1.31", +] + +[[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]] @@ -1245,7 +1647,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ "native-tls", - "tokio", + "tokio 1.14.0", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils", + "futures 0.1.31", + "lazy_static", + "log", + "mio 0.6.23", + "num_cpus", + "parking_lot", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4baa378e417d780beff82bf54ceb0d195193ea6a00c14e22359e7f39456b5689" +dependencies = [ + "rustls 0.20.2", + "tokio 1.14.0", + "webpki 0.22.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]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "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", + "futures 0.1.31", + "slab", + "tokio-executor", ] [[package]] @@ -1254,12 +1739,12 @@ version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ - "bytes", + "bytes 1.1.0", "futures-core", "futures-sink", "log", "pin-project-lite", - "tokio", + "tokio 1.14.0", ] [[package]] @@ -1274,7 +1759,7 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "pin-project-lite", "tracing-core", ] @@ -1294,12 +1779,15 @@ version = "0.1.0" dependencies = [ "acme-micro", "anyhow", - "bytes", + "bytes 1.1.0", "chrono", "envy", - "futures", - "http", - "hyper", + "futures 0.3.18", + "futures-util", + "http 0.2.5", + "hyper 0.14.15", + "hyper-reverse-proxy", + "lazy_static", "log", "pretty_env_logger", "regex", @@ -1308,7 +1796,9 @@ dependencies = [ "rustls-pemfile", "serde", "serde_json", - "tokio", + "tokio 1.14.0", + "tokio-rustls", + "unicase", "uuid", ] @@ -1318,6 +1808,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.7" @@ -1394,6 +1893,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "want" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +dependencies = [ + "futures 0.1.31", + "log", + "try-lock", +] + [[package]] name = "want" version = "0.3.0" @@ -1416,7 +1926,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -1441,7 +1951,7 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -1515,6 +2025,12 @@ dependencies = [ "webpki 0.21.4", ] +[[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" @@ -1525,6 +2041,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" @@ -1537,7 +2059,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1552,5 +2074,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" dependencies = [ - "winapi", + "winapi 0.3.9", +] + +[[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", ] diff --git a/Cargo.toml b/Cargo.toml index 8de31a0..9c7ae8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,5 +23,11 @@ uuid = "0.8" rustls = "0.20" rustls-pemfile = "0.2" chrono = { version = "0.4", features = [ "serde" ] } -hyper = { version = "0.14", features = [ "http1", "http2", "runtime", "server", "tcp" ] } +hyper = { version = "0.14", features = [ "full" ] } +futures-util = "0.3" +tokio-rustls = "0.23" +#hyper-rustls = "0.23" http = "0.2" +hyper-reverse-proxy = "0.4" +unicase = "2" +lazy_static = "1.4" diff --git a/src/cert.rs b/src/cert.rs index de0d821..0be43f3 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use anyhow::Result; use chrono::{Date, NaiveDate, Utc}; @@ -17,7 +19,7 @@ pub struct CertSer { pub struct Cert { pub ser: CertSer, - pub certkey: CertifiedKey, + pub certkey: Arc, } impl Cert { @@ -46,7 +48,7 @@ impl Cert { bail!("{} keys present in pem file", keys.len()); } - let certkey = CertifiedKey::new(certs, keys.into_iter().next().unwrap()); + let certkey = Arc::new(CertifiedKey::new(certs, keys.into_iter().next().unwrap())); Ok(Cert { ser, certkey }) } diff --git a/src/cert_store.rs b/src/cert_store.rs index 6529395..1b1a478 100644 --- a/src/cert_store.rs +++ b/src/cert_store.rs @@ -6,9 +6,11 @@ use anyhow::Result; use chrono::Utc; use log::*; use tokio::sync::watch; +use tokio::task::block_in_place; use acme_micro::create_p384_key; use acme_micro::{Directory, DirectoryUrl}; +use rustls::sign::CertifiedKey; use crate::cert::{Cert, CertSer}; use crate::consul::Consul; @@ -93,7 +95,7 @@ impl CertStore { dir.load_account(std::str::from_utf8(&acc_privkey)?, contact)? } else { info!("Creating new Let's encrypt account"); - let acc = dir.register_account(contact.clone())?; + let acc = block_in_place(|| dir.register_account(contact.clone()))?; self.consul .kv_put( "letsencrypt_account_key.pem", @@ -119,17 +121,18 @@ impl CertStore { .await?; info!("Validating challenge"); - chall.validate(Duration::from_millis(5000))?; + block_in_place(|| chall.validate(Duration::from_millis(5000)))?; info!("Deleting challenge"); self.consul.kv_delete(&chall_key).await?; - ord_new.refresh()?; + block_in_place(|| ord_new.refresh())?; }; let pkey_pri = create_p384_key()?; - let ord_cert = ord_csr.finalize_pkey(pkey_pri, Duration::from_millis(5000))?; - let cert = ord_cert.download_cert()?; + let ord_cert = + block_in_place(|| ord_csr.finalize_pkey(pkey_pri, Duration::from_millis(5000)))?; + let cert = block_in_place(|| ord_cert.download_cert())?; info!("Keys and certificate obtained"); let key_pem = cert.private_key().to_string(); @@ -157,3 +160,13 @@ impl CertStore { Ok(cert) } } + +pub struct StoreResolver(pub Arc); + +impl rustls::server::ResolvesServerCert for StoreResolver { + fn resolve(&self, client_hello: rustls::server::ClientHello<'_>) -> Option> { + let domain = client_hello.server_name()?; + let cert = futures::executor::block_on(self.0.get_cert(domain)).ok()?; + Some(cert.certkey.clone()) + } +} diff --git a/src/https.rs b/src/https.rs new file mode 100644 index 0000000..c80d51c --- /dev/null +++ b/src/https.rs @@ -0,0 +1,126 @@ +use std::net::SocketAddr; +use std::sync::Arc; + +use anyhow::Result; +use log::*; + +use futures::FutureExt; +use hyper::server::conn::Http; +use hyper::service::service_fn; +use hyper::{Body, Request, Response, StatusCode}; +use tokio::net::TcpListener; +use tokio::sync::watch; +use tokio_rustls::TlsAcceptor; + +use crate::cert_store::{CertStore, StoreResolver}; +use crate::proxy_config::ProxyConfig; +use crate::reverse_proxy; + +pub async fn serve_https( + cert_store: Arc, + proxy_config: watch::Receiver>, +) -> Result<()> { + let addr = format!("0.0.0.0:1443"); + + let mut cfg = rustls::ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_cert_resolver(Arc::new(StoreResolver(cert_store))); + + cfg.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; + let tls_cfg = Arc::new(cfg); + let tls_acceptor = Arc::new(TlsAcceptor::from(tls_cfg)); + + println!("Starting to serve on https://{}.", addr); + + let tcp = TcpListener::bind(&addr).await?; + loop { + let (socket, remote_addr) = tcp.accept().await?; + + let proxy_config = proxy_config.clone(); + let tls_acceptor = tls_acceptor.clone(); + + tokio::spawn(async move { + match tls_acceptor.accept(socket).await { + Ok(stream) => { + debug!("TLS handshake was successfull"); + let http_result = Http::new() + .serve_connection( + stream, + service_fn(move |req: Request| { + let proxy_config: Arc = proxy_config.borrow().clone(); + handle(remote_addr, req, proxy_config).map(|res| match res { + Err(e) => { + warn!("Handler error: {}", e); + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(Body::from(format!("{}", e))) + .map_err(Into::into) + } + x => x, + }) + }), + ) + .await; + if let Err(http_err) = http_result { + debug!("HTTP error: {}", http_err); + } + } + Err(e) => debug!("Error in TLS connection: {}", e), + } + }); + } +} + +// Custom echo service, handling two different routes and a +// catch-all 404 responder. +async fn handle( + remote_addr: SocketAddr, + req: Request, + proxy_config: Arc, +) -> Result, anyhow::Error> { + let host = if let Some(auth) = req.uri().authority() { + auth.as_str() + } else { + req.headers() + .get("host") + .ok_or_else(|| anyhow!("Missing host header"))? + .to_str()? + }; + let path = req.uri().path(); + + let ent = proxy_config + .entries + .iter() + .filter(|ent| { + ent.host == host + && ent + .path_prefix + .as_ref() + .map(|prefix| path.starts_with(prefix)) + .unwrap_or(true) + }) + .min_by_key(|ent| { + ( + ent.priority, + -(ent + .path_prefix + .as_ref() + .map(|x| x.len() as i32) + .unwrap_or(0)), + ) + }); + + if let Some(proxy_to) = ent { + let to_addr = format!("http://{}", proxy_to.target_addr); + info!("Proxying {} {} -> {}", host, path, to_addr); + + reverse_proxy::call(remote_addr.ip(), &to_addr, req).await + } else { + info!("Proxying {} {} -> NOT FOUND", host, path); + + Ok(Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::from("No matching proxy entry"))?) + } +} diff --git a/src/main.rs b/src/main.rs index d7f1e24..df0845d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,13 @@ mod cert; mod cert_store; mod consul; mod http; +mod https; mod proxy_config; +mod reverse_proxy; use log::*; -#[tokio::main(flavor = "multi_thread")] +#[tokio::main(flavor = "multi_thread", worker_threads = 10)] async fn main() { if std::env::var("RUST_LOG").is_err() { std::env::set_var("RUST_LOG", "tricot=debug") @@ -28,6 +30,10 @@ async fn main() { ); tokio::spawn(http::serve_http(consul.clone())); + tokio::spawn(https::serve_https( + cert_store.clone(), + rx_proxy_config.clone(), + )); while rx_proxy_config.changed().await.is_ok() { info!("Proxy config: {:#?}", *rx_proxy_config.borrow()); diff --git a/src/reverse_proxy.rs b/src/reverse_proxy.rs new file mode 100644 index 0000000..82533d8 --- /dev/null +++ b/src/reverse_proxy.rs @@ -0,0 +1,114 @@ +//! Copied from https://github.com/felipenoris/hyper-reverse-proxy +//! See there for original Copyright notice + +use anyhow::Result; + +use hyper::header::{HeaderMap, HeaderValue}; +use hyper::{Body, Client, Request, Response, Uri}; +use lazy_static::lazy_static; +use std::net::IpAddr; +use std::str::FromStr; + +fn is_hop_header(name: &str) -> bool { + use unicase::Ascii; + + // A list of the headers, using `unicase` to help us compare without + // worrying about the case, and `lazy_static!` to prevent reallocation + // of the vector. + lazy_static! { + static ref HOP_HEADERS: Vec> = vec![ + Ascii::new("Connection"), + Ascii::new("Keep-Alive"), + Ascii::new("Proxy-Authenticate"), + Ascii::new("Proxy-Authorization"), + Ascii::new("Te"), + Ascii::new("Trailers"), + Ascii::new("Transfer-Encoding"), + Ascii::new("Upgrade"), + ]; + } + + HOP_HEADERS.iter().any(|h| h == &name) +} + +/// Returns a clone of the headers without the [hop-by-hop headers]. +/// +/// [hop-by-hop headers]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html +fn remove_hop_headers(headers: &HeaderMap) -> HeaderMap { + let mut result = HeaderMap::new(); + for (k, v) in headers.iter() { + if !is_hop_header(k.as_str()) { + result.insert(k.clone(), v.clone()); + } + } + result +} + +fn create_proxied_response(mut response: Response) -> Response { + *response.headers_mut() = remove_hop_headers(response.headers()); + response +} + +fn forward_uri(forward_url: &str, req: &Request) -> Result { + let forward_uri = match req.uri().query() { + Some(query) => format!("{}{}?{}", forward_url, req.uri().path(), query), + None => format!("{}{}", forward_url, req.uri().path()), + }; + + Ok(Uri::from_str(forward_uri.as_str())?) +} + +fn create_proxied_request( + client_ip: IpAddr, + forward_url: &str, + request: Request, +) -> Result> { + let mut builder = Request::builder().uri(forward_uri(forward_url, &request)?); + + *builder.headers_mut().unwrap() = remove_hop_headers(request.headers()); + + let host_header_name = "host"; + let x_forwarded_for_header_name = "x-forwarded-for"; + + // If request does not have host header, add it from original URI authority + if let Some(authority) = request.uri().authority() { + if let hyper::header::Entry::Vacant(entry) = builder + .headers_mut() + .unwrap() + .entry(host_header_name) + { + entry.insert(authority.as_str().parse()?); + } + } + + // Add forwarding information in the headers + match builder + .headers_mut() + .unwrap() + .entry(x_forwarded_for_header_name) + { + hyper::header::Entry::Vacant(entry) => { + entry.insert(client_ip.to_string().parse()?); + } + + hyper::header::Entry::Occupied(mut entry) => { + let addr = format!("{}, {}", entry.get().to_str()?, client_ip); + entry.insert(addr.parse()?); + } + } + + Ok(builder.body(request.into_body())?) +} + +pub async fn call( + client_ip: IpAddr, + forward_uri: &str, + request: Request, +) -> Result> { + let proxied_request = create_proxied_request(client_ip, &forward_uri, request)?; + + let client = Client::new(); + let response = client.request(proxied_request).await?; + let proxied_response = create_proxied_response(response); + Ok(proxied_response) +} -- cgit v1.2.3