diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index d9258f6..729f1c0 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -11,8 +11,12 @@ on: description: "Tag for the release (x.x.x)" required: true type: string - zapret-version: - description: "Zapret version (x.x)" + nfqws-version: + description: "Nfqws version (x.x)" + required: true + type: string + nfqws2-version: + description: "Nfqws2 version (x.x)" required: true type: string version: @@ -36,7 +40,10 @@ jobs: build: runs-on: ubuntu-latest env: - ZAPRET_VERSION: ${{ inputs.zapret-version }} + NFQWS_VERSION: ${{ inputs.nfqws-version }} + NFQWS2_VERSION: ${{ inputs.nfqws2-version }} + MODULE_VERSION: ${{ inputs.version }} + MODULE_VERSION_CODE: ${{ inputs.version_code }} steps: - uses: actions/checkout@v4 @@ -84,33 +91,15 @@ jobs: - name: Create module.prop run: | - cat > zaprett/module.prop < zaprett-hosts/module.prop < zaprett/module.prop < zaprett-hosts/module.prop < zaprett/module.prop < zaprett-hosts/module.prop < { + static $name: Lazy = Lazy::new(|| { + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + Path::new(&manifest_dir).join($path) + }); + }; +} + +rel_manifest_path!(NFQ, "zapret2/nfq2"); +rel_manifest_path!(NFQ_CRYPTO, "zapret2/nfq2/crypto"); + +fn main() { + const SYMBOLS: &[&str] = &[ + "DLOG", + "net32_add", + "net16_add", + "tcp_find_option", + "tcp_find_scale_factor", + "tcp_find_mss", + "proto_skip_ipv6", + "proto_check_ipv4", + "proto_check_ipv6", + "extract_ports", + "extract_endpoints", + "proto_name", + "family_from_proto", + "str_ip", + "print_ip", + "str_srcdst_ip6", + "str_ip6hdr", + "print_ip6hdr", + "str_tcphdr", + "print_tcphdr", + "l7proto_str", + "l7_proto_match", + "posmarker_name", + "AnyProtoPos", + "ResolvePos", + "HttpPos", + "TLSPos", + "TLSFindExt", + "TLSAdvanceToHostInSNI", + "ResolveMultiPos", + "IsHttp", + "HttpFindHost", + "IsHttpReply", + "HttpReplyCode", + "HttpExtractHeader", + "HttpExtractHost", + "HttpReplyLooksLikeDPIRedirect", + "TLSVersionStr", + "TLSRecordDataLen", + "TLSRecordLen", + "DLOG_CONDUP", + "IsTLSRecordFull", + "DLOG_ERR", + "IsTLSClientHello", + "DLOG_PERROR", + "LOG_APPEND", + "HOSTLIST_DEBUGLOG_APPEND", + "hexdump_limited_dlog", + "TLSHandshakeLen", + "IsTLSHandshakeClientHello", + "IsTLSHandshakeFull", + "TLSFindExtLenOffsetInHandshake", + "TLSFindExtLen", + "TLSFindExtInHandshake", + "TLSHelloExtractHost", + "TLSHelloExtractHostFromHandshake", + "IsQUICCryptoHello", + "QUICDraftVersion", + "str_udphdr", + "QUICIsLongHeader", + "dp_init", + "dp_list_add", + "dp_clear", + "dp_entry_destroy", + "dp_list_destroy", + "dp_list_have_autohostlist", + "cleanup_params", + "progname", + "tld", + "QUICExtractVersion", + "QUICExtractDCID", + "QUICDecryptInitial", + "print_udphdr", + "QUICDefragCrypto", + "IsQUICInitial", + "IsWireguardHandshakeInitiation", + "proto_skip_ipv4", + "IsDiscordIpDiscoveryRequest", + "IsStunMessage", + "proto_check_tcp", + "proto_skip_tcp", + "proto_check_udp", + "proto_skip_udp", + "proto_dissect_l3l4", + "tcp_synack_segment", + "tcp_syn_segment", + "rawsend_cleanup", + "rawsend_preinit", + "rawsend", + "rawsend_rp", + "rawsend_queue", + "wlan_info_deinit", + "wlan_info_init", + "wlan_info_get_rate_limited", + "wlans", + "wlan_ifname2ssid", + "wlan_ifidx2ssid", + "wlan_ssid_search_ifname", + "wlan_ssid_search_ifidx", + "verdict_tcp_csum_fix", + "dpi_desync_packet", + "verdict_udp_csum_fix", + "unique_size_t", + "qsort_size_t", + "dbgprint_socket_buffers", + "fake_http_request_default", + "rtrim", + "replace_char", + "fake_tls_clienthello_default", + "params", + "strncasestr", + "load_file", + "append_to_list_file", + "expand_bits", + "strip_host_to_ip", + "ntop46", + "ntop46_port", + "print_sockaddr", + "saport", + "pntoh64", + "set_socket_buffers", + "phton64", + "seq_within", + "ipv6_addr_is_zero", + "parse_hex_str", + "fprint_localtime", + "file_mod_time", + "file_mod_signature", + "file_open_test", + "pf_in_range", + "pf_parse", + "pf_is_empty", + "fill_random_bytes", + "fill_random_az", + "fill_random_az09", + "set_console_io_buffering", + "set_env_exedir", + "str_cidr4", + "print_cidr4", + "str_cidr6", + "print_cidr6", + "parse_cidr4", + "parse_cidr6", + ]; + let mut cc_builder = cc::Build::new(); + cc_builder.files( + glob::glob(&format!("{}/*.c", NFQ.display())) + .unwrap() + .filter_map(Result::ok), + ); + cc_builder.files( + glob::glob(&format!("{}/*.c", NFQ_CRYPTO.display())) + .unwrap() + .filter_map(Result::ok), + ); + cc_builder.include(&*NFQ); + cc_builder.include(&*NFQ_CRYPTO); + cc_builder.flag("-w"); + for &symbol in SYMBOLS { + let val = format!("nfq2_{}", symbol); + cc_builder.define(symbol, Some(&val[..])); + } + cc_builder.define("main", "nfqws2_main"); + cc_builder.compile("libnfqws2.a"); + + let compiler = cc_builder.get_compiler(); + let output = compiler.to_command() + .arg("-print-libgcc-file-name") + .output() + .expect("Failed to query compiler for libgcc path"); + + let path_str = String::from_utf8(output.stdout).unwrap(); + let lib_path = Path::new(path_str.trim()); + + if lib_path.exists() { + if let Some(parent) = lib_path.parent() { + println!("cargo:rustc-link-search=native={}", parent.display()); + } + + if let Some(stem) = lib_path.file_stem() { + let lib_name = stem.to_string_lossy(); + let lib_name = lib_name.strip_prefix("lib").unwrap_or(&lib_name); + println!("cargo:rustc-link-lib=static={}", lib_name); + } + } else { + println!("cargo:warning=Could not find compiler builtins library at {:?}", lib_path); + println!("cargo:rustc-link-lib=gcc"); + } + + println!("cargo:rustc-link-lib=z"); + println!("cargo:rustc-link-lib=netfilter_queue"); + println!("cargo:rustc-link-lib=nfnetlink"); + println!("cargo:rustc-link-lib=mnl"); + println!("cargo:rustc-link-lib=static=luajit"); + println!("cargo:rustc-link-lib=unwind"); // for shitass luajit + + let _ = env::var("NETFILTER_LIBS") + .map(|libs| println!("cargo:rustc-link-search=native={libs}/lib")); + let _ = env::var("LUAJIT_LIBS") + .map(|libs| println!("cargo:rustc-link-search=native={libs}/lib")); + + println!("cargo:rustc-link-lib=static=nfqws2"); + println!("cargo:rerun-if-changed={}", NFQ.display()); + println!("cargo:rerun-if-changed={}", NFQ_CRYPTO.display()); + println!("cargo:rerun-if-changed=build.rs"); + + let mut builder = bindgen::Builder::default(); + + for header in glob::glob(&format!("{}/*.h", NFQ.display())) + .unwrap() + .filter_map(Result::ok) + { + builder = builder.header(header.to_string_lossy()); + } + builder = builder.clang_arg("-Dmain=nfqws2_main"); + + if let Ok(luajit) = env::var("LUAJIT") { + builder = builder.clang_arg(format!("-I{}", luajit)); + } + + let bindings = builder + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .generate() + .expect("Unable to generate libnfqws2"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("libnfqws2.rs")) + .expect("Couldn't write libnfqws2"); +} diff --git a/rust/crates/libnfqws2/src/lib.rs b/rust/crates/libnfqws2/src/lib.rs new file mode 100644 index 0000000..0442572 --- /dev/null +++ b/rust/crates/libnfqws2/src/lib.rs @@ -0,0 +1,2 @@ +#![allow(warnings)] +include!(concat!(env!("OUT_DIR"), "/libnfqws2.rs")); diff --git a/rust/crates/libnfqws2/zapret2 b/rust/crates/libnfqws2/zapret2 new file mode 160000 index 0000000..36ee42b --- /dev/null +++ b/rust/crates/libnfqws2/zapret2 @@ -0,0 +1 @@ +Subproject commit 36ee42bc8cd914fdc2126610a0c3aef6ce6efb9f diff --git a/rust/crates/zaprett/Cargo.toml b/rust/crates/zaprett/Cargo.toml index d1859f2..4f9ab30 100644 --- a/rust/crates/zaprett/Cargo.toml +++ b/rust/crates/zaprett/Cargo.toml @@ -9,12 +9,12 @@ anyhow = { workspace = true } clap = { workspace = true } libc = { workspace = true } regex = { workspace = true } -rust-ini = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sysctl ={ workspace = true } tokio = { workspace = true } libnfqws = { path = "../libnfqws" } +libnfqws2 = { path = "../libnfqws2" } daemonize = { workspace = true } pretty_env_logger = { workspace = true } log = { workspace = true } diff --git a/rust/crates/zaprett/build.rs b/rust/crates/zaprett/build.rs index 2726f5f..018d8be 100644 --- a/rust/crates/zaprett/build.rs +++ b/rust/crates/zaprett/build.rs @@ -1,5 +1,7 @@ use std::env; fn main() { - let zapret_version = env::var("ZAPRET_VERSION").unwrap_or("unknown".to_string()); - println!("cargo:rustc-env=ZAPRET_VERSION={}", zapret_version); + let nfqws_version = env::var("NFQWS_VERSION").unwrap_or("unknown".to_string()); + let nfqws2_version = env::var("NFQWS2_VERSION").unwrap_or("unknown".to_string()); + println!("cargo:rustc-env=NFQWS_VERSION={}", nfqws_version); + println!("cargo:rustc-env=NFQWS2_VERSION={}", nfqws2_version) } diff --git a/rust/crates/zaprett/src/cli.rs b/rust/crates/zaprett/src/cli.rs index 797bf16..ec85ea7 100644 --- a/rust/crates/zaprett/src/cli.rs +++ b/rust/crates/zaprett/src/cli.rs @@ -5,7 +5,7 @@ use commands::Command; use getset::Getters; #[derive(Parser, Getters)] -// #[command(version)] +#[command(version = option_env!("MODULE_VERSION").unwrap_or("unknown"))] #[getset(get = "pub")] pub struct CliApp { #[command(subcommand)] diff --git a/rust/crates/zaprett/src/cli/commands.rs b/rust/crates/zaprett/src/cli/commands.rs index f8d9f2f..cff8e6e 100644 --- a/rust/crates/zaprett/src/cli/commands.rs +++ b/rust/crates/zaprett/src/cli/commands.rs @@ -1,8 +1,7 @@ use crate::autostart::{get_autostart, set_autostart}; use crate::service::{restart_service, service_status, start_service, stop_service}; -use crate::{bin_version, module_version, run_nfqws}; +use crate::{nfqws_version, nfqws2_version, run_nfqws}; use clap::Subcommand; -use log::error; #[derive(Subcommand)] pub enum Command { @@ -24,14 +23,14 @@ pub enum Command { /// Show whether autostart is enabled GetAutostart, - /// Show the module version - ModuleVersion, + /// Show the nfqws version + NfqwsVersion, - /// Show the nfqws binary version - BinaryVersion, + /// Show the nfqws2 version + Nfqws2Version, /// Run nfqws - Args { + Run { #[arg(allow_hyphen_values=true, trailing_var_arg = true, num_args = 0..)] args: Vec, }, @@ -40,11 +39,9 @@ pub enum Command { impl Command { pub async fn exec(&self) -> anyhow::Result<()> { match self { - Command::Start => return start_service().await, - Command::Stop => { - let _ = stop_service().await; - } - Command::Restart => return restart_service().await, + Command::Start => start_service().await?, + Command::Stop => stop_service().await?, + Command::Restart => restart_service().await?, Command::Status => { println!( "zaprett is {}", @@ -55,15 +52,11 @@ impl Command { } ); } - Command::SetAutostart => { - if let Err(err) = set_autostart().await { - error!("Failed to set auto start: {err}") - } - } + Command::SetAutostart => set_autostart().await?, Command::GetAutostart => println!("{}", get_autostart()), - Command::ModuleVersion => println!("{}", module_version().await?), - Command::BinaryVersion => println!("{}", bin_version()), - Command::Args { args } => run_nfqws(&args.join(" "))?, + Command::NfqwsVersion => println!("{}", nfqws_version()), + Command::Nfqws2Version => println!("{}", nfqws2_version()), + Command::Run { args } => run_nfqws(&args.join(" "))?, } Ok(()) diff --git a/rust/crates/zaprett/src/config.rs b/rust/crates/zaprett/src/config.rs index cdb4ae5..1d96614 100644 --- a/rust/crates/zaprett/src/config.rs +++ b/rust/crates/zaprett/src/config.rs @@ -10,17 +10,36 @@ pub enum ListType { Blacklist, } +#[derive(Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum ServiceType { + #[default] + Nfqws, + Nfqws2, +} + +#[derive(Default, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum ApplistType { + #[default] + None, + Blacklist, + Whitelist, +} + #[derive(Default, Serialize, Deserialize, Getters)] #[getset(get = "pub")] #[serde(default)] pub struct Config { + service_type: ServiceType, active_lists: Vec, active_ipsets: Vec, active_exclude_lists: Vec, active_exclude_ipsets: Vec, list_type: ListType, strategy: String, - app_list: String, + strategy_nfqws2: String, + app_list: ApplistType, whitelist: Vec, blacklist: Vec, } diff --git a/rust/crates/zaprett/src/daemon.rs b/rust/crates/zaprett/src/daemon.rs index 6441fce..80e97e1 100644 --- a/rust/crates/zaprett/src/daemon.rs +++ b/rust/crates/zaprett/src/daemon.rs @@ -1,4 +1,4 @@ -use crate::{MODULE_PATH, run_nfqws}; +use crate::{MODULE_PATH, run_nfqws, run_nfqws2}; use daemonize::Daemonize; use log::{error, info}; use std::fs::File; @@ -24,3 +24,25 @@ pub async fn daemonize_nfqws(args: &str) { Err(e) => error!("Error while starting nfqws daemon: {e}"), } } + +pub async fn daemonize_nfqws2(args: &str) { + info!("Starting nfqws2 as a daemon"); + + let stdout = File::create(MODULE_PATH.join("tmp/nfqws2.out")).unwrap(); + let stderr = File::create(MODULE_PATH.join("tmp/nfqws2.err")).unwrap(); + + let daemonize = Daemonize::new() + .pid_file(MODULE_PATH.join("tmp/pid.lock").as_path()) + .working_directory(MODULE_PATH.join("tmp")) + .stdout(stdout) + .stderr(stderr) + .privileged_action(|| "Executed before drop privileges"); + + match daemonize.start() { + Ok(_) => { + info!("Success, nfqws2 daemonized"); + run_nfqws2(args).unwrap() + } + Err(e) => error!("Error while starting nfqws2 daemon: {e}"), + } +} diff --git a/rust/crates/zaprett/src/lib.rs b/rust/crates/zaprett/src/lib.rs index 4307731..28ee76f 100644 --- a/rust/crates/zaprett/src/lib.rs +++ b/rust/crates/zaprett/src/lib.rs @@ -5,48 +5,65 @@ pub mod iptables_rust; mod service; mod autostart; -use ini::Ini; use libnfqws::nfqws_main; +use libnfqws2::nfqws2_main; use std::error; use std::ffi::CString; use std::os::raw::c_char; use std::path::Path; use std::sync::LazyLock; -use anyhow::bail; use tokio::fs::File; use tokio::io::{copy, AsyncWriteExt}; -use tokio::task::spawn_blocking; +#[cfg(target_os = "android")] pub static MODULE_PATH: LazyLock<&Path> = LazyLock::new(|| Path::new("/data/adb/modules/zaprett")); - +#[cfg(target_os = "android")] pub static ZAPRETT_DIR_PATH: LazyLock<&Path> = LazyLock::new(|| Path::new("/storage/emulated/0/zaprett")); +#[cfg(target_os = "android")] +pub static ZAPRETT_LIBS_PATH: LazyLock<&Path> = + LazyLock::new(|| Path::new("/storage/emulated/0/zaprett/strategies/nfwqs2/libs")); -pub static DEFAULT_START: &str = " - --filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig,badsum $hostlist --new - --filter-tcp=443 $hostlist --dpi-desync=fake,split2 --dpi-desync-repeats=6 --dpi-desync-fooling=md5sig,badsum --dpi-desync-fake-tls=${zaprettdir}/bin/tls_clienthello_www_google_com.bin --new - --filter-tcp=80,443 --dpi-desync=fake,disorder2 --dpi-desync-repeats=6 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig,badsum $hostlist --new +// Only for testing +#[cfg(target_os = "linux")] +pub static MODULE_PATH: LazyLock<&Path> = + LazyLock::new(|| Path::new("zaprett_module")); +#[cfg(target_os = "linux")] +pub static ZAPRETT_DIR_PATH: LazyLock<&Path> = + LazyLock::new(|| Path::new("zaprett")); +#[cfg(target_os = "linux")] +pub static ZAPRETT_LIBS_PATH: LazyLock<&Path> = + LazyLock::new(|| Path::new("zaprett/strategies/nfwqs2/libs")); + + +pub static DEFAULT_STRATEGY_NFQWS: &str = " + --filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig,badsum ${hostlist} --new + --filter-tcp=443 ${hostlist} --dpi-desync=fake,split2 --dpi-desync-repeats=6 --dpi-desync-fooling=md5sig,badsum --dpi-desync-fake-tls=${zaprettdir}/bin/tls_clienthello_www_google_com.bin --new + --filter-tcp=80,443 --dpi-desync=fake,disorder2 --dpi-desync-repeats=6 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig,badsum ${hostlist} --new --filter-udp=50000-50100 --dpi-desync=fake --dpi-desync-any-protocol --dpi-desync-fake-quic=0xC30000000108 --new - --filter-udp=443 $hostlist --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-fake-quic=${zaprettdir}/bin/quic_initial_www_google_com.bin --new - --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 $hostlist + --filter-udp=443 ${hostlist} --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-fake-quic=${zaprettdir}/bin/quic_initial_www_google_com.bin --new + --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 ${hostlist} + "; +// тестовая стратегия, заменить на нормальную потом +pub static DEFAULT_STRATEGY_NFQWS2: &str = " + --lua-init=@${libsdir}/zapret-lib.lua --lua-init=@${libsdir}/zapret-antidpi.lua + --blob=quic_google:@${zaprettdir}/bin/quic_initial_www_google_com.bin + --blob=tls_google:${zaprettdir}/bin/tls_clienthello_www_google_com.bin + --blob=tls_4pda:@${zaprettdir}/bin/tls_clienthello_4pda_to.bin + --blob=tls_max:@${zaprettdir}/bin/tls_clienthello_max_ru.bin + --blob=zero4:0x00000000 + --filter-udp=443 --hostlist=${zaprettdir}/lists/include/list-general.txt --lua-desync=fake:blob=quic_google:repeats=6 --new + --filter-tcp=443 --hostlist=${zaprettdir}/lists/include/list-google.txt --lua-desync=fake:blob=tls_google:repeats=6:tcp_seq=2:tls_mod=none:ip_id=zero --new + --filter-tcp=80,443 --hostlist=${zaprettdir}/lists/include/list-general.txt --lua-desync=fake:blob=tls_google:repeats=6:tcp_seq=2:tls_mod=none "; -async fn module_version() -> anyhow::Result { - let prop = spawn_blocking(|| Ini::load_from_file(MODULE_PATH.join("module.prop"))) - .await??; - - if let Some(props) = prop.section::(None) - && let Some(version) = props.get("version") - { - return Ok(version.into()); - } - - bail!("Failed to get version, prop not found") +fn nfqws_version() -> &'static str { + env!("NFQWS_VERSION") } -fn bin_version() -> &'static str { - env!("ZAPRET_VERSION") +fn nfqws2_version() -> &'static str { + env!("NFQWS2_VERSION") } pub async fn merge_files( @@ -101,3 +118,31 @@ fn run_nfqws(args_str: &str) -> anyhow::Result<()> { Ok(()) } + + +fn run_nfqws2(args_str: &str) -> anyhow::Result<()> { + let mut args = vec![ + "nfqws2".to_string(), + "--uid=0:0".to_string(), + "--qnum=200".to_string(), + ]; + + if args_str.trim().is_empty() { + args.push("-v".to_string()); + } else { + args.extend(args_str.split_whitespace().map(String::from)); + } + + let c_args: Vec = args + .into_iter() + .map(|arg| CString::new(arg).unwrap()) + .collect(); + + let mut ptrs: Vec<*const c_char> = c_args.iter().map(|arg| arg.as_ptr()).collect(); + + unsafe { + nfqws2_main(c_args.len() as libc::c_int, ptrs.as_mut_ptr() as *mut _); + } + + Ok(()) +} diff --git a/rust/crates/zaprett/src/main.rs b/rust/crates/zaprett/src/main.rs index dcbc32e..7c79558 100644 --- a/rust/crates/zaprett/src/main.rs +++ b/rust/crates/zaprett/src/main.rs @@ -8,7 +8,7 @@ async fn main() -> anyhow::Result<()> { let cli = CliApp::parse(); match cli.cmd() { Some(cmd) => cmd.exec().await?, - None => println!("zaprett installed. Join us: t.me/zaprett_module"), + None => println!("zaprett installed. Join us in Telegram: t.me/zaprett_module"), } Ok(()) diff --git a/rust/crates/zaprett/src/service.rs b/rust/crates/zaprett/src/service.rs index ecbdd53..560c7cc 100644 --- a/rust/crates/zaprett/src/service.rs +++ b/rust/crates/zaprett/src/service.rs @@ -1,7 +1,8 @@ -use crate::config::Config; +use crate::config::{Config, ServiceType}; use crate::daemon::daemonize_nfqws; +use crate::daemon::daemonize_nfqws2; use crate::iptables_rust::{clear_iptables_rules, setup_iptables_rules}; -use crate::{DEFAULT_START, MODULE_PATH, ZAPRETT_DIR_PATH}; +use crate::{DEFAULT_STRATEGY_NFQWS, DEFAULT_STRATEGY_NFQWS2, MODULE_PATH, ZAPRETT_DIR_PATH, ZAPRETT_LIBS_PATH}; use anyhow::bail; use log::info; use nix::sys::signal::{Signal, kill}; @@ -53,14 +54,26 @@ pub async fn start_service() -> anyhow::Result<()> { let config: Config = serde_json::from_str(&config_contents)?; - let start = fs::read_to_string(config.strategy()) - .await - .map(Cow::Owned) - .unwrap_or(Cow::Borrowed(DEFAULT_START)); + let start: Cow = if config.service_type() == &ServiceType::Nfqws { + fs::read_to_string(config.strategy()) + .await + .map(Cow::Owned) + .unwrap_or(Cow::Borrowed(DEFAULT_STRATEGY_NFQWS)) + } + else if config.service_type() == &ServiceType::Nfqws2 { + fs::read_to_string(config.strategy_nfqws2()) + .await + .map(Cow::Owned) + .unwrap_or(Cow::Borrowed(DEFAULT_STRATEGY_NFQWS2)) + } + else { + bail!("Broken config file!"); + }; - let regex_hostlist = Regex::new(r"\$hostlist")?; - let regex_ipsets = Regex::new(r"\$ipset")?; - let regex_zaprettdir = Regex::new(r"\$\{?zaprettdir}?")?; + let regex_hostlist = Regex::new(r"\$(?:hostlist|\{hostlist})")?; + let regex_ipsets = Regex::new(r"\$(?:ipset|\{ipset})")?; + let regex_zaprettdir = Regex::new(r"\$(?:zaprettdir|\{zaprettdir})")?; + let regex_libsdir = Regex::new(r"\$(?:libsdir|\{libsdir})")?; let mut strat_modified; let (hosts, ipsets) = config.list_type().merge(&config).await; @@ -74,12 +87,25 @@ pub async fn start_service() -> anyhow::Result<()> { .replace_all(&strat_modified, ZAPRETT_DIR_PATH.to_str().unwrap()) .into_owned(); + strat_modified = regex_libsdir + .replace_all(&strat_modified, ZAPRETT_LIBS_PATH.to_str().unwrap()) + .into_owned(); + let ctl = Ctl::new("net.netfilter.nf_conntrack_tcp_be_liberal")?; ctl.set_value(CtlValue::String("1".into()))?; setup_iptables_rules().expect("setup iptables rules"); - daemonize_nfqws(&strat_modified).await; + if config.service_type() == &ServiceType::Nfqws { + daemonize_nfqws(&strat_modified).await; + } + else if config.service_type() == &ServiceType::Nfqws2 { + daemonize_nfqws2(&strat_modified).await; + } + else { + bail!("Broken config file!"); + } + println!("zaprett service started!"); Ok(()) } diff --git a/rust/justfile b/rust/justfile index c1ab5a3..e2f5ff0 100644 --- a/rust/justfile +++ b/rust/justfile @@ -6,6 +6,7 @@ export ANDROID_NDK_VERSION := "r27d-linux" TARGET := `pwd` + "/target" export NETFILTER_LIBS := TARGET + "/netfilter" +export LUAJIT_LIBS := TARGET + "/luajit" export NDK_HOME := TARGET + "/android-ndk-" + ANDROID_NDK_VERSION @@ -76,7 +77,44 @@ _build_netfilter_libs target_arch: echo "Netfilter libs for {{target_arch}} already built" fi -_instal_rust_target target: +_build_luajit target_arch: + #!/usr/bin/env bash + + if [ ! -d "{{LUAJIT_LIBS}}-{{target_arch}}" ]; then + cd "{{TARGET}}" + + if [ ! -d "luajit2-*" ]; then + wget -qO- https://github.com/openresty/luajit2/archive/refs/tags/v2.1-20250826.tar.gz | tar -xz + fi + + export TOOLCHAIN=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 + export CC="$TOOLCHAIN/bin/clang --target={{target_arch}}$ANDROID_API" + export AR=$TOOLCHAIN/bin/llvm-ar + export STRIP=$TOOLCHAIN/bin/llvm-strip + + case "{{target_arch}}" in + *64*) HOSTCC="cc" ;; + *) HOSTCC="cc -m32" ;; + esac + + ( + cd luajit2-* + make clean + make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI \ + HOST_CC="$HOSTCC" CROSS= CC="$CC" \ + TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP \ + CFLAGS="-Os -flto=auto" -j$(nproc) + + make install PREFIX= DESTDIR="{{LUAJIT_LIBS}}-{{target_arch}}" + mv "{{LUAJIT_LIBS}}-{{target_arch}}/lib/libluajit-5.1.a" \ + "{{LUAJIT_LIBS}}-{{target_arch}}/lib/libluajit.a" + ) + else + echo "LuaJIT for {{target_arch}} already built" + fi + + +_install_rust_target target: #!/usr/bin/env bash if ! rustup target list --installed | grep -q "{{target}}"; then echo "Installing missing target: {{target}}" @@ -98,12 +136,18 @@ build-android *args: prepare-android t=${targets[$i]} ( echo "Building target $t" - export CFLAGS="-I$NETFILTER_LIBS-$t/include" - export LDFLAGS="-L$NETFILTER_LIBS-$t/lib" + export CFLAGS="-I$NETFILTER_LIBS-$t/include -I$LUAJIT_LIBS-$t/include/luajit-2.1" + export LDFLAGS="-L$NETFILTER_LIBS-$t/lib -L$LUAJIT_LIBS-$t/lib" export CXXFLAGS="$CFLAGS" + export LUAJIT="$LUAJIT_LIBS-$t/include/luajit-2.1" + export LJIT=1 + export LCFLAGS="-I$LUAJIT_LIBS-$t/include/luajit-2.1" + export LLIB="-L$LUAJIT_LIBS-$t/lib -lluajit-2.1" + just _build_netfilter_libs $t - just _instal_rust_target $t - NETFILTER_LIBS=$NETFILTER_LIBS-$t cargo ndk -t $t --platform $ANDROID_API build {{args}} + just _build_luajit $t + just _install_rust_target $t + NETFILTER_LIBS=$NETFILTER_LIBS-$t LUAJIT_LIBS=$LUAJIT_LIBS-$t cargo ndk -t $t --platform $ANDROID_API build {{args}} ) done