mirror of
https://github.com/sadoyan/aralez.git
synced 2026-06-22 23:32:40 +08:00
Basic access/error logging. Upgrade to Pingra 8.0.1
This commit is contained in:
42
Cargo.lock
generated
42
Cargo.lock
generated
@@ -127,7 +127,7 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||
|
||||
[[package]]
|
||||
name = "aralez"
|
||||
version = "0.92.10"
|
||||
version = "0.92.11"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"arc-swap",
|
||||
@@ -165,7 +165,7 @@ dependencies = [
|
||||
"subtle",
|
||||
"tokio",
|
||||
"tonic",
|
||||
"tower-http",
|
||||
"tower-http 0.7.0",
|
||||
"urlencoding",
|
||||
"x509-parser",
|
||||
]
|
||||
@@ -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",
|
||||
@@ -2212,9 +2212,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "noyalib"
|
||||
version = "0.0.7"
|
||||
version = "0.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaecb583890b00deddd413f1c9522cc3537e893cd3845dec578ed6c85de653f7"
|
||||
checksum = "14057395c16a4230575c6f86bfa074db87e8458626d3e56b20c2454334a7e50c"
|
||||
dependencies = [
|
||||
"indexmap 2.14.0",
|
||||
"itoa",
|
||||
@@ -3191,7 +3191,7 @@ dependencies = [
|
||||
"tokio-rustls",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tower-http 0.6.11",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
@@ -4086,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",
|
||||
@@ -4102,10 +4120,8 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
18
Cargo.toml
18
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "aralez"
|
||||
version = "0.92.10"
|
||||
version = "0.92.11"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
description = "Reverse proxy built on top of Cloudflare's Pingora"
|
||||
@@ -16,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"] }
|
||||
noyalib = { version = "0.0.7", features = ["compat-serde-yaml"] }
|
||||
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"] }
|
||||
@@ -41,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"
|
||||
|
||||
@@ -74,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) |
|
||||
|
||||
@@ -112,6 +112,7 @@ 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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -281,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());
|
||||
}
|
||||
}
|
||||
@@ -303,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),
|
||||
@@ -314,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,6 +4,7 @@ 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;
|
||||
@@ -59,6 +60,8 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user