From 5a1d9efd83277c467d26dfdb99a4988f06e61c19 Mon Sep 17 00:00:00 2001 From: zonyitoo Date: Sun, 31 May 2020 22:50:17 +0800 Subject: [PATCH] [#260] Support HTTPS local server with native-tls --- Cargo.lock | 88 +++++------ src/bin/local.rs | 29 ++++ src/config.rs | 28 ++++ src/relay/local.rs | 7 + src/relay/tcprelay/http_local.rs | 71 ++++++--- src/relay/tcprelay/http_tls/mod.rs | 15 ++ src/relay/tcprelay/http_tls/native_tls.rs | 171 ++++++++++++++++++++++ src/relay/tcprelay/http_tls/rustls.rs | 0 src/relay/tcprelay/local.rs | 5 + src/relay/tcprelay/mod.rs | 5 + src/relay/tcprelay/proxy_stream.rs | 5 + src/relay/udprelay/local.rs | 5 + 12 files changed, 367 insertions(+), 62 deletions(-) create mode 100644 src/relay/tcprelay/http_tls/mod.rs create mode 100644 src/relay/tcprelay/http_tls/native_tls.rs create mode 100644 src/relay/tcprelay/http_tls/rustls.rs diff --git a/Cargo.lock b/Cargo.lock index fd5f1740c17e..c7e9025e5d73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,7 +94,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -330,7 +330,7 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -443,7 +443,7 @@ dependencies = [ "proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -589,7 +589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -602,8 +602,8 @@ dependencies = [ "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -680,7 +680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1010,7 +1010,7 @@ dependencies = [ "pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1038,12 +1038,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pin-project-lite" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1187,7 +1187,7 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.13" +version = "0.16.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1216,9 +1216,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.14 (registry+https://github.com/rust-lang/crates.io-index)", "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1251,7 +1251,7 @@ name = "sct" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.14 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1278,20 +1278,20 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1301,7 +1301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1311,7 +1311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1345,7 +1345,7 @@ dependencies = [ "hkdf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "ipnet 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "iprange 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "json5 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1365,9 +1365,9 @@ dependencies = [ "qrcode 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1453,7 +1453,7 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1463,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1541,7 +1541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1577,7 +1577,7 @@ dependencies = [ "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1591,7 +1591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1611,7 +1611,7 @@ dependencies = [ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1623,7 +1623,7 @@ dependencies = [ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1766,7 +1766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1796,7 +1796,7 @@ dependencies = [ "trust-dns-proto 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-rustls 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", "typed-headers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1854,7 +1854,7 @@ dependencies = [ "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-proto 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1978,7 +1978,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1998,7 +1998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-backend 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-shared 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2019,10 +2019,10 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.14 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2031,7 +2031,7 @@ name = "webpki-roots" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2179,7 +2179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" "checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum hyper 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" +"checksum hyper 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" @@ -2230,7 +2230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" "checksum pin-project 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791" "checksum pin-project-internal 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40" -"checksum pin-project-lite 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" +"checksum pin-project-lite 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9df32da11d84f3a7d70205549562966279adb900e080fad3dccd8e64afccf0ad" "checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" "checksum pmac 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd76d63e86aa67a4bd063079f0d93bb8730b036eea5697345f651e6874ea61e5" @@ -2250,7 +2250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum resolv-conf 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a" -"checksum ring 0.16.13 (registry+https://github.com/rust-lang/crates.io-index)" = "703516ae74571f24b465b4a1431e81e2ad51336cb0ded733a55a1aa3eccac196" +"checksum ring 0.16.14 (registry+https://github.com/rust-lang/crates.io-index)" = "06b3fefa4f12272808f809a0af618501fdaba41a58963c5fb72238ab0be09603" "checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" @@ -2260,8 +2260,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" "checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" "checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" -"checksum serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)" = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" -"checksum serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)" = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" +"checksum serde 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" +"checksum serde_derive 1.0.111 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" "checksum serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)" = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" "checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" @@ -2276,7 +2276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" "checksum strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e33a62f20d3dc02a1bc9c1d385f92b459bbf35e4dc325eed20c53db5b90c03" +"checksum syn 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum tar 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "5c058ad0bd6ccb84faa24cc44d4fc99bee8a5d7ba9ff33aa4d993122d1aeeac2" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" @@ -2332,7 +2332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum wasm-bindgen-macro-support 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" "checksum wasm-bindgen-shared 0.2.63 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd" "checksum web-sys 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "7b72fe77fd39e4bd3eaa4412fd299a0be6b3dfe9d2597e2f1c20beb968f41d17" -"checksum webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" +"checksum webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae" "checksum webpki-roots 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" "checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/src/bin/local.rs b/src/bin/local.rs index e29e50583d78..3621793adcbe 100644 --- a/src/bin/local.rs +++ b/src/bin/local.rs @@ -34,6 +34,11 @@ const AVAILABLE_PROTOCOLS: &[&str] = &[ "socks4", #[cfg(feature = "local-http")] "http", + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + "https", #[cfg(feature = "local-tunnel")] "tunnel", #[cfg(feature = "local-redir")] @@ -122,6 +127,14 @@ fn main() { ); } + #[cfg(feature = "local-http-native-tls")] + { + app = clap_app!(@app (app) + (@arg TLS_IDENTITY_PATH: --("tls-identity") +takes_value required_if("PROTOCOL", "https") requires[TLS_IDENTITY_PASSWORD] "TLS identity file (PKCS #12) path for HTTPS server") + (@arg TLS_IDENTITY_PASSWORD: --("tls-identity-password") +takes_value required_if("PROTOCOL", "https") requires[TLS_IDENTITY_PATH] "TLS identity file's password for HTTPS server") + ); + } + let matches = app.get_matches(); drop(available_ciphers); @@ -134,6 +147,11 @@ fn main() { Some("socks4") => ConfigType::Socks4Local, #[cfg(feature = "local-http")] Some("http") => ConfigType::HttpLocal, + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + Some("https") => ConfigType::HttpsLocal, #[cfg(feature = "local-tunnel")] Some("tunnel") => ConfigType::TunnelLocal, #[cfg(feature = "local-redir")] @@ -269,6 +287,17 @@ fn main() { } } + #[cfg(feature = "local-http-native-tls")] + { + if let Some(ipath) = matches.value_of("TLS_IDENTITY_PATH") { + config.tls_identity_path = Some(ipath.into()); + } + + if let Some(ipwd) = matches.value_of("TLS_IDENTITY_PASSWORD") { + config.tls_identity_password = Some(ipwd.into()); + } + } + // DONE READING options if config.local_addr.is_none() { diff --git a/src/config.rs b/src/config.rs index 2ae00fd1c243..d22ecc2ec04a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -595,6 +595,15 @@ pub enum ConfigType { #[cfg(feature = "local-http")] HttpLocal, + /// Config for HTTPS local + /// + /// Requires `local` configuration + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + HttpsLocal, + /// Config for tunnel local /// /// Requires `local` and `forward` configuration @@ -633,6 +642,11 @@ impl ConfigType { ConfigType::TunnelLocal => true, #[cfg(feature = "local-http")] ConfigType::HttpLocal => true, + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + ConfigType::HttpsLocal => true, #[cfg(feature = "local-redir")] ConfigType::RedirLocal => true, ConfigType::Server | ConfigType::Manager => false, @@ -651,6 +665,11 @@ impl ConfigType { ConfigType::TunnelLocal => false, #[cfg(feature = "local-http")] ConfigType::HttpLocal => false, + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + ConfigType::HttpsLocal => false, #[cfg(feature = "local-redir")] ConfigType::RedirLocal => false, ConfigType::Manager => false, @@ -958,6 +977,11 @@ pub struct Config { /// /// Set to `true` if you want to query IPv6 addresses before IPv4 pub ipv6_first: bool, + /// TLS cryptographic identify (X509) + #[cfg(feature = "local-http-native-tls")] + pub tls_identity_path: Option, + #[cfg(feature = "local-http-native-tls")] + pub tls_identity_password: Option, } /// Configuration parsing error kind @@ -1048,6 +1072,10 @@ impl Config { local_dns_addr: None, remote_dns_addr: None, ipv6_first: false, + #[cfg(feature = "local-http-native-tls")] + tls_identity_path: None, + #[cfg(feature = "local-http-native-tls")] + tls_identity_password: None, } } diff --git a/src/relay/local.rs b/src/relay/local.rs index 793d65a296db..284cfb3ed962 100644 --- a/src/relay/local.rs +++ b/src/relay/local.rs @@ -66,6 +66,13 @@ pub async fn run(mut config: Config) -> io::Result<()> { #[cfg(feature = "local-http")] ConfigType::HttpLocal => true, + // HTTPS must be TCP + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + ConfigType::HttpsLocal => true, + // Redir mode controlled by this flag #[cfg(feature = "local-redir")] ConfigType::RedirLocal => mode.enable_tcp(), diff --git a/src/relay/tcprelay/http_local.rs b/src/relay/tcprelay/http_local.rs index bebadd9537d6..9adfeedbaf28 100644 --- a/src/relay/tcprelay/http_local.rs +++ b/src/relay/tcprelay/http_local.rs @@ -39,6 +39,7 @@ use pin_project::pin_project; use tokio::io::{AsyncRead, AsyncWrite}; use crate::{ + config::ConfigType, context::SharedContext, relay::{ loadbalancing::server::{ @@ -826,31 +827,65 @@ pub async fn run(context: SharedContext) -> io::Result<()> { let bind_addr = local_addr.bind_addr(&context).await?; let bypass_client = Client::builder().build::<_, Body>(DirectConnector::new(context.clone())); - let servers: PingBalancer = PingBalancer::new(context, ServerType::Tcp).await; + let servers: PingBalancer = PingBalancer::new(context.clone(), ServerType::Tcp).await; let servers = Arc::new(servers); - let make_service = make_service_fn(|socket: &AddrStream| { - let client_addr = socket.remote_addr(); - let servers = servers.clone(); - let bypass_client = bypass_client.clone(); + match context.config().config_type { + ConfigType::HttpLocal => { + let make_service = make_service_fn(|socket: &AddrStream| { + let client_addr = socket.remote_addr(); + let servers = servers.clone(); + let bypass_client = bypass_client.clone(); + + async move { + Ok::<_, Infallible>(service_fn(move |req: Request| { + let svr_score = servers.pick_server(); + server_dispatch(req, svr_score, client_addr, bypass_client.clone()) + })) + } + }); + + // HTTP Proxy protocol only defined in HTTP 1.x + let server = Server::bind(&bind_addr).http1_only(true).serve(make_service); + info!("shadowsocks HTTP listening on {}", server.local_addr()); - async move { - Ok::<_, Infallible>(service_fn(move |req: Request| { - let svr_score = servers.pick_server(); - server_dispatch(req, svr_score, client_addr, bypass_client.clone()) - })) + if let Err(err) = server.await { + use std::io::Error; + + error!("hyper server exited with error: {}", err); + return Err(Error::new(ErrorKind::Other, err)); + } } - }); + #[cfg(any(feature = "local-http-native-tls", feature = "local-http-rustls"))] + ConfigType::HttpsLocal => { + use super::http_tls::{TlsAcceptor, TlsStream}; + + let make_service = make_service_fn(|socket: &TlsStream| { + let client_addr = socket.remote_addr(); + let servers = servers.clone(); + let bypass_client = bypass_client.clone(); + + async move { + Ok::<_, Infallible>(service_fn(move |req: Request| { + let svr_score = servers.pick_server(); + server_dispatch(req, svr_score, client_addr, bypass_client.clone()) + })) + } + }); + + let acceptor = TlsAcceptor::bind(context.config(), &bind_addr)?; + info!("shadowsocks HTTPS listening on {}", acceptor.local_addr()); - // HTTP Proxy protocol only defined in HTTP 1.x - let server = Server::bind(&bind_addr).http1_only(true).serve(make_service); - info!("shadowsocks HTTP listening on {}", server.local_addr()); + let server = Server::builder(acceptor).http1_only(true).serve(make_service); - if let Err(err) = server.await { - use std::io::Error; + if let Err(err) = server.await { + use std::io::Error; - error!("hyper server exited with error: {}", err); - return Err(Error::new(ErrorKind::Other, err)); + error!("hyper server exited with error: {}", err); + return Err(Error::new(ErrorKind::Other, err)); + } + } + _ => unreachable!("http_local::run shouldn't used with {:?}", context.config().config_type), } Ok(()) diff --git a/src/relay/tcprelay/http_tls/mod.rs b/src/relay/tcprelay/http_tls/mod.rs new file mode 100644 index 000000000000..1ab942d54998 --- /dev/null +++ b/src/relay/tcprelay/http_tls/mod.rs @@ -0,0 +1,15 @@ +//! TLS support for HTTP local (HTTPS) +//! +//! Choosing TLS library by `local-http-rustls` and `local-http-native-tls` + +#[cfg(feature = "local-http-native-tls")] +pub mod native_tls; + +#[cfg(feature = "local-http-native-tls")] +pub use self::native_tls::{TlsAcceptor, TlsStream}; + +#[cfg(feature = "local-http-rustls")] +pub mod rustls; + +#[cfg(feature = "local-http-rustls")] +pub use self::rustls::{TlsAcceptor, TlsStream}; diff --git a/src/relay/tcprelay/http_tls/native_tls.rs b/src/relay/tcprelay/http_tls/native_tls.rs new file mode 100644 index 000000000000..071dc8103142 --- /dev/null +++ b/src/relay/tcprelay/http_tls/native_tls.rs @@ -0,0 +1,171 @@ +//! TLS support implementation by native-tls + +use std::{ + fs::File, + future::Future, + io, + io::Read, + net::SocketAddr, + pin::Pin, + sync::Arc, + task::{self, Poll}, +}; + +use futures::{ready, FutureExt}; +use hyper::server::{ + accept::Accept, + conn::{AddrIncoming, AddrStream}, +}; +use native_tls::Identity; +use pin_project::pin_project; +use tokio::io::{AsyncRead, AsyncWrite}; + +use crate::config::Config; + +#[pin_project] +pub struct TlsAcceptor { + acceptor: Arc, + #[pin] + incoming: AddrIncoming, +} + +impl TlsAcceptor { + pub fn bind(config: &Config, addr: &SocketAddr) -> io::Result { + let id_path = config.tls_identity_path.as_ref().expect("identity path"); + let id_pwd = config.tls_identity_password.as_ref().expect("identify password"); + + let mut id_file = File::open(id_path)?; + let mut id_buf = Vec::new(); + id_file.read_to_end(&mut id_buf)?; + + let identity = match Identity::from_pkcs12(&id_buf, &id_pwd) { + Ok(identity) => identity, + Err(err) => { + let err = io::Error::new(io::ErrorKind::Other, format!("load identity: {}", err)); + return Err(err); + } + }; + + let acceptor = match native_tls::TlsAcceptor::new(identity) { + Ok(acceptor) => acceptor, + Err(err) => { + let err = io::Error::new(io::ErrorKind::Other, format!("create tls acceptor: {}", err)); + return Err(err); + } + }; + + Ok(TlsAcceptor { + acceptor: Arc::new(From::from(acceptor)), + incoming: match AddrIncoming::bind(addr) { + Ok(incoming) => incoming, + Err(err) => { + let err = io::Error::new(io::ErrorKind::Other, format!("hyper bind: {}", err)); + return Err(err); + } + }, + }) + } + + pub fn local_addr(&self) -> SocketAddr { + self.incoming.local_addr() + } +} + +impl Accept for TlsAcceptor { + type Conn = TlsStream; + type Error = io::Error; + + fn poll_accept(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll>> { + let this = self.project(); + match ready!(this.incoming.poll_accept(cx)) { + Some(Ok(stream)) => { + let acceptor = this.acceptor.clone(); + let remote_addr = stream.remote_addr(); + Poll::Ready(Some(Ok(TlsStream { + state: TlsStreamState::Handshaking(async move { acceptor.accept(stream).await }.boxed()), + remote_addr, + }))) + } + Some(Err(e)) => Poll::Ready(Some(Err(e))), + None => Poll::Ready(None), + } + } +} + +enum TlsStreamState { + Handshaking( + Pin< + Box< + dyn Future, native_tls::Error>> + + Send + + 'static, + >, + >, + ), + Streaming(tokio_native_tls::TlsStream), +} + +pub struct TlsStream { + state: TlsStreamState, + remote_addr: SocketAddr, +} + +impl TlsStream { + pub fn remote_addr(&self) -> SocketAddr { + self.remote_addr + } +} + +macro_rules! forward_stream_method { + ($self:expr, $cx:expr, $method:ident $(, $param:expr)*) => {{ + let this = $self.get_mut(); + + loop { + match this.state { + TlsStreamState::Handshaking(ref mut accept_fut) => { + let fut = accept_fut.as_mut(); + match ready!(fut.poll($cx)) { + Ok(stream) => { + this.state = TlsStreamState::Streaming(stream); + } + Err(err) => { + let err = io::Error::new(io::ErrorKind::Other, format!("tls handshake: {}", err)); + return Poll::Ready(Err(err)); + } + } + } + TlsStreamState::Streaming(ref mut stream) => { + return Pin::new(stream).$method($cx, $($param),*); + } + } + } + }}; +} + +impl AsyncRead for TlsStream { + fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll> { + forward_stream_method!(self, cx, poll_read, buf) + } +} + +impl AsyncWrite for TlsStream { + fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { + forward_stream_method!(self, cx, poll_write, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { + let this = self.get_mut(); + match this.state { + TlsStreamState::Handshaking(..) => Poll::Ready(Ok(())), + TlsStreamState::Streaming(ref mut stream) => Pin::new(stream).poll_flush(cx), + } + } + + fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { + let this = self.get_mut(); + match this.state { + TlsStreamState::Handshaking(..) => Poll::Ready(Ok(())), + TlsStreamState::Streaming(ref mut stream) => Pin::new(stream).poll_shutdown(cx), + } + } +} diff --git a/src/relay/tcprelay/http_tls/rustls.rs b/src/relay/tcprelay/http_tls/rustls.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/relay/tcprelay/local.rs b/src/relay/tcprelay/local.rs index 6a1a79074b08..fec78864f946 100644 --- a/src/relay/tcprelay/local.rs +++ b/src/relay/tcprelay/local.rs @@ -14,6 +14,11 @@ pub async fn run(context: SharedContext) -> io::Result<()> { ConfigType::TunnelLocal => super::tunnel_local::run(context).await, #[cfg(feature = "local-http")] ConfigType::HttpLocal => super::http_local::run(context).await, + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + ConfigType::HttpsLocal => super::http_local::run(context).await, #[cfg(feature = "local-redir")] ConfigType::RedirLocal => super::redir_local::run(context).await, #[cfg(feature = "local-dns-relay")] diff --git a/src/relay/tcprelay/mod.rs b/src/relay/tcprelay/mod.rs index 237ad48f2d8c..d53a6ba55ddd 100644 --- a/src/relay/tcprelay/mod.rs +++ b/src/relay/tcprelay/mod.rs @@ -19,6 +19,11 @@ mod connection; mod crypto_io; #[cfg(feature = "local-http")] mod http_local; +#[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") +))] +mod http_tls; pub mod local; mod monitor; mod proxy_stream; diff --git a/src/relay/tcprelay/proxy_stream.rs b/src/relay/tcprelay/proxy_stream.rs index 0b22cae1f31c..afe96cbf4a03 100644 --- a/src/relay/tcprelay/proxy_stream.rs +++ b/src/relay/tcprelay/proxy_stream.rs @@ -471,6 +471,11 @@ async fn connect_proxy_server(context: &Context, svr_cfg: &ServerConfig) -> io:: ConfigType::DnsLocal => svr_cfg.external_addr(), #[cfg(feature = "local-http")] ConfigType::HttpLocal => svr_cfg.external_addr(), + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + ConfigType::HttpsLocal => svr_cfg.external_addr(), #[cfg(feature = "local-redir")] ConfigType::RedirLocal => svr_cfg.external_addr(), diff --git a/src/relay/udprelay/local.rs b/src/relay/udprelay/local.rs index 147b906b277f..e55fd423276b 100644 --- a/src/relay/udprelay/local.rs +++ b/src/relay/udprelay/local.rs @@ -29,6 +29,11 @@ pub async fn run(context: SharedContext) -> io::Result<()> { ConfigType::RedirLocal => super::redir_local::run(context).await, #[cfg(feature = "local-http")] ConfigType::HttpLocal => unreachable!(), + #[cfg(all( + feature = "local-http", + any(feature = "local-http-native-tls", feature = "local-http-rustls") + ))] + ConfigType::HttpsLocal => unreachable!(), #[cfg(feature = "local-dns-relay")] ConfigType::DnsLocal => unreachable!(), ConfigType::Server => unreachable!(),