Skip to content

Commit

Permalink
feat: implement the knock-cli
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyYe committed Mar 2, 2024
1 parent a943f70 commit be34d2d
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 5 deletions.
2 changes: 2 additions & 0 deletions knock-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ edition = "2021"

[dependencies]
clap = { version = "4.5.1", features = ["derive"] }
serde = { version = "1.0.197", features = ["derive"] }
serde_yaml = "0.9.32"
15 changes: 15 additions & 0 deletions knock-cli/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
rules:
- name: "enable_ssh"
host: "example.com"
sequence:
- 12345
- 54321
- 32768
- 18933
- name: "disable_ssh"
host: "example.com"
sequence:
- 18933
- 32768
- 54321
- 12345
15 changes: 15 additions & 0 deletions knock-cli/src/config/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
extern crate serde;

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Rule {
pub name: String,
pub host: String,
pub sequence: Vec<i32>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
pub rules: Vec<Rule>,
}
28 changes: 28 additions & 0 deletions knock-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use std::fs::File;
use std::io::Read;

pub use config::Config;
pub use config::Rule;
pub mod config;

pub fn load_config(path: &str) -> Result<Config, Box<dyn std::error::Error>> {
let mut file = File::open(path)?;
let mut content = String::new();

file.read_to_string(&mut content)?;
let config: Config = serde_yaml::from_str(&content)?;

Ok(config)
}

// test case for load_config
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_load_config() {
let config = load_config("config.yaml").unwrap();
assert_eq!(config.rules.len(), 2);
}
}
8 changes: 6 additions & 2 deletions knock-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use clap::Parser;

mod config;
mod rule;

#[derive(Parser, Debug)]
#[command(version = env!("VERSION"), about, long_about = "A port knocking console application written in Rust")]
struct Args {
Expand All @@ -13,7 +16,6 @@ struct Args {

fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();

let rule = match args.rule {
Some(rule) => rule,
None => {
Expand All @@ -22,7 +24,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
};

println!("rule: {}", rule);
let config = config::load_config(&args.config)?;
let executor = rule::RuleExecutor::new(config);
executor.run(&rule)?;

Ok(())
}
44 changes: 44 additions & 0 deletions knock-cli/src/rule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::config::Config;
use crate::config::Rule;
use std::collections::HashMap;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::time::Duration;

pub struct RuleExecutor {
rules: HashMap<String, Rule>,
}

impl RuleExecutor {
pub fn new(config: Config) -> RuleExecutor {
let mut rules = HashMap::new();
for rule in config.rules {
rules.insert(rule.name.clone(), rule);
}

RuleExecutor { rules }
}

pub fn run(&self, name: &str) -> Result<(), Box<dyn std::error::Error>> {
if let Some(rule) = self.rules.get(name) {
println!("Executing rule: {}", rule.name);
// Iterate over the ports and attempt to connect to each
for port in rule.sequence.iter() {
let address = format!("{}:{}", rule.host, port);
let addr: Vec<SocketAddr> = address.to_socket_addrs()?.collect();
println!("knocking at: {:?}", addr);

// Attempt to connect to the target IP and port
if let Ok(stream) = TcpStream::connect_timeout(&addr[0], Duration::from_millis(100))
{
drop(stream);
}
}
} else {
println!("Rule not found: {}", name);
return Ok(());
}

println!("Rule execution complete.");
Ok(())
}
}
6 changes: 3 additions & 3 deletions knockd/config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
interface: "enp3s0"
timeout: 5
rules:
- name: "Enable SSH"
- name: "enable_ssh"
command: "/usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT"
sequence:
- 15523
- 17767
- 32768
- 28977
- 51234
- name: "Disable SSH"
- name: "disable_ssh"
command: "/usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT"
sequence:
- 51234
- 28977
- 32768
- 17767
- 15523
- 15523

0 comments on commit be34d2d

Please sign in to comment.