init support ip number strict
This commit is contained in:
commit
33f528a72d
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
||||
433
Cargo.lock
generated
Normal file
433
Cargo.lock
generated
Normal file
@ -0,0 +1,433 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
|
||||
dependencies = [
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"env_filter",
|
||||
"humantime",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "iptables"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d39f0d72d0feb83c9b7f4e1fbde2b4a629886f30841127b3f86383831dba2629"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"nix",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "lru_time_cache"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
|
||||
[[package]]
|
||||
name = "nfq"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9c8f4c88952507d9df9400a6a2e48640fb460e21dcb2b4716eb3ff156d6db9e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "no-std-net"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
|
||||
|
||||
[[package]]
|
||||
name = "pnet_base"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c"
|
||||
dependencies = [
|
||||
"no-std-net",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pnet_macros"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pnet_macros_support"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56"
|
||||
dependencies = [
|
||||
"pnet_base",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pnet_packet"
|
||||
version = "0.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"pnet_base",
|
||||
"pnet_macros",
|
||||
"pnet_macros_support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "rs_filter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ctrlc",
|
||||
"env_logger",
|
||||
"iptables",
|
||||
"log",
|
||||
"lru_time_cache",
|
||||
"nfq",
|
||||
"pnet_packet",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.197"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "rs_filter"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
lru_time_cache = "0.11.11"
|
||||
nfq = "0.2.5"
|
||||
pnet_packet = "0.34.0"
|
||||
anyhow="1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
iptables = "0.5.1"
|
||||
ctrlc = "3.4.2"
|
||||
log = "0.4.21"
|
||||
env_logger = "0.11.3"
|
||||
13
src/config.rs
Normal file
13
src/config.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct IPNumberStrict {
|
||||
pub time_thr_sec: u64,
|
||||
pub max_ip_number: usize,
|
||||
pub port_range: (u16, u16),
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub ip_num_strict: IPNumberStrict,
|
||||
|
||||
}
|
||||
39
src/main.rs
Normal file
39
src/main.rs
Normal file
@ -0,0 +1,39 @@
|
||||
mod config;
|
||||
mod nfq_mng;
|
||||
mod nfq_proc;
|
||||
mod processor;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use config::Config;
|
||||
use nfq_mng::NFQMng;
|
||||
use nfq_proc::NfqRunBuilder;
|
||||
use processor::ip_num_strict::IpNumStrict;
|
||||
fn main() -> anyhow::Result<()> {
|
||||
env_logger::init();
|
||||
let cfg_file: PathBuf = std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or_else(|| "config.json".to_owned())
|
||||
.parse()?;
|
||||
let config: Config = serde_json::from_reader(std::fs::File::open(&cfg_file)?)?;
|
||||
let mut ipt_mng = NFQMng::new();
|
||||
ipt_mng.add__nfq_rule(
|
||||
"mangle",
|
||||
"PREROUTING",
|
||||
&format!(
|
||||
"-p tcp --dport {}:{} -m conntrack --ctstate NEW",
|
||||
config.ip_num_strict.port_range.0, config.ip_num_strict.port_range.1
|
||||
),
|
||||
0,
|
||||
);
|
||||
ipt_mng.run()?;
|
||||
let mut builder = NfqRunBuilder::new();
|
||||
builder.add_processor(
|
||||
0,
|
||||
Box::new(IpNumStrict::new(
|
||||
config.ip_num_strict.max_ip_number,
|
||||
config.ip_num_strict.time_thr_sec,
|
||||
)),
|
||||
);
|
||||
builder.run()?;
|
||||
Ok(())
|
||||
}
|
||||
83
src/nfq_mng.rs
Normal file
83
src/nfq_mng.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use std::{
|
||||
process::exit,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use ctrlc::set_handler;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Rule {
|
||||
tbl: String,
|
||||
chain: String,
|
||||
rule: String,
|
||||
}
|
||||
pub struct NFQMng {
|
||||
rules: Arc<Mutex<Vec<Rule>>>,
|
||||
}
|
||||
|
||||
impl NFQMng {
|
||||
pub fn new() -> NFQMng {
|
||||
NFQMng {
|
||||
rules: Default::default(),
|
||||
}
|
||||
}
|
||||
pub fn add__nfq_rule(&mut self, tbl: &str, chain: &str, para: &str, queue_num: u32) {
|
||||
let rule_str = format!("{para} -j NFQUEUE --queue-bypass --queue-num {queue_num}");
|
||||
self.rules.lock().unwrap().push(Rule {
|
||||
tbl: tbl.to_owned(),
|
||||
chain: chain.to_owned(),
|
||||
rule: rule_str,
|
||||
});
|
||||
}
|
||||
pub fn add__comm_rule(&mut self, tbl: &str, chain: &str, para: &str) {
|
||||
self.rules.lock().unwrap().push(Rule {
|
||||
tbl: tbl.to_owned(),
|
||||
chain: chain.to_owned(),
|
||||
rule: para.to_owned(),
|
||||
});
|
||||
}
|
||||
pub fn run(self) -> anyhow::Result<()> {
|
||||
let notify = Arc::new(std::sync::Condvar::new());
|
||||
let mutex = Mutex::new(());
|
||||
let notifier = notify.clone();
|
||||
let rules_clone = self.rules.clone();
|
||||
std::thread::spawn(move || {
|
||||
let ips = iptables::new(false).unwrap();
|
||||
set_handler(move || {
|
||||
let ips = iptables::new(false).unwrap();
|
||||
for r in rules_clone.lock().unwrap().iter() {
|
||||
if let Err(e) = ips.delete(&r.tbl, &r.chain, &r.rule) {
|
||||
println!("clean iptables rule: {r:?} failed: {e:?}");
|
||||
}
|
||||
}
|
||||
println!("unsetup iptables success");
|
||||
exit(0);
|
||||
})
|
||||
.unwrap();
|
||||
loop {
|
||||
let mut has_failed = false;
|
||||
for r in self.rules.lock().unwrap().iter() {
|
||||
match ips.exists(&r.tbl, &r.chain, &r.rule) {
|
||||
Ok(false) => {
|
||||
if let Err(e) = ips.insert(&r.tbl, &r.chain, &r.rule, 1) {
|
||||
println!("setup iptables rule: {r:?} failed: {e:?}");
|
||||
has_failed = true;
|
||||
}
|
||||
}
|
||||
Ok(true) => {}
|
||||
Err(e) => {
|
||||
println!("check iptables rule: {r:?} failed: {e:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
if !has_failed {
|
||||
notifier.notify_all();
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_secs(5 * 60));
|
||||
}
|
||||
});
|
||||
let l = mutex.lock().unwrap();
|
||||
let _l = notify.wait(l).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
98
src/nfq_proc.rs
Normal file
98
src/nfq_proc.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use std::{collections::HashMap, net::Ipv4Addr};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use nfq::{Queue, Verdict};
|
||||
use pnet_packet::{ipv4::Ipv4Packet, tcp::TcpPacket, udp::UdpPacket, Packet};
|
||||
|
||||
pub struct MessageData {
|
||||
pub from_ip: Ipv4Addr,
|
||||
pub dst_ip: Ipv4Addr,
|
||||
pub src_port: u16,
|
||||
pub dst_port: u16,
|
||||
}
|
||||
pub trait Processor {
|
||||
fn run<'a>(&mut self, msg: &MessageData, orig_msg: &Ipv4Packet<'a>) -> Verdict;
|
||||
fn message_type(&self) -> MessageType;
|
||||
}
|
||||
|
||||
pub enum MessageType {
|
||||
Tcp,
|
||||
Udp,
|
||||
}
|
||||
pub struct NfqRunBuilder {
|
||||
processor: HashMap<u16, (MessageType, Vec<Box<dyn Processor + Send + Sync + 'static>>)>,
|
||||
}
|
||||
|
||||
impl NfqRunBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
processor: Default::default(),
|
||||
}
|
||||
}
|
||||
pub fn add_processor(
|
||||
&mut self,
|
||||
que_idx: u16,
|
||||
processor: Box<dyn Processor + Send + Sync + 'static>,
|
||||
) {
|
||||
self.processor
|
||||
.entry(que_idx)
|
||||
.or_insert_with(|| (processor.message_type(), Vec::new()))
|
||||
.1
|
||||
.push(processor);
|
||||
}
|
||||
pub fn run(self) -> anyhow::Result<()> {
|
||||
let mut handlers = Vec::new();
|
||||
for (idx, (ty, mut all_processor)) in self.processor.into_iter() {
|
||||
let parse2 = match ty {
|
||||
MessageType::Tcp => move |ip_pkt: &Ipv4Packet| {
|
||||
let tcp_pkt = TcpPacket::new(ip_pkt.payload())
|
||||
.ok_or(anyhow!("can't parse tcp packet"))?;
|
||||
Ok::<_, anyhow::Error>((tcp_pkt.get_source(), tcp_pkt.get_destination()))
|
||||
},
|
||||
MessageType::Udp => move |ip_pkt: &Ipv4Packet| {
|
||||
let tcp_pkt = UdpPacket::new(ip_pkt.payload())
|
||||
.ok_or(anyhow!("can't parse udp packet"))?;
|
||||
Ok::<_, anyhow::Error>((tcp_pkt.get_source(), tcp_pkt.get_destination()))
|
||||
},
|
||||
};
|
||||
let h = std::thread::spawn(move || {
|
||||
let mut queue = Queue::open()?;
|
||||
queue.bind(idx)?;
|
||||
loop {
|
||||
let mut msg = queue.recv()?;
|
||||
let mut act = Verdict::Accept;
|
||||
if let Some(ip_packet) = pnet_packet::ipv4::Ipv4Packet::new(msg.get_payload()) {
|
||||
let from_ip = ip_packet.get_source();
|
||||
let dst_ip = ip_packet.get_destination();
|
||||
let (src_port, dst_port) = parse2(&ip_packet)?;
|
||||
let msg_data = MessageData {
|
||||
from_ip,
|
||||
dst_ip,
|
||||
src_port,
|
||||
dst_port,
|
||||
};
|
||||
log::trace!("ip from: {from_ip:?}:{src_port} to {dst_ip:?}:{dst_port}");
|
||||
for p in all_processor.iter_mut() {
|
||||
let cur_rst = p.run(&msg_data, &ip_packet);
|
||||
match cur_rst {
|
||||
Verdict::Drop | Verdict::Stop => {
|
||||
act = cur_rst;
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
msg.set_verdict(act);
|
||||
queue.verdict(msg)?;
|
||||
}
|
||||
Ok::<_, anyhow::Error>(())
|
||||
});
|
||||
handlers.push(h);
|
||||
}
|
||||
for h in handlers {
|
||||
let _ = h.join();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
57
src/processor/ip_num_strict.rs
Normal file
57
src/processor/ip_num_strict.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use std::{collections::HashMap, net::Ipv4Addr};
|
||||
|
||||
use nfq::Verdict;
|
||||
use pnet_packet::ipv4::Ipv4Packet;
|
||||
|
||||
use crate::nfq_proc::{MessageData, MessageType, Processor};
|
||||
|
||||
pub struct IpNumStrict {
|
||||
ip_number: usize,
|
||||
time_thr: u64,
|
||||
data: HashMap<u16, lru_time_cache::LruCache<Ipv4Addr, ()>>,
|
||||
}
|
||||
impl IpNumStrict {
|
||||
pub fn new(ip_number: usize, time_thr: u64) -> Self {
|
||||
Self {
|
||||
ip_number,
|
||||
time_thr,
|
||||
data: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Processor for IpNumStrict {
|
||||
fn run<'a>(&mut self, msg: &MessageData, _orig_msg: &Ipv4Packet<'a>) -> Verdict {
|
||||
let mut act = Verdict::Accept;
|
||||
let from_ip = msg.from_ip;
|
||||
let dst_ip = msg.dst_ip;
|
||||
let src_port = msg.src_port;
|
||||
let dst_port = msg.dst_port;
|
||||
let port_record = self.data.entry(dst_port).or_insert_with(|| {
|
||||
lru_time_cache::LruCache::with_expiry_duration(std::time::Duration::from_secs(
|
||||
self.time_thr,
|
||||
))
|
||||
});
|
||||
let cur_len = port_record.len();
|
||||
let entry = port_record.entry(from_ip);
|
||||
match entry {
|
||||
lru_time_cache::Entry::Vacant(e) => {
|
||||
// 不存在的ip,检查数量限制
|
||||
if cur_len >= self.ip_number {
|
||||
// 达到了限制
|
||||
log::warn!("{from_ip:?}:{src_port} -> {dst_ip:?}:{dst_port}, Ip num exceed");
|
||||
act = Verdict::Drop;
|
||||
} else {
|
||||
// 新增
|
||||
e.insert(());
|
||||
}
|
||||
}
|
||||
lru_time_cache::Entry::Occupied(_e) => {
|
||||
// 已经存在,直接放行
|
||||
}
|
||||
}
|
||||
act
|
||||
}
|
||||
fn message_type(&self) -> MessageType {
|
||||
MessageType::Tcp
|
||||
}
|
||||
}
|
||||
2
src/processor/mod.rs
Normal file
2
src/processor/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod ip_num_strict;
|
||||
use super::nfq_proc::Processor;
|
||||
Loading…
x
Reference in New Issue
Block a user