Skip to content

Commit

Permalink
server: support allow_ips (#10)
Browse files Browse the repository at this point in the history
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
  • Loading branch information
cppcoffee authored Jan 13, 2024
1 parent 41b977b commit 01f89d0
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 8 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ anyhow = "1.0"
nfq = "0.2"
# dashmap = "5.5"
clap = { version = "4.4", features = ["derive"] }
pnet = { version = "0.34", features = ["serde"] }
pnet = { version = "0.34", default-features = false, features = ["std", "serde"] }
libc = "0.2"
ipnet = { version = "2.9", default-features = false, features = ["std", "serde"] }

# crypto
rand = "0.8"
rsa = { version = "0.9", features = ["sha2", "std", "pem"] }
rsa = { version = "0.9", default-features = false, features = ["sha2", "std", "pem"] }

# serde
serde = { version = "1.0", features = ["derive"] }
serde = { version = "1.0", default-features = false, features = ["std", "derive"] }
toml = "0.8"

crypto = { path = "./crypto" }
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ $ cargo build --release

## TODO

- Allow IP list
- Add query and reject connection Interfaces
- More certificate signing algorithms
- Reload configuration file
Expand Down
1 change: 1 addition & 0 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ nfq = { workspace = true }
clap = { workspace = true }
pnet = { workspace = true }
libc = { workspace = true }
ipnet = { workspace = true }

# crypto
rand = { workspace = true }
Expand Down
3 changes: 1 addition & 2 deletions server/config/netguard.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ connection_timeout = 300
# 1min. unit: seconds
reclaim_interval = 60

# TODO: more filter
# allow_ips = ["192.168.1.0/24"]
allow_ips = ["192.168.1.0/24"]

[filter.tcp]
# filter tcp 8000 port
Expand Down
10 changes: 9 additions & 1 deletion server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;

use anyhow::{bail, Context, Result};
use ipnet::IpNet;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -51,6 +52,7 @@ pub struct Filter {
pub connection_timeout: u64,
pub tcp: Rule,
pub udp: Rule,
pub allow_ips: Vec<IpNet>,
}

#[derive(Debug, Deserialize)]
Expand All @@ -62,13 +64,18 @@ pub struct Rule {
impl Config {
pub fn from_file(path: &Path) -> Result<Arc<Self>> {
let s = fs::read_to_string(path).context(format!("can't read file: {}", path.display()))?;
let config: Config = toml::from_str(&s)?;
let mut config: Config = toml::from_str(&s)?;

config.verify()?;
config.aggregate();

Ok(Arc::new(config))
}

pub fn aggregate(&mut self) {
self.filter.allow_ips = IpNet::aggregate(&self.filter.allow_ips);
}

fn verify(&self) -> Result<()> {
if self.setting.queue_count == 0 {
bail!("queue_count must be greater than 0");
Expand Down Expand Up @@ -128,6 +135,7 @@ mod tests {
ports: vec![],
reject: false,
},
allow_ips: vec![],
},
};

Expand Down
32 changes: 31 additions & 1 deletion server/src/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::sync::Arc;
use std::thread;
use std::time::Instant;

use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
use ipnet::IpNet;
use nfq::{Queue, Verdict};
use pnet::packet::ip::{IpNextHeaderProtocol, IpNextHeaderProtocols};
use pnet::packet::ipv4::Ipv4Packet;
Expand All @@ -19,6 +20,9 @@ use tracing::{debug, error, info};

use crate::{util, Config, ConntrackEntry, ConntrackMap, Protocol, Sender};

const IPV4_ADDR_BITS: u8 = 32;
const IPV6_ADDR_BITS: u8 = 128;

pub struct Worker {
queue_num: u16,
config: Arc<Config>,
Expand Down Expand Up @@ -98,6 +102,11 @@ impl Worker {
let ip_header = Ipv4Packet::new(payload).ok_or(anyhow!("Malformed IPv4 packet"))?;

let source = IpAddr::V4(ip_header.get_source());

if self.is_allow_ip(&source)? {
return Ok(Verdict::Accept);
}

let destination = IpAddr::V4(ip_header.get_destination());
let protocol = ip_header.get_next_level_protocol();

Expand All @@ -118,6 +127,11 @@ impl Worker {
let ip_header = Ipv6Packet::new(payload).ok_or(anyhow!("Malformed IPv6 packet"))?;

let source = IpAddr::V6(ip_header.get_source());

if self.is_allow_ip(&source)? {
return Ok(Verdict::Accept);
}

let destination = IpAddr::V6(ip_header.get_destination());
let protocol = ip_header.get_next_header();

Expand Down Expand Up @@ -256,6 +270,22 @@ impl Worker {
Ok(Verdict::Drop)
}

fn is_allow_ip(&self, source: &IpAddr) -> Result<bool> {
if self.config.filter.allow_ips.is_empty() {
return Ok(false);
}

let bits = match source {
IpAddr::V4(_) => IPV4_ADDR_BITS,
IpAddr::V6(_) => IPV6_ADDR_BITS,
};

let src_ip =
IpNet::new(*source, bits).context(format!("IpNet::new({}, {}) fail", source, bits))?;

Ok(self.config.filter.allow_ips.contains(&src_ip))
}

fn is_auth_port(&self, protocol: Protocol, dst_port: u16) -> bool {
self.config.auth.protocol == protocol && self.config.auth.port == dst_port
}
Expand Down

0 comments on commit 01f89d0

Please sign in to comment.