mirror of
https://github.com/sadoyan/aralez.git
synced 2026-06-22 23:32:40 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5815da6576 | ||
|
|
1ab0916026 | ||
|
|
707f725b88 | ||
|
|
eb4e73ece0 | ||
|
|
53e7dcfd33 | ||
|
|
f3b346a28d | ||
|
|
c011800e1e | ||
|
|
265ff6b774 | ||
|
|
1c3d9a263f | ||
|
|
162c5060c9 | ||
|
|
132cf45dfe | ||
|
|
77dcafbb4e | ||
|
|
649bd979f7 | ||
|
|
bd315106b9 | ||
|
|
3ba2ed33ae | ||
|
|
c09efab9fd | ||
|
|
735d605f6d | ||
|
|
6773d0f502 | ||
|
|
a8cb727da5 | ||
|
|
f81194aee7 | ||
|
|
0f09a2e02b | ||
|
|
27aca0a3a5 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -5,13 +5,13 @@
|
||||
*.dll
|
||||
*.exe
|
||||
*.sh
|
||||
/docs/
|
||||
*.yaml
|
||||
/docs
|
||||
/etc
|
||||
assets/
|
||||
assets
|
||||
/target/
|
||||
*.iml
|
||||
.idea/
|
||||
.etc/
|
||||
*.ipr
|
||||
*.iws
|
||||
/out/
|
||||
@@ -22,4 +22,5 @@ crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
/target
|
||||
/z_shpo
|
||||
/configs
|
||||
Makefile
|
||||
|
||||
212
Cargo.lock
generated
212
Cargo.lock
generated
@@ -127,7 +127,7 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||
|
||||
[[package]]
|
||||
name = "aralez"
|
||||
version = "0.9.2"
|
||||
version = "0.92.11"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"arc-swap",
|
||||
@@ -139,10 +139,13 @@ dependencies = [
|
||||
"futures",
|
||||
"instant-acme",
|
||||
"jsonwebtoken",
|
||||
"libc",
|
||||
"log",
|
||||
"log4rs",
|
||||
"mimalloc",
|
||||
"moka",
|
||||
"notify",
|
||||
"noyalib",
|
||||
"pingora",
|
||||
"pingora-core",
|
||||
"pingora-http",
|
||||
@@ -157,15 +160,12 @@ dependencies = [
|
||||
"sd-notify",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yml",
|
||||
"sha2 0.11.0",
|
||||
"signal-hook",
|
||||
"subtle",
|
||||
"tikv-jemalloc-ctl",
|
||||
"tikv-jemallocator",
|
||||
"tokio",
|
||||
"tonic",
|
||||
"tower-http",
|
||||
"tower-http 0.7.0",
|
||||
"urlencoding",
|
||||
"x509-parser",
|
||||
]
|
||||
@@ -473,27 +473,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cf-rustracing"
|
||||
version = "1.3.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6565523d8145e63e0cf1b397a5f1bd4e90d5652a7dffb2de8cec460ff23ef6b1"
|
||||
checksum = "93f85c3824e4191621dec0551e3cef3d511f329da9a8990bf3e450a85651d97e"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"rand 0.10.1",
|
||||
"rand 0.8.6",
|
||||
"tokio",
|
||||
"trackable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cf-rustracing-jaeger"
|
||||
version = "1.3.0"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16c0e4d8cce27f6a6eaff58d2b66f063a18b8ed0d6ef0947ae7a263afa3b7c08"
|
||||
checksum = "a6a5f80d44c257c3300a7f45ada676c211e64bbbac591bbec19344a8f61fbcab"
|
||||
dependencies = [
|
||||
"cf-rustracing",
|
||||
"hostname",
|
||||
"local-ip-address",
|
||||
"percent-encoding",
|
||||
"rand 0.10.1",
|
||||
"rand 0.9.4",
|
||||
"thrift_codec",
|
||||
"tokio",
|
||||
"trackable",
|
||||
@@ -1713,9 +1713,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199"
|
||||
checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"inotify-sys",
|
||||
@@ -1872,9 +1872,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a"
|
||||
checksum = "273c0752728918e0ac4976f2b275b6fefb9ecd400585dec929419f3844cd87b5"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
@@ -1882,9 +1882,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.1.0"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7b65860415f949f23fa882e669f2dbd4a0f0eeb1acdd56790b30494afd7da2f"
|
||||
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"libc",
|
||||
@@ -1918,13 +1918,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||
|
||||
[[package]]
|
||||
name = "libyml"
|
||||
version = "0.0.5"
|
||||
name = "libmimalloc-sys"
|
||||
version = "0.1.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980"
|
||||
checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"version_check",
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2043,6 +2042,15 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mimalloc"
|
||||
version = "0.1.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862"
|
||||
dependencies = [
|
||||
"libmimalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
@@ -2202,6 +2210,22 @@ dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "noyalib"
|
||||
version = "0.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14057395c16a4230575c6f86bfa074db87e8458626d3e56b20c2454334a7e50c"
|
||||
dependencies = [
|
||||
"indexmap 2.14.0",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"rustc-hash",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_ignored",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
@@ -2428,12 +2452,6 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "pem"
|
||||
version = "3.0.6"
|
||||
@@ -2497,9 +2515,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pingora"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "844a13b16e556293f4ea96dc5ac0923ac6f36855a9dfc13b640d0da183f6b5b7"
|
||||
checksum = "54a75f2ff8e122aa80ab202dc865294fe59cd856c2a5dab2d3df6e122c93b941"
|
||||
dependencies = [
|
||||
"pingora-cache",
|
||||
"pingora-core",
|
||||
@@ -2511,9 +2529,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-cache"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59d8c4c939a3a193a3da0e061aa7acf7432431f92ee62a26f5a9e5167a0ade2"
|
||||
checksum = "527735ac204efb9fa3884bfd9224d016c5735fabe1d394ebed145b40e7545b99"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"async-trait",
|
||||
@@ -2548,9 +2566,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-core"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08973c4853cef4c682f7a592907e81a32dcad69476c4846e5de079f16448b177"
|
||||
checksum = "6a7ffe2f5acf9f94fd255cfd1438866bc9124f8f0c7d42562bd3f853df2094b7"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"async-trait",
|
||||
@@ -2600,15 +2618,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-error"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9fa97a500e7e5c27a7b8609b9294c8922c9656322285268bfad9520f12feb38"
|
||||
checksum = "b23f7bc013de67e44ed902a82843f6157460b89d11da882bcc6f09f8ae380af1"
|
||||
|
||||
[[package]]
|
||||
name = "pingora-header-serde"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2705feb8b50d4e734e0c7d3879aa040e655a45656276323ff530e254585dd816"
|
||||
checksum = "828c0e53e74160cbfe8e67dd3a811eb6a253c36acbaf7a39a01d9aacfb9ac139"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
@@ -2622,9 +2640,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-http"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbb52d4651b687fab6abf669539cfd97b7cd94b301fde8f57c63354f9c9cc5e2"
|
||||
checksum = "d553d310a15ec88107b9388a02885f798efc57764d8e9bdaaf32a76722927a10"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
@@ -2633,27 +2651,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-ketama"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0286fb5a0359dca1e2e137dfe14ca4d94f676635a5eae4616bb3d8d4ce06d120"
|
||||
checksum = "3e2a2e43a14f1d291fba7905542c7c1d1f89528f470b3cd48b6806e702ea772f"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pingora-limits"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7568624fc0e2f11fa32d27053ac862048b40bad98140b07a11d82f1b4989700"
|
||||
checksum = "4bafc633ceb95dc8b39a0d1b52d105758ae0913d360ef3a3365a6f6494d0fe17"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pingora-load-balancing"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2606e9e22e72927a69772cefe56b0d41d251c3ffdfcd548a6020fe157fb79ad"
|
||||
checksum = "361b69af0234d2e4d10234e2efd106bb3b8147c575d52f45604a46aaf26def7a"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"async-trait",
|
||||
@@ -2673,9 +2691,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-lru"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91bb5030596a3d442c0866ac68afe29c14ba558e77c726dcdf7016b0dbb359d9"
|
||||
checksum = "6705a26ad89d241a989a5395641931ba37076f5ab5fbd19ee92402414a43af32"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"hashbrown 0.17.0",
|
||||
@@ -2685,9 +2703,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-openssl"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cb7f135948a5c5a28a634e40fabd40c2588c757372f8a358bfca634a56514a6"
|
||||
checksum = "5f288cacd77196168db0f6ae80817bc4844a8dd1448b75bb2da935eb6d9c3118"
|
||||
dependencies = [
|
||||
"foreign-types",
|
||||
"libc",
|
||||
@@ -2698,9 +2716,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-pool"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67f034be36772f318370d058913db43dbd22c3763ad974c995ba2e4afb2bb52a"
|
||||
checksum = "feb1237893b15a9cf6b371bee8d7e2e1c10742e4be6eb00ed38cfe87fd1363f8"
|
||||
dependencies = [
|
||||
"crossbeam-queue",
|
||||
"log",
|
||||
@@ -2713,9 +2731,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-proxy"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e1e070a98a70d0d05f2fdcfb706237e06a043b2fbc9261e8772a3459cc2175e"
|
||||
checksum = "8a92ee756ecf6ecb6419864da651cad6cecd933b6d420a26877031efa16bef57"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
@@ -2736,9 +2754,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-runtime"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e371315b1c44c2e5a8788fdc61577527b785e121e6ff49144755f40d86511430"
|
||||
checksum = "41815a13691a3e7d9ad0e34767d4140284132e31b95a4481f5e73ab6f407f834"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rand 0.8.6",
|
||||
@@ -2748,9 +2766,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pingora-timeout"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a853fee5ce510a7f5db2561f99c752724112ed13fc3820e70d462d278d704ea"
|
||||
checksum = "8e3e321452eaa461e0b6c5aaa35b7e42527ee89df33710279f37fae7f066b68e"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
@@ -3173,7 +3191,7 @@ dependencies = [
|
||||
"tokio-rustls",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-http 0.6.11",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
@@ -3497,6 +3515,16 @@ dependencies = [
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_ignored"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.150"
|
||||
@@ -3546,21 +3574,6 @@ dependencies = [
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yml"
|
||||
version = "0.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
|
||||
dependencies = [
|
||||
"indexmap 2.14.0",
|
||||
"itoa",
|
||||
"libyml",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sfv"
|
||||
version = "0.10.4"
|
||||
@@ -3880,37 +3893,6 @@ dependencies = [
|
||||
"trackable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-ctl"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a184c43b8ab2f41df2733b55556e3f5f632f4aeaa205b1bb018f574b7f5f142"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"paste",
|
||||
"tikv-jemalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-sys"
|
||||
version = "0.7.1+5.3.1-0-g81034ce1f1373e37dc865038e1bc8eeecf559ce8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a2825c78386b4ae0314074867860ba9577875de945f05992c38815cbec327f0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemallocator"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "249f09e49ab1609436f34c776e84231bead18d6a955f119f939bdc1d847561bd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tikv-jemalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.47"
|
||||
@@ -4104,6 +4086,24 @@ name = "tower-http"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"pin-project-lite",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233"
|
||||
dependencies = [
|
||||
"bitflags 2.11.1",
|
||||
"bytes",
|
||||
@@ -4120,10 +4120,8 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
27
Cargo.toml
27
Cargo.toml
@@ -1,7 +1,11 @@
|
||||
[package]
|
||||
name = "aralez"
|
||||
version = "0.9.2"
|
||||
version = "0.92.11"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
description = "Reverse proxy built on top of Cloudflare's Pingora"
|
||||
exclude = ["configs/*"]
|
||||
repository = "https://github.com/sadoyan/aralez"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
@@ -12,20 +16,20 @@ strip = true
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.52.3", features = ["full"] }
|
||||
pingora = { version = "0.8.0", features = ["lb", "openssl"] } # openssl, rustls, boringssl
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
pingora = { version = "0.8.1", features = ["lb", "openssl"] } # openssl, rustls, boringssl
|
||||
pingora-core = "0.8.1"
|
||||
pingora-proxy = "0.8.1"
|
||||
pingora-http = "0.8.1"
|
||||
pingora-limits = "0.8.1"
|
||||
dashmap = "7.0.0-rc2"
|
||||
pingora-core = "0.8.0"
|
||||
pingora-proxy = "0.8.0"
|
||||
pingora-http = "0.8.0"
|
||||
pingora-limits = "0.8.0"
|
||||
async-trait = "0.1.89"
|
||||
log = "0.4.30"
|
||||
futures = "0.3.32"
|
||||
notify = "9.0.0-rc.4"
|
||||
axum = { version = "0.8.9" }
|
||||
reqwest = { version = "0.13.4", features = ["json", "stream", "blocking"] }
|
||||
serde_yml = "0.0.12"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
noyalib = { version = "0.0.8", features = ["compat-serde-yaml"] }
|
||||
rand = "0.10.1"
|
||||
base64 = "0.22.1"
|
||||
jsonwebtoken = { version = "10.4.0", default-features = false, features = ["use_pem", "rust_crypto"] }
|
||||
@@ -37,7 +41,7 @@ arc-swap = "1.9.1"
|
||||
prometheus = "0.14.0"
|
||||
x509-parser = "0.18.1"
|
||||
rustls-pemfile = "2.2.0"
|
||||
tower-http = { version = "0.6.11", features = ["fs"] }
|
||||
tower-http = { version = "0.7.0", features = ["fs"] }
|
||||
privdrop = "0.5.6"
|
||||
serde_json = "1.0.150"
|
||||
subtle = "2.6.1"
|
||||
@@ -46,8 +50,7 @@ ahash = "0.8.12"
|
||||
instant-acme = "0.8.5"
|
||||
rcgen = "0.14.8"
|
||||
log4rs = "1.4.0"
|
||||
#mimalloc = { version = "0.1.52", default-features = false }
|
||||
tikv-jemallocator = "0.7.0"
|
||||
tikv-jemalloc-ctl = { version = "0.7.0", features = ["stats"] }
|
||||
mimalloc = { version = "0.1.52", default-features = false }
|
||||
signal-hook = "0.4.4"
|
||||
sd-notify = "0.5.0"
|
||||
libc = "0.2.186"
|
||||
|
||||
23
README.md
23
README.md
@@ -9,13 +9,23 @@
|
||||
Aralez is a high-performance Rust reverse proxy with zero-configuration automatic protocol handling, TLS, and upstream management,
|
||||
featuring Consul and Kubernetes integration for dynamic pod discovery and health-checked routing, acting as a lightweight ingress-style proxy.
|
||||
|
||||
|
||||
---
|
||||
What Aralez means ?
|
||||
**Aralez = Արալեզ** <ins>Named after the legendary Armenian guardian spirit, winged dog-like creature, that descend upon fallen heroes to lick their wounds and resurrect them</ins>.
|
||||
|
||||
Built on Rust, on top of **Cloudflare’s Pingora engine**, **Aralez** delivers world-class performance, security and scalability — right out of the box.
|
||||
|
||||
[](https://www.buymeacoffee.com/sadoyan)
|
||||
---
|
||||
|
||||
## Links
|
||||
|
||||
- [**Documentation**](https://aralez.rs) : The manual you should read
|
||||
- [**Downloads**](https://github.com/sadoyan/aralez/releases) : Binary downloads
|
||||
- [**Issues**](https://github.com/sadoyan/aralez/issues) : Issues and requests
|
||||
- [**Crates**](https://crates.io/crates/aralez) : The Rust crate registry
|
||||
- [**DockerHUB**](https://hub.docker.com/r/sadoyan/aralez) : DockerHUB official repository
|
||||
- [**GitHUB Packages**](https://github.com/sadoyan/aralez/pkgs/container/aralez) : GitHUB ghcr.io images
|
||||
|
||||
---
|
||||
|
||||
@@ -64,6 +74,7 @@ Built on Rust, on top of **Cloudflare’s Pingora engine**, **Aralez** delivers
|
||||
| **proxy_address_tls** | 0.0.0.0:6194 | Aralez HTTPS bind address (Optional) |
|
||||
| **proxy_configs** | /etc/aralez/ | Direcotry containing configuration files, must be writeable by user `aralez` |
|
||||
| **upstreams_conf** | /etc/aralez/upstreams.yaml | Location of the upstreams file |
|
||||
| **access_log** | access | Configure access logging. Values: `access, error` |
|
||||
| **log_level** | info | Log level: `info`, `warn`, `error`, `debug`, `trace`, `off` |
|
||||
| **log_file** | /full/path/to/aralez.log | Optional, the location of log file. If thi entry does not exist logs will be emitted to stdout. |
|
||||
| **hc_method** | HEAD | Healthcheck method: HEAD, GET, POST (UPPERCASE) |
|
||||
@@ -107,6 +118,9 @@ For getting the best performance on newer hardware use `aralez-x86_64-*.gz`.
|
||||
|
||||
```shell
|
||||
docker run -d -v /path/to/config:/etc/aralez:rw -p 80:80 -p 443:443 sadoyan/aralez
|
||||
docker run -d -v /path/to/config:/etc/aralez:rw -p 80:80 -p 443:443 sadoyan/aralez:compat
|
||||
docker run -d -v /path/to/config:/etc/aralez:rw -p 80:80 -p 443:443 ghcr.io/sadoyan/aralez:latest
|
||||
docker run -d -v /path/to/config:/etc/aralez:rw -p 80:80 -p 443:443 ghcr.io/sadoyan/aralez:compat
|
||||
```
|
||||
|
||||
**Dockerfile :**
|
||||
@@ -554,10 +568,3 @@ The results show requests per second performed by Load balancer. You can see 3 b
|
||||
1. Requests via http1.1 to plain text endpoint.
|
||||
2. Requests to via http2 to SSL endpoint.
|
||||
3. Mixed workload with plain http1.1 and htt2 SSL.
|
||||
|
||||
## Links
|
||||
|
||||
- [**Documentation**](https://aralez.rs) : The manual you should read
|
||||
- [**Downloads**](https://github.com/sadoyan/aralez/releases) : Binary downloads
|
||||
- [**Issues**](https://github.com/sadoyan/aralez/issues) : Issues and requests
|
||||
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
# Main configuration file, applied on startup
|
||||
threads: 12 # Number of daemon threads default setting
|
||||
#runuser: pastor # Username for running aralez after dropping root privileges, requires program to start as root
|
||||
#rungroup: pastor # Group for running aralez after dropping root privileges, requires program to start as root
|
||||
daemon: false # Run in background
|
||||
runuser: aralez # Username for running aralez after dropping root privileges, requires program to start as root
|
||||
rungroup: aralez # Group for running aralez after dropping root privileges, requires program to start as root
|
||||
upstream_keepalive_pool_size: 500 # Pool size for upstream keepalive connections
|
||||
pid_file: /tmp/aralez.pid # Path to PID file
|
||||
error_log: /tmp/aralez_err.log # Path to error log
|
||||
upgrade_sock: /tmp/aralez.sock # Path to socket file
|
||||
config_api_enabled: true # Boolean to enable/disable remote config push capability.
|
||||
config_address: 0.0.0.0:3000 # HTTP API address for pushing upstreams.yaml from remote location
|
||||
proxy_address_http: 0.0.0.0:6193 # Proxy HTTP bind address
|
||||
proxy_address_tls: 0.0.0.0:6194 # Optional, Proxy TLS bind address
|
||||
proxy_configs: /opt/Rust/Projects/asyncweb/etc # Mandatory if proxy_address_tls set, should contain a certificate and key files strictly in a format {NAME}.crt, {NAME}.key.
|
||||
config_address: 127.0.0.1:3000 # HTTP API address for pushing upstreams.yaml from remote location
|
||||
proxy_address_http: 0.0.0.0:80 # Proxy HTTP bind address
|
||||
proxy_address_tls: 0.0.0.0:443 # Optional, Proxy TLS bind address
|
||||
proxy_configs: /opt/aralez/asyncweb/etc # Mandatory if proxy_address_tls set, should contain a certificate and key files strictly in a format {NAME}.crt, {NAME}.key.
|
||||
proxy_tls_grade: high # Grade of TLS suite for proxy (high, medium, unsafe), matching grades of Qualys SSL Labs
|
||||
upstreams_conf: /opt/Rust/Projects/asyncweb/etc/upstreams.yaml # the location of upstreams file
|
||||
#file_server_folder: /opt/storage # Optional, local folder to serve
|
||||
#file_server_address: 127.0.0.1:3002 # Optional, Local address for file server. Can set as upstream for public access.
|
||||
upstreams_conf: /opt/aralez/etc/upstreams.yaml # the location of upstreams file
|
||||
file_server_folder: /opt/aralez/public # Optional, local folder to serve
|
||||
file_server_address: 0.0.0.0:3002 # Optional, Local address for file server. Can set as upstream for public access.
|
||||
log_level: info # info, warn, error, debug, trace, off
|
||||
log_file: /tmp/aralez.log # Optional, the location of log file. If this entry does not exist logs will be emitted to stdout.
|
||||
access_log: error # all, error, (Off if commented)
|
||||
hc_method: HEAD # Healthcheck method (HEAD, GET, POST are supported) UPPERCASE
|
||||
hc_interval: 2 #Interval for health checks in seconds
|
||||
#master_key: 910517d9-f9a1-48de-8826-dbadacbd84af-cb6f830e-ab16-47ec-9d8f-0090de732774 # Mater key for working with API server and JWT Secret
|
||||
tcp_keepalive_idle: 60 # Seconds of inactivity before the kernel starts sending keepalive probes to a downstream client
|
||||
tcp_keepalive_interval: 10 # Seconds between individual keepalive probes if the client does not respond
|
||||
tcp_keepalive_count: 5 # Number of unanswered probes before the kernel declares the connection dead and closes it
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
provider: "file"
|
||||
globals:
|
||||
headers:
|
||||
- "Access-Control-Allow-Origin:*"
|
||||
- "Access-Control-Allow-Methods:POST, GET, OPTIONS"
|
||||
- "Access-Control-Max-Age:86400"
|
||||
- "X-Custom-Header:Something Special"
|
||||
upstreams:
|
||||
myip.netangels.net:
|
||||
paths:
|
||||
"/":
|
||||
ssl: false
|
||||
headers:
|
||||
- "X-Proxy-From:Aralez"
|
||||
servers:
|
||||
- "192.168.221.213:8000"
|
||||
- "192.168.221.214:8000"
|
||||
- "192.168.221.210:8000"
|
||||
- "192.168.221.212:8000"
|
||||
@@ -1,49 +1,44 @@
|
||||
# The file under watch and hot reload, changes are applied immediately, no need to restart or reload.
|
||||
provider: "file" # "file" "consul" "kubernetes"
|
||||
sticky_sessions: 8600
|
||||
sticky_sessions: 172000
|
||||
to_https: false
|
||||
rate_limit: 300
|
||||
x4xx_limit: 200
|
||||
rate_limit: 500000
|
||||
x4xx_limit: 100000
|
||||
server_headers:
|
||||
- "X-Forwarded-Proto:https"
|
||||
- "X-Forwarded-Port:443"
|
||||
- "Y-Global-Something: Something For Servers"
|
||||
client_headers:
|
||||
- "Access-Control-Allow-Origin:*"
|
||||
- "Access-Control-Allow-Methods:POST, GET, OPTIONS"
|
||||
- "Access-Control-Max-Age:86400"
|
||||
- "X-Global-Something: Something For Clients"
|
||||
#authorization:
|
||||
# type: "jwt"
|
||||
# creds: "910517d9-f9a1-48de-8826-dbadacbd84af-cb6f830e-ab16-47ec-9d8f-0090de732774"
|
||||
# type: "basic"
|
||||
# creds: "username:Pa$$w0rd"
|
||||
# data: "root:toor"
|
||||
# type: "jwt"
|
||||
# data: "910517d9-f9a1-48de-8826-dbadacbd84af-cb6f830e-ab16-47ec-9d8f-0090de732774"
|
||||
# type: "apikey"
|
||||
# creds: "5ecbf799-1343-4e94-a9b5-e278af5cd313-56b45249-1839-4008-a450-a60dc76d2bae"
|
||||
# data: "5ecbf799-1343-4e94-a9b5-e278af5cd313-56b45249-1839-4008-a450-a60dc76d2bae"
|
||||
consul:
|
||||
servers:
|
||||
- "http://192.168.1.199:8500"
|
||||
- "http://192.168.1.200:8500"
|
||||
- "http://192.168.1.201:8500"
|
||||
- "http://consul1:8500"
|
||||
services: # hostname: The hostname to access the proxy server, upstream : The real service name in Consul database.
|
||||
- hostname: "webapi-service"
|
||||
upstream: "webapi-service-health"
|
||||
- hostname: "nconsul"
|
||||
upstream: "nginx-consul-NginX-health"
|
||||
path: "/one"
|
||||
client_headers:
|
||||
- "X-Some-Thing:Yaaaaaaaaaaaaaaa"
|
||||
- "X-Proxy-From:Aralez"
|
||||
rate_limit: 1
|
||||
to_https: false
|
||||
- hostname: "webapi-service"
|
||||
upstream: "webapi-service-health"
|
||||
- hostname: "nconsul"
|
||||
upstream: "nginx-consul-NginX-health"
|
||||
path: "/"
|
||||
token: "8e2db809-845b-45e1-8b47-2c8356a09da0-a4370955-18c2-4d6e-a8f8-ffcc0b47be81" # Consul server access token, If Consul auth is enabled
|
||||
kubernetes:
|
||||
servers:
|
||||
- "192.168.1.55:443" #For testing only, overrides with KUBERNETES_SERVICE_HOST : KUBERNETES_SERVICE_PORT_HTTPS env variables.
|
||||
- "172.16.0.11:5443" # Gets KUBERNETES_SERVICE_HOST : KUBERNETES_SERVICE_PORT_HTTPS env variables.
|
||||
services:
|
||||
- hostname: "webapi-service"
|
||||
- hostname: "api-service"
|
||||
upstream: "api-service"
|
||||
path: "/"
|
||||
upstream: "webapi-service"
|
||||
- hostname: "webapi-service"
|
||||
- hostname: "api-service"
|
||||
upstream: "console-service"
|
||||
path: "/one"
|
||||
client_headers:
|
||||
@@ -51,71 +46,92 @@ kubernetes:
|
||||
- "X-Proxy-From:Aralez"
|
||||
rate_limit: 100
|
||||
to_https: false
|
||||
- hostname: "webapi-service"
|
||||
upstream: "rambul-service"
|
||||
- hostname: "api-service"
|
||||
upstream: "feed-fanout-service"
|
||||
path: "/two"
|
||||
- hostname: "websocket-service"
|
||||
upstream: "websocket-service"
|
||||
path: "/"
|
||||
tokenpath: "/path/to/kubetoken.txt" #If not set, will default to /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
tokenpath: "/opt/Rust/Projects/asyncweb/etc/kubetoken.txt" # Defaults to /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
upstreams:
|
||||
myip.mydomain.com:
|
||||
www.example.com:
|
||||
paths:
|
||||
"/":
|
||||
rate_limit: 200
|
||||
rate_limit: 50
|
||||
x4xx_limit: 100
|
||||
to_https: false
|
||||
client_headers:
|
||||
- "X-Proxy-From:Aralez"
|
||||
servers:
|
||||
- "127.0.0.1:8000"
|
||||
- "127.0.0.2:8000"
|
||||
- "127.0.0.3:8000"
|
||||
- "127.0.0.4:8000"
|
||||
- "127.0.0.5:8000"
|
||||
"/ping":
|
||||
authorization: # Will be ignored if global authentication is enabled.
|
||||
authorization:
|
||||
type: "basic"
|
||||
creds: "admin:admin"
|
||||
to_https: false
|
||||
data: "root:toor"
|
||||
server_headers:
|
||||
- "X-Forwarded-Proto:https"
|
||||
- "X-Forwarded-Port:443"
|
||||
- "Y-Proxy-Server-Some:Yaaaaaaaaaaaaaaa"
|
||||
- "Y-Proxy-Server-From:Aralez"
|
||||
- "Y-Proxy-Server-Vers:Aralez v-xxx"
|
||||
client_headers:
|
||||
- "X-Some-Thing:Yaaaaaaaaaaaaaaa"
|
||||
- "X-Proxy-From:Aralez"
|
||||
- "Access-Control-Allow-Origin:*"
|
||||
- "Access-Control-Allow-Methods:POST, GET, OPTIONS"
|
||||
- "Access-Control-Max-Age:86400"
|
||||
- "Strict-Transport-Security:max-age=31536000; includeSubDomains; preload"
|
||||
servers:
|
||||
- "127.0.0.1:8000"
|
||||
- "127.0.0.2:8000"
|
||||
"/draw":
|
||||
servers:
|
||||
- "192.168.1.1:8000"
|
||||
polo.mydomain.com:
|
||||
paths:
|
||||
"/":
|
||||
to_https: false
|
||||
client_headers:
|
||||
- "X-Some-Thing:Yaaaaaaaaaaaaaaa"
|
||||
servers:
|
||||
- "192.168.1.1:8000"
|
||||
- "192.168.1.10:8000"
|
||||
- "127.0.0.1:8000"
|
||||
- "127.0.0.2:8000"
|
||||
- "127.0.0.3:8000"
|
||||
- "127.0.0.4:8000"
|
||||
apt.mydomain.com:
|
||||
"/ping":
|
||||
to_https: true
|
||||
client_headers:
|
||||
- "X-Some-Thing:Something Else"
|
||||
- "Access-Control-Allow-Origin:*"
|
||||
- "Access-Control-Allow-Methods:POST, GET, OPTIONS"
|
||||
- "Access-Control-Max-Age:86400"
|
||||
- "Strict-Transport-Security:max-age=31536000; includeSubDomains; preload"
|
||||
servers:
|
||||
- "127.0.0.1:8000"
|
||||
"/secret":
|
||||
authorization:
|
||||
type: "forward"
|
||||
data: "http://127.0.0.1:8899/admin/login"
|
||||
servers:
|
||||
- "127.0.0.10:8000"
|
||||
example.com:
|
||||
paths:
|
||||
"/":
|
||||
redirect_to: "https://www.example.com:443"
|
||||
servers:
|
||||
- "192.168.1.10:443"
|
||||
- "127.0.0.1:80"
|
||||
h2.example.com:
|
||||
paths:
|
||||
"/":
|
||||
server_headers:
|
||||
- "Y-Global-Something: Yes this is something"
|
||||
client_headers:
|
||||
- "Access-Control-Allow-Methods:POST, GET, OPTIONS"
|
||||
rate_limit: 60
|
||||
x4xx_limit: 30
|
||||
authorization:
|
||||
type: "jwt"
|
||||
servers:
|
||||
- "127.0.0.1:8000"
|
||||
- "127.0.0.2:8000"
|
||||
"/.well-known/acme-challenge":
|
||||
healthcheck: false
|
||||
servers:
|
||||
- "127.0.0.1:8001"
|
||||
rdr.mydomain.com:
|
||||
paths:
|
||||
"/":
|
||||
redirect_to: "https://som.other.domain:6194"
|
||||
"/400":
|
||||
rate_limit: 4
|
||||
x4xx_limit: 2
|
||||
servers:
|
||||
- "127.0.0.1:8899"
|
||||
"/500":
|
||||
healthcheck: false
|
||||
servers:
|
||||
- "127.0.0.1:8080"
|
||||
- "127.0.0.1:8899"
|
||||
DEFAULT:
|
||||
paths:
|
||||
"/":
|
||||
healthcheck: false
|
||||
servers:
|
||||
- "127.0.0.1:3000"
|
||||
"/.well-known/acme-challenge":
|
||||
healthcheck: false
|
||||
servers:
|
||||
- "127.0.0.1:3000"
|
||||
|
||||
10
src/main.rs
10
src/main.rs
@@ -1,14 +1,16 @@
|
||||
use tikv_jemallocator::Jemalloc;
|
||||
|
||||
mod tls;
|
||||
mod utils;
|
||||
mod web;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOC: Jemalloc = Jemalloc;
|
||||
// static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||
// pub static A: CountingAllocator = CountingAllocator;
|
||||
|
||||
fn main() {
|
||||
if std::env::args().any(|a| a == "--version" || a == "-v") {
|
||||
println!("aralez {}", env!("CARGO_PKG_VERSION"));
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
web::start::run();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ use prometheus::{register_histogram, register_int_counter, register_int_counter_
|
||||
use std::sync::Arc;
|
||||
use std::sync::LazyLock;
|
||||
use std::time::Duration;
|
||||
use tikv_jemalloc_ctl::{epoch, stats};
|
||||
|
||||
pub struct MetricTypes {
|
||||
pub method: Method,
|
||||
@@ -66,9 +65,17 @@ pub fn calc_metrics(metric_types: &MetricTypes) {
|
||||
RESPONSE_LATENCY.observe(metric_types.latency.as_secs_f64());
|
||||
}
|
||||
|
||||
pub fn get_memory_usage() -> usize {
|
||||
epoch::mib().unwrap().advance().unwrap(); // refresh stats
|
||||
stats::allocated::mib().unwrap().read().unwrap() // bytes allocated
|
||||
pub(crate) fn get_memory_usage() -> usize {
|
||||
std::fs::read_to_string("/proc/self/status")
|
||||
.ok()
|
||||
.and_then(|s| {
|
||||
s.lines()
|
||||
.find(|l| l.starts_with("VmRSS:"))
|
||||
.and_then(|l| l.split_whitespace().nth(1))
|
||||
.and_then(|v| v.parse::<usize>().ok())
|
||||
})
|
||||
.unwrap_or(0)
|
||||
* 1024
|
||||
}
|
||||
|
||||
pub fn get_open_files() -> usize {
|
||||
|
||||
@@ -108,7 +108,7 @@ pub async fn load_configuration(d: &str, kind: &str) -> (Option<Configuration>,
|
||||
}
|
||||
};
|
||||
|
||||
let mut parsed: Config = match serde_yml::from_str(&yaml_data) {
|
||||
let mut parsed: Config = match noyalib::from_str(&yaml_data) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(e) => {
|
||||
error!("Failed to parse upstreams file: {}", e);
|
||||
@@ -118,7 +118,7 @@ pub async fn load_configuration(d: &str, kind: &str) -> (Option<Configuration>,
|
||||
|
||||
if let Some(ref mut upstreams) = parsed.upstreams {
|
||||
for uconf in conf_files {
|
||||
let p: HashMap<String, HostConfig> = match serde_yml::from_str(&uconf) {
|
||||
let p: HashMap<String, HostConfig> = match noyalib::from_str(&uconf) {
|
||||
Ok(ucfg) => ucfg,
|
||||
Err(e) => {
|
||||
error!("Failed to parse upstreams file: {}", e);
|
||||
@@ -264,19 +264,13 @@ async fn populate_file_upstreams(config: &mut Configuration, parsed: &Config) {
|
||||
}
|
||||
pub fn parce_main_config(path: &str) -> AppConfig {
|
||||
let data = fs::read_to_string(path).unwrap();
|
||||
let reply = DashMap::new();
|
||||
let cfg: HashMap<String, String> = serde_yml::from_str(&data).expect("Failed to parse main config file");
|
||||
let mut cfo: AppConfig = serde_yml::from_str(&data).expect("Failed to parse main config file");
|
||||
|
||||
let mut cfo: AppConfig = noyalib::from_str(&data).expect("Failed to parse main config file");
|
||||
if let Ok(jwt_key) = env::var("JWT_KEY") {
|
||||
cfo.master_key = Some(jwt_key);
|
||||
};
|
||||
|
||||
log_builder(&cfo, &cfo.log_file);
|
||||
cfo.hc_method = cfo.hc_method.to_uppercase();
|
||||
for (k, v) in cfg {
|
||||
reply.insert(k.to_string(), v.to_string());
|
||||
}
|
||||
if let Some((ip, port_str)) = cfo.config_address.split_once(':') {
|
||||
if let Ok(port) = port_str.parse::<u16>() {
|
||||
cfo.local_server = Option::from((ip.to_string(), port));
|
||||
|
||||
@@ -112,6 +112,8 @@ pub struct AppConfig {
|
||||
pub hc_method: String,
|
||||
pub upstreams_conf: String,
|
||||
pub log_level: String,
|
||||
pub access_log: Option<String>,
|
||||
pub pid_file: Option<String>,
|
||||
pub master_key: Option<String>,
|
||||
pub config_address: String,
|
||||
pub proxy_address_http: String,
|
||||
@@ -130,6 +132,9 @@ pub struct AppConfig {
|
||||
pub runuser: Option<String>,
|
||||
pub rungroup: Option<String>,
|
||||
pub log_file: Option<String>,
|
||||
pub tcp_keepalive_idle: Option<u64>,
|
||||
pub tcp_keepalive_interval: Option<u64>,
|
||||
pub tcp_keepalive_count: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
|
||||
|
||||
@@ -10,9 +10,12 @@ use sha2::{Digest, Sha256};
|
||||
use std::any::type_name;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Write;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write as IoWrite;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::TcpListener;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
@@ -274,7 +277,7 @@ pub fn drop_priv(user: String, group: String, http_addr: String, tls_addr: Optio
|
||||
}
|
||||
|
||||
pub fn check_priv(addr: &str) {
|
||||
let port = SocketAddr::from_str(addr).map(|sa| sa.port()).unwrap();
|
||||
let port = SocketAddr::from_str(addr).map(|sa| sa.port()).expect("Failed to parse address port ");
|
||||
if port < 1024 {
|
||||
let meta = std::fs::metadata("/proc/self").map(|m| m.uid()).unwrap();
|
||||
if meta != 0 {
|
||||
@@ -380,3 +383,14 @@ pub fn prepend(prefix: &str, val: &Option<Arc<str>>, uri: &str, port: &str) -> O
|
||||
buf
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_pid_file(path: &str) -> std::io::Result<()> {
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.custom_flags(libc::O_NOFOLLOW) // refuse to follow symlinks
|
||||
.open(path)?;
|
||||
file.write_all(process::id().to_string().as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod acme;
|
||||
pub mod bgservice;
|
||||
pub mod gethosts;
|
||||
pub mod logging;
|
||||
pub mod proxyhttp;
|
||||
pub mod start;
|
||||
pub mod webserver;
|
||||
|
||||
57
src/web/logging.rs
Normal file
57
src/web/logging.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use log::info;
|
||||
use pingora_proxy::Session;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub static ACCESS_LOG: OnceLock<LogLevel> = OnceLock::new();
|
||||
|
||||
pub fn init_access_log(level_str: &str) {
|
||||
let level = LogLevel::from_str(level_str);
|
||||
let _ = ACCESS_LOG.set(level);
|
||||
}
|
||||
|
||||
pub enum LogLevel {
|
||||
Access,
|
||||
Error,
|
||||
None,
|
||||
}
|
||||
|
||||
impl LogLevel {
|
||||
pub fn from_str(s: &str) -> Self {
|
||||
match s {
|
||||
"all" => LogLevel::Access,
|
||||
"error" => LogLevel::Error,
|
||||
_ => LogLevel::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn access_log(response_code: u16, summary: &str, session: &Session) {
|
||||
let level = ACCESS_LOG.get().unwrap_or(&LogLevel::None);
|
||||
|
||||
let should_log = match level {
|
||||
LogLevel::Access => true,
|
||||
LogLevel::None => false,
|
||||
LogLevel::Error => !(100..=399).contains(&response_code),
|
||||
};
|
||||
|
||||
if !should_log {
|
||||
return;
|
||||
}
|
||||
|
||||
let ip = session
|
||||
.client_addr()
|
||||
.and_then(|addr| addr.as_inet())
|
||||
.map(|addr| addr.ip())
|
||||
.unwrap_or(IpAddr::V4(Ipv4Addr::LOCALHOST));
|
||||
|
||||
let user_agent = session.req_header().headers.get("user-agent").and_then(|v| v.to_str().ok()).unwrap_or("-");
|
||||
|
||||
info!(
|
||||
"{}, response code: {response_code}, client: {}, version: {:?}, useragent: {}",
|
||||
summary,
|
||||
ip,
|
||||
session.req_header().version,
|
||||
user_agent,
|
||||
);
|
||||
}
|
||||
@@ -3,10 +3,11 @@ use crate::utils::lazylock::{LOCALHOST, RATE_LIMITER, REQUESTS_4XX, REVERSE_STOR
|
||||
use crate::utils::metrics::*;
|
||||
use crate::utils::structs::{AppConfig, Extraparams, Headers, InnerMap, UpstreamsDashMap, UpstreamsIdMap};
|
||||
use crate::web::gethosts::{GetHost, GetHostsReturHeaders};
|
||||
use crate::web::logging::access_log;
|
||||
use arc_swap::ArcSwap;
|
||||
use async_trait::async_trait;
|
||||
use axum::body::Bytes;
|
||||
use log::{debug, error, warn};
|
||||
use log::error;
|
||||
use pingora::http::{RequestHeader, ResponseHeader, StatusCode};
|
||||
use pingora::prelude::*;
|
||||
use pingora::ErrorSource::Upstream;
|
||||
@@ -20,10 +21,6 @@ use std::sync::Arc;
|
||||
use tokio::time::Instant;
|
||||
|
||||
thread_local! {static IP_BUFFER: RefCell<String> = RefCell::new(String::with_capacity(50));}
|
||||
// static REVERSE_STORE: LazyLock<DashMap<String, String>> = LazyLock::new(DashMap::new);
|
||||
// pub static RATE_LIMITER: LazyLock<Rate> = LazyLock::new(|| Rate::new(Duration::from_secs(1)));
|
||||
// pub static REQUESTS_4XX: LazyLock<Cache<IpAddr, u32>> = LazyLock::new(|| Cache::builder().time_to_live(Duration::from_secs(1)).build());
|
||||
// pub static LOCALHOST: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("localhost"));
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LB {
|
||||
@@ -86,7 +83,6 @@ impl ProxyHttp for LB {
|
||||
if let Some(auth) = _ctx.extraparams.authentication.as_ref().or(innermap.authorization.as_ref()) {
|
||||
if !authenticate(&auth, session).await {
|
||||
let _ = session.respond_error(401).await;
|
||||
warn!("Forbidden: {:?}, {}", session.client_addr(), session.req_header().uri.path());
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@@ -99,9 +95,9 @@ impl ProxyHttp for LB {
|
||||
let header = ResponseHeader::build(429, None)?;
|
||||
session.set_keepalive(None);
|
||||
session.write_response_header(Box::new(header), true).await?;
|
||||
if let (Some(oi), Some(oa)) = (&_ctx.hostname, rate_key) {
|
||||
warn!("Limit 4XX: {}-rps exceed on {} from {} path {}", rate, oi, oa, session.req_header().uri.path());
|
||||
}
|
||||
// if let (Some(oi), Some(oa)) = (&_ctx.hostname, rate_key) {
|
||||
// warn!("Limit 4XX: {}-rps exceed on {} from {} path {}", rate, oi, oa, session.req_header().uri.path());
|
||||
// }
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@@ -113,9 +109,9 @@ impl ProxyHttp for LB {
|
||||
let header = ResponseHeader::build(429, None)?;
|
||||
session.set_keepalive(None);
|
||||
session.write_response_header(Box::new(header), true).await?;
|
||||
if let (Some(oi), Some(oa)) = (&_ctx.hostname, rate_key) {
|
||||
warn!("Limit: {}-rps exceed on {} from {}", rate, oi, oa);
|
||||
}
|
||||
// if let (Some(oi), Some(oa)) = (&_ctx.hostname, rate_key) {
|
||||
// warn!("Limit: {}-rps exceed on {} from {}", rate, oi, oa);
|
||||
// }
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@@ -177,6 +173,20 @@ impl ProxyHttp for LB {
|
||||
peer.options.verify_cert = false;
|
||||
peer.options.verify_hostname = false;
|
||||
}
|
||||
/*
|
||||
Experimental optionsv
|
||||
The following TCP optimizations were tested but caused performance degrade under heavy load:
|
||||
peer.options.tcp_keepalive = Some(TcpKeepalive {
|
||||
idle: Duration::from_secs(60),
|
||||
interval: Duration::from_secs(10),
|
||||
count: 5,
|
||||
user_timeout: Duration::from_secs(30),
|
||||
});
|
||||
|
||||
peer.options.idle_timeout = Some(Duration::from_secs(300));
|
||||
peer.options.tcp_recv_buf = Some(128 * 1024);
|
||||
End of experimental options
|
||||
*/
|
||||
if let Some(_) = ctx.extraparams.sticky_sessions {
|
||||
let mut s = String::with_capacity(64);
|
||||
write!(
|
||||
@@ -267,14 +277,12 @@ impl ProxyHttp for LB {
|
||||
REVERSE_STORE.insert(hh.clone(), bid.clone());
|
||||
hh
|
||||
};
|
||||
// let _ = _upstream_response.insert_header("set-cookie", format!("backend_id={}; Path=/; Max-Age=600; HttpOnly; SameSite=Lax", tt));
|
||||
let mut buf = String::with_capacity(80);
|
||||
buf.push_str("backend_id=");
|
||||
buf.push_str(&tt);
|
||||
buf.push_str("; Path=/; Max-Age=");
|
||||
buf.push_str(&val.to_string());
|
||||
buf.push_str("; HttpOnly; SameSite=Lax");
|
||||
// buf.push_str("; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax");
|
||||
let _ = _upstream_response.insert_header("set-cookie", buf.as_str());
|
||||
}
|
||||
}
|
||||
@@ -289,7 +297,6 @@ impl ProxyHttp for LB {
|
||||
|
||||
async fn logging(&self, session: &mut Session, _e: Option<&pingora::Error>, ctx: &mut Self::CTX) {
|
||||
let response_code = session.response_written().map_or(0, |resp| resp.status.as_u16());
|
||||
debug!("{}, response code: {response_code}", self.request_summary(session, ctx));
|
||||
let m = &MetricTypes {
|
||||
method: session.req_header().method.clone(),
|
||||
code: session.response_written().map(|resp| resp.status),
|
||||
@@ -300,13 +307,14 @@ impl ProxyHttp for LB {
|
||||
calc_metrics(m);
|
||||
ACTIVE_SESSIONS.dec();
|
||||
if let Some(_) = ctx.x4xx_limit.or(ctx.extraparams.x4xx_limit) {
|
||||
if 400 <= response_code && response_code <= 499 {
|
||||
if (400..=499).contains(&response_code) {
|
||||
if let Some(ip) = session.client_addr().and_then(|a| a.as_inet()).map(|i| i.ip()) {
|
||||
let current = REQUESTS_4XX.get(&ip).unwrap_or(0);
|
||||
REQUESTS_4XX.insert(ip, current + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
access_log(response_code, &self.request_summary(session, ctx), session);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,16 @@ use crate::tls::load;
|
||||
use crate::tls::load::CertificateConfig;
|
||||
use crate::utils::structs::Extraparams;
|
||||
use crate::utils::tools::*;
|
||||
use crate::web::logging::init_access_log;
|
||||
use crate::web::proxyhttp::LB;
|
||||
use arc_swap::ArcSwap;
|
||||
use dashmap::DashMap;
|
||||
use log::info;
|
||||
use pingora::tls::ssl::{SslAlert, SslRef};
|
||||
use pingora_core::listeners::tls::TlsSettings;
|
||||
use pingora_core::listeners::TcpSocketOptions;
|
||||
use pingora_core::prelude::{background_service, Opt};
|
||||
use pingora_core::protocols::TcpKeepalive;
|
||||
use pingora_core::server::Server;
|
||||
use privdrop::reexports::libc::SIGQUIT;
|
||||
use sd_notify::NotifyState;
|
||||
@@ -21,7 +24,7 @@ use signal_hook::{
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::{fs, process, thread};
|
||||
use std::{fs, thread};
|
||||
|
||||
pub fn run() {
|
||||
// default_provider().install_default().expect("Failed to install rustls crypto provider");
|
||||
@@ -57,17 +60,41 @@ pub fn run() {
|
||||
server_headers: sh_config,
|
||||
extraparams: ec_config,
|
||||
};
|
||||
let al = cfg.access_log.clone().unwrap_or("none".to_string());
|
||||
init_access_log(al.as_str());
|
||||
|
||||
let grade = cfg.proxy_tls_grade.clone().unwrap_or("medium".to_string());
|
||||
info!("TLS grade set to: [ {} ]", grade);
|
||||
|
||||
let bg_srvc = background_service("bgsrvc", lb.clone());
|
||||
let mut proxy = pingora_proxy::http_proxy_service(&server.configuration, lb.clone());
|
||||
let bind_address_http = cfg.proxy_address_http.clone();
|
||||
let bind_address_tls = cfg.proxy_address_tls.clone();
|
||||
|
||||
let mut proxy = pingora_proxy::http_proxy_service(&server.configuration, lb.clone());
|
||||
|
||||
check_priv(bind_address_http.as_str());
|
||||
|
||||
// let mut tcp_options: Option<TcpSocketOptions> = Some(TcpSocketOptions::default());
|
||||
// let mut tcp_options = TcpSocketOptions::default();
|
||||
|
||||
let mut tcp_options: Option<TcpSocketOptions> = None;
|
||||
if let Some(idle) = cfg.tcp_keepalive_idle {
|
||||
let mut to = TcpSocketOptions::default();
|
||||
to.tcp_keepalive = Some(TcpKeepalive {
|
||||
idle: Duration::from_secs(idle),
|
||||
interval: Duration::from_secs(cfg.tcp_keepalive_interval.unwrap_or(10)),
|
||||
user_timeout: Default::default(),
|
||||
count: cfg.tcp_keepalive_count.unwrap_or(5usize),
|
||||
});
|
||||
tcp_options = Some(to);
|
||||
info!(
|
||||
"Applying kernel tcp_keepalive parameters: idle {}, interval {}, count {}",
|
||||
idle,
|
||||
cfg.tcp_keepalive_interval.unwrap_or(60),
|
||||
cfg.tcp_keepalive_count.unwrap_or(5),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(bind_address_tls) = bind_address_tls {
|
||||
check_priv(bind_address_tls.as_str());
|
||||
let (tx, rx): (Sender<Vec<CertificateConfig>>, Receiver<Vec<CertificateConfig>>) = channel();
|
||||
@@ -95,7 +122,7 @@ pub fn run() {
|
||||
tls_settings.set_servername_callback(move |ssl_ref: &mut SslRef, ssl_alert: &mut SslAlert| certs_for_callback.load().server_name_callback(ssl_ref, ssl_alert));
|
||||
tls_settings.set_alpn_select_callback(grades::prefer_h2);
|
||||
|
||||
proxy.add_tls_with_settings(&bind_address_tls, None, tls_settings);
|
||||
proxy.add_tls_with_settings(&bind_address_tls, tcp_options.clone(), tls_settings);
|
||||
|
||||
let certs_for_watcher = certificates.clone();
|
||||
thread::spawn(move || {
|
||||
@@ -107,8 +134,13 @@ pub fn run() {
|
||||
}
|
||||
});
|
||||
}
|
||||
info!("Running HTTP listener on :{}", bind_address_http.as_str());
|
||||
proxy.add_tcp(bind_address_http.as_str());
|
||||
info!("Running HTTP listener on :{}", bind_address_http);
|
||||
if let Some(tc) = tcp_options {
|
||||
proxy.add_tcp_with_settings(&bind_address_http, tc);
|
||||
} else {
|
||||
proxy.add_tcp(&bind_address_http)
|
||||
}
|
||||
|
||||
server.add_service(proxy);
|
||||
server.add_service(bg_srvc);
|
||||
thread::spawn(move || server.run_forever());
|
||||
@@ -117,8 +149,11 @@ pub fn run() {
|
||||
drop_priv(user, group, cfg.proxy_address_http.clone(), cfg.proxy_address_tls.clone());
|
||||
}
|
||||
let _ = sd_notify::notify(&[NotifyState::Ready]);
|
||||
let _ = fs::write("/tmp/aralez.pid", process::id().to_string());
|
||||
|
||||
let pf = cfg.pid_file.clone().unwrap_or("/tmp/aralez.pid".to_string());
|
||||
if let Err(e) = write_pid_file(pf.as_str()) {
|
||||
panic!("Failed to write PID file: {} : {}", pf, e);
|
||||
}
|
||||
let mut signals = Signals::new(&[SIGINT, SIGTERM, SIGQUIT]).unwrap();
|
||||
for sig in signals.forever() {
|
||||
match sig {
|
||||
|
||||
@@ -18,6 +18,8 @@ use prometheus::{gather, Encoder, TextEncoder};
|
||||
use serde::Serialize;
|
||||
use signal_hook::{consts::SIGQUIT, iterator::Signals};
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use tokio::net::TcpListener;
|
||||
@@ -67,16 +69,14 @@ pub async fn run_server(config: &APIUpstreamProvider, mut to_return: Sender<Conf
|
||||
|
||||
let mut static_handle: Option<tokio::task::JoinHandle<()>> = None;
|
||||
if let (Some(address), Some(folder)) = (&config.file_server_address, &config.file_server_folder) {
|
||||
port_is_available("File Server", &address).await;
|
||||
let static_listen = port_is_available("File Server", &address).await;
|
||||
let static_files = ServeDir::new(folder);
|
||||
let static_serve: Router = Router::new().fallback_service(static_files);
|
||||
let static_listen = TcpListener::bind(address).await.unwrap();
|
||||
// drop(tokio::spawn(async move { axum::serve(static_listen, static_serve).await.unwrap() }));
|
||||
static_handle = Some(tokio::spawn(async move { axum::serve(static_listen, static_serve).await.unwrap() }))
|
||||
}
|
||||
|
||||
port_is_available("Config API", &config.address).await;
|
||||
let listener = TcpListener::bind(config.address.clone()).await.unwrap();
|
||||
let listener = port_is_available("Config API", &config.address).await;
|
||||
info!("Starting the API server on: {}", config.address);
|
||||
let api_server = tokio::spawn(async move { axum::serve(listener, app).await.unwrap() });
|
||||
|
||||
@@ -102,7 +102,7 @@ async fn conf(State(st): State<AppState>, Query(params): Query<HashMap<String, S
|
||||
}
|
||||
|
||||
let strcontent = content.as_str();
|
||||
let parsed = serde_yml::from_str::<Config>(strcontent);
|
||||
let parsed = noyalib::from_str::<Config>(strcontent);
|
||||
match parsed {
|
||||
Ok(_) => {
|
||||
if let Some(_) = params.get("save") {
|
||||
@@ -227,20 +227,18 @@ async fn status(State(st): State<AppState>, Query(params): Query<HashMap<String,
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn port_is_available(name: &str, address: &str) {
|
||||
let addr_port = address.split(":").collect::<Vec<&str>>();
|
||||
pub async fn port_is_available(name: &str, address: &str) -> TcpListener {
|
||||
let addr = SocketAddr::from_str(address).unwrap_or_else(|e| panic!("{}: Invalid address format: {:?}", name, e));
|
||||
let t = Duration::from_secs(2);
|
||||
|
||||
let mut a = addr_port[0];
|
||||
if address == "0.0.0.0" {
|
||||
a = "127.0.0.1";
|
||||
}
|
||||
let p = addr_port[1].parse::<u16>().unwrap();
|
||||
|
||||
//if addr.ip() == IpAddr::V4(Ipv4Addr::UNSPECIFIED) {
|
||||
// addr.set_ip(IpAddr::V4(Ipv4Addr::LOCALHOST));
|
||||
//}
|
||||
let p = addr.port();
|
||||
loop {
|
||||
match TcpListener::bind((a, p)).await {
|
||||
Ok(_) => {
|
||||
break;
|
||||
match TcpListener::bind(addr).await {
|
||||
Ok(listener) => {
|
||||
return listener;
|
||||
}
|
||||
Err(_) => {
|
||||
warn!("{} port is not available: {} will try again in {:?}", name, p, t);
|
||||
|
||||
Reference in New Issue
Block a user