diff --git a/Cargo.lock b/Cargo.lock index 6bff064..b7bf90c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -448,6 +448,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -477,7 +486,9 @@ dependencies = [ "log", "log4rs", "rand", + "serde", "tokio", + "toml", ] [[package]] @@ -579,6 +590,40 @@ dependencies = [ "syn 1.0.105", ] +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "typemap-ors" version = "1.0.0" @@ -820,3 +865,12 @@ name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index 10895a5..951067b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,6 @@ edition = "2021" log = "0.4.21" log4rs = "1.3.0" rand = "0.8.5" +serde = { version = "1.0.197", features = ["derive"] } tokio = { version = "1", features = ["full"] } +toml = "0.8.12" diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..aaa8fa0 --- /dev/null +++ b/config.toml @@ -0,0 +1,12 @@ +[listen] +# address and port to listen +bind_addr = "127.0.0.1" +bind_port = 5063 + +[log] +# log file location +log_file = "sip-tarpit.log" + +[tarpit] +# delay in milliseconds +delay = 1500 diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..db91184 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,87 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +struct ConfigToml { + listen: Option, + log: Option, + tarpit: Option +} + +#[derive(Serialize, Deserialize, Debug)] +struct ConfigTomlListen { + bind_addr: Option, + bind_port: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +struct ConfigTomlLog { + log_file: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +struct ConfigTomlTarpit { + delay: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct Config { + pub bind_addr: String, + pub bind_port: u16, + pub log_file: String, + pub delay: u64, +} + +impl Config { + pub fn new() -> Self { + let config_filepaths: [&str; 3] = [ + "./config.toml", + "~/.config/sip-tarpit/config.toml", + "/etc/sip-tarpit/config.toml", + ]; + + let mut content: String = "".to_owned(); + + for filepath in config_filepaths { + let result: Result = std::fs::read_to_string(filepath); + + if result.is_ok() { + content = result.unwrap(); + break; + } + } + + let config_toml: ConfigToml = toml::from_str(&content).unwrap_or_else(|_| { + println!("Failed to create Config from config file."); + ConfigToml { + listen: None, + log: None, + tarpit: None + } + }); + + let (bind_addr, bind_port): (String, u16) = match config_toml.listen { + Some(ConfigTomlListen { bind_addr, bind_port }) => ( + bind_addr.unwrap_or("127.0.0.1".to_owned()), + bind_port.unwrap_or(5060) + ), + None => ("127.0.0.1".to_owned(), 5060) + }; + + let log_file = match config_toml.log { + Some(ConfigTomlLog { log_file }) => log_file.unwrap_or("sip-tarpit.log".to_owned()), + None => "sip-tarpit.log".to_owned() + }; + + let delay = match config_toml.tarpit { + Some(ConfigTomlTarpit { delay }) => delay.unwrap_or(0), + None => 0 + }; + + Config { + bind_addr, + bind_port, + log_file, + delay + } + } +} diff --git a/src/main.rs b/src/main.rs index c78d043..989a6ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,8 @@ * Listens on 5060 udp by default * */ -pub mod sip; +mod sip; +mod config; use crate::sip::generic::*; use crate::sip::not_found::*; @@ -13,7 +14,7 @@ use crate::sip::unauthorized::*; use rand::Rng; use std::error::Error; use std::net::SocketAddr; -use std::{env, io}; +use std::io; use tokio::net::UdpSocket; use tokio::time::{sleep, Duration}; use log::LevelFilter; @@ -21,13 +22,11 @@ use log4rs::append::file::FileAppender; use log4rs::config::{Appender, Config, Root}; use log4rs::encode::pattern::PatternEncoder; -// delay miliseconds for tarpit feature -static TARPIT_DELAY: u64 = 1500; // more than 2 seconds make spivicious go timeout - struct Server { socket: UdpSocket, buf: Vec, to_send: Option<(usize, SocketAddr)>, + config: config::Config } impl Server { @@ -36,6 +35,7 @@ impl Server { socket, mut buf, mut to_send, + config } = self; loop { @@ -51,7 +51,7 @@ impl Server { match msg { msg if msg.contains("OPTIONS") => { // esperar - tarpit! - sleep(Duration::from_millis(TARPIT_DELAY)).await; + sleep(Duration::from_millis(config.delay)).await; let options = Options::parse(&msg); // respondemos con un 404 not found @@ -80,7 +80,7 @@ impl Server { }, msg if msg.contains("REGISTER") => { // esperar - tarpit! - sleep(Duration::from_millis(TARPIT_DELAY)).await; + sleep(Duration::from_millis(config.delay)).await; let register = Register::parse(&msg); @@ -163,21 +163,21 @@ impl Server { #[tokio::main] async fn main() -> Result<(), Box> { + let config: config::Config = config::Config::new(); + // println!("{:#?}", config); + let logfile = FileAppender::builder() .encoder(Box::new(PatternEncoder::new("{d} - {l} - {m}\n"))) .build("sip-tarpit.log") .unwrap(); - let config = Config::builder() + let logconfig = Config::builder() .appender(Appender::builder().build("logfile", Box::new(logfile))) .build(Root::builder().appender("logfile").build(LevelFilter::Trace)) .unwrap(); - log4rs::init_config(config).unwrap(); - - let addr = env::args() - .nth(1) - .unwrap_or_else(|| "127.0.0.1:5063".to_string()); + log4rs::init_config(logconfig).unwrap(); + let addr = format!("{}:{}", config.bind_addr, config.bind_port); let socket = UdpSocket::bind(&addr).await?; log::info!("Listening on: {}", socket.local_addr()?); @@ -185,6 +185,7 @@ async fn main() -> Result<(), Box> { socket, buf: vec![0; 1024], to_send: None, + config: config, }; // This starts the server task.