Config
This commit is contained in:
parent
ceebd53626
commit
5dc6ca05ce
6 changed files with 187 additions and 24 deletions
101
Cargo.lock
generated
101
Cargo.lock
generated
|
|
@ -17,6 +17,18 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy 0.7.35",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
|
@ -26,6 +38,18 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arraydeque"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.74"
|
version = "0.3.74"
|
||||||
|
|
@ -122,6 +146,25 @@ version = "0.31.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashlink"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hybrid-array"
|
name = "hybrid-array"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
@ -161,6 +204,7 @@ dependencies = [
|
||||||
"realm_io",
|
"realm_io",
|
||||||
"realm_syscall",
|
"realm_syscall",
|
||||||
"regex",
|
"regex",
|
||||||
|
"saphyr",
|
||||||
"sha2",
|
"sha2",
|
||||||
"sha3",
|
"sha3",
|
||||||
"static_cell",
|
"static_cell",
|
||||||
|
|
@ -197,6 +241,12 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
|
@ -215,7 +265,7 @@ version = "0.2.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy",
|
"zerocopy 0.8.24",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -323,6 +373,27 @@ version = "0.1.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "saphyr"
|
||||||
|
version = "0.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d31513a748cdf8fb8d1b64dcc14fdd997fa02f2431671c7ce34efbea5e7eeea"
|
||||||
|
dependencies = [
|
||||||
|
"arraydeque",
|
||||||
|
"hashlink",
|
||||||
|
"saphyr-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "saphyr-parser"
|
||||||
|
version = "0.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "123f0a6da68f3072c7c761450276d1d444cb391c8be182a757cd26cf684cb77f"
|
||||||
|
dependencies = [
|
||||||
|
"arraydeque",
|
||||||
|
"hashlink",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.11.0-pre.5"
|
version = "0.11.0-pre.5"
|
||||||
|
|
@ -419,6 +490,12 @@ version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
|
@ -498,13 +575,33 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive 0.7.35",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.24"
|
version = "0.8.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive 0.8.24",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ rand = "0.8.5"
|
||||||
realm_io = { version = "0.5" }
|
realm_io = { version = "0.5" }
|
||||||
realm_syscall = "0.1"
|
realm_syscall = "0.1"
|
||||||
regex = { version = "1.11", default-features = false, features = ["perf", "std"] }
|
regex = { version = "1.11", default-features = false, features = ["perf", "std"] }
|
||||||
|
saphyr = { version = "0.0.3", default-features = false }
|
||||||
sha2 = { version = "0.11.0-pre.5", default-features = false, features = ["std"] }
|
sha2 = { version = "0.11.0-pre.5", default-features = false, features = ["std"] }
|
||||||
# TODO test feature asm on ARM
|
# TODO test feature asm on ARM
|
||||||
sha3 = { version = "0.11.0-pre.5", default-features = false, features = ["std"] }
|
sha3 = { version = "0.11.0-pre.5", default-features = false, features = ["std"] }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Mesozoa
|
# Mesozoa
|
||||||
|
|
||||||
Intermediate reverse proxy that protects your server from crawlers by forcing the browser to run proof of work.
|
Mesozoa is a small animal living between a reverse-proxy and a server, protecting the server from crawlers by forcing the browser to run proof of work.
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
|
|
||||||
|
|
|
||||||
38
example-config.yaml
Normal file
38
example-config.yaml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
# Mesozoa listens to this address
|
||||||
|
# It should be a local address, that receives traffic from the reverse-proxy.
|
||||||
|
listen: 127.0.0.1:8504
|
||||||
|
# Mesozoa relays accepted traffic to this address
|
||||||
|
pass: 127.0.0.1:8000
|
||||||
|
|
||||||
|
# Duration (in seconds) of validity of a challenge
|
||||||
|
challenge-timeout: 3600
|
||||||
|
# PoW difficulty
|
||||||
|
# Mean PoW duration is multiplied by 2 when this number is incremented by 1.
|
||||||
|
# (TODO: unused for now, needs dynamic challenge page)
|
||||||
|
#target-zeros: 15
|
||||||
|
|
||||||
|
# Action applied when no policy matches
|
||||||
|
# (see below for legal values)
|
||||||
|
default-action: challenge
|
||||||
|
|
||||||
|
# Policy groups are evaluated in order.
|
||||||
|
# The first matching group stops evaluation.
|
||||||
|
# Policies within a group are all evaluated at the same time.
|
||||||
|
# The first matching policy (order from the list here) is applied and stops evaluation.
|
||||||
|
# `name` is for logging, put anything you want.
|
||||||
|
# `first-line` is a regex for the first line of the HTTP request.
|
||||||
|
# `action` is one of the following:
|
||||||
|
# - "allow": relay without challenge
|
||||||
|
# - "challenge": ask Pow challenge and relay iff client succeeds
|
||||||
|
# - "drop": drop connection and do not relay
|
||||||
|
policy-groups:
|
||||||
|
- - name: Favicon
|
||||||
|
first-line: "^GET /favicon.ico "
|
||||||
|
action: allow
|
||||||
|
- name: robots.txt
|
||||||
|
first-line: "^GET /robots.txt "
|
||||||
|
action: allow
|
||||||
|
- name: Favicon
|
||||||
|
first-line: "^GET /favicon.ico "
|
||||||
|
action: allow
|
||||||
57
src/main.rs
57
src/main.rs
|
|
@ -8,7 +8,12 @@ use policy::{CompiledPolicies, Policy};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use realm_syscall::socket2::TcpKeepalive;
|
use realm_syscall::socket2::TcpKeepalive;
|
||||||
use regex::bytes::Regex;
|
use regex::bytes::Regex;
|
||||||
use std::{io::Write, net::SocketAddr, time::Duration};
|
use std::{
|
||||||
|
io::{Read, Write},
|
||||||
|
net::SocketAddr,
|
||||||
|
str::FromStr,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncWriteExt, ReadBuf},
|
io::{AsyncWriteExt, ReadBuf},
|
||||||
net::{TcpSocket, TcpStream},
|
net::{TcpSocket, TcpStream},
|
||||||
|
|
@ -34,28 +39,38 @@ macro_rules! mk_static {
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
let mut config_file =
|
||||||
|
std::fs::File::open("example-config.yaml").expect("Cannot open config file");
|
||||||
|
let mut config_str = String::new();
|
||||||
|
config_file
|
||||||
|
.read_to_string(&mut config_str)
|
||||||
|
.expect("Cannot read config file");
|
||||||
|
let config_yaml = saphyr::Yaml::load_from_str(&config_str).expect("Error parsing config");
|
||||||
|
let config_doc = &config_yaml[0];
|
||||||
|
let listen_addr: SocketAddr = config_doc["listen"]
|
||||||
|
.as_str()
|
||||||
|
.expect("Missing listen address in config")
|
||||||
|
.parse()
|
||||||
|
.expect("Invalid listen address");
|
||||||
|
let pass_addr: SocketAddr = config_doc["pass"]
|
||||||
|
.as_str()
|
||||||
|
.expect("Missing pass address in config")
|
||||||
|
.parse()
|
||||||
|
.expect("Invalid pass address");
|
||||||
|
let default_action = policy::Action::from_str(
|
||||||
|
config_doc["default-action"]
|
||||||
|
.as_str()
|
||||||
|
.expect("Missing default action in config"),
|
||||||
|
)
|
||||||
|
.expect("Invalid default action");
|
||||||
|
let policy_groups: Vec<Vec<Policy>> = config_doc["policy-groups"].as_vec().expect("Missing policies in config").into_iter().map(|policy_group| policy_group.as_vec().expect("Missing policies in config").into_iter().map(|policy| Policy {
|
||||||
|
name: policy["name"].as_str().expect("Expected policy name string").to_string(),
|
||||||
|
first_line_regex: policy["first-line"].as_str().expect("Expected policy first line regex string").to_string(),
|
||||||
|
action: policy::Action::from_str(policy["action"].as_str().expect("Expected policy action string")).expect("Invalid policy action"),
|
||||||
|
}).collect()).collect();
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
let listen_addr: SocketAddr = "127.0.0.1:8504".parse().unwrap();
|
|
||||||
let pass_addr: SocketAddr = "127.0.0.1:80".parse().unwrap();
|
|
||||||
let policy_groups = vec![vec![
|
|
||||||
Policy {
|
|
||||||
name: String::from("Favicon"),
|
|
||||||
first_line_regex: String::from(r"^GET /favicon.ico"),
|
|
||||||
action: policy::Action::Allow,
|
|
||||||
},
|
|
||||||
Policy {
|
|
||||||
name: String::from("robots.txt"),
|
|
||||||
first_line_regex: String::from(r"^GET /robots.txt"),
|
|
||||||
action: policy::Action::Allow,
|
|
||||||
},
|
|
||||||
Policy {
|
|
||||||
name: String::from("Block"),
|
|
||||||
first_line_regex: String::from(r"^GET /block"),
|
|
||||||
action: policy::Action::Drop,
|
|
||||||
},
|
|
||||||
]];
|
|
||||||
let default_action = policy::Action::Challenge;
|
|
||||||
let secret: [u8; SECRET_LEN] = rng.r#gen();
|
let secret: [u8; SECRET_LEN] = rng.r#gen();
|
||||||
|
|
||||||
let policy_groups = &*mk_static!(
|
let policy_groups = &*mk_static!(
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,18 @@ pub enum Action {
|
||||||
Drop,
|
Drop,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for Action {
|
||||||
|
type Err = ();
|
||||||
|
fn from_str(s: &str) -> Result<Self, ()> {
|
||||||
|
match s {
|
||||||
|
"allow" | "Allow" => Ok(Self::Allow),
|
||||||
|
"challenge" | "Challenge" => Ok(Self::Challenge),
|
||||||
|
"drop" | "Drop" => Ok(Self::Drop),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Policy {
|
pub struct Policy {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue