-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 06b6e29
Showing
20 changed files
with
473 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[alias] | ||
xtask = "run --package xtask --" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
### https://raw.github.com/github/gitignore/master/Rust.gitignore | ||
|
||
# Generated by Cargo | ||
# will have compiled files and executables | ||
debug/ | ||
target/ | ||
|
||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries | ||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html | ||
Cargo.lock | ||
|
||
# These are backup files generated by rustfmt | ||
**/*.rs.bk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"rust-analyzer.linkedProjects": ["Cargo.toml", "kill-the-devil-ebpf/Cargo.toml"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"rust-analyzer.linkedProjects": ["Cargo.toml", "kill-the-devil-ebpf/Cargo.toml"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[workspace] | ||
members = ["xtask", "kill-the-devil", "kill-the-devil-common"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# kill-the-devil | ||
|
||
## Prerequisites | ||
|
||
1. Install bpf-linker: `cargo install bpf-linker` | ||
|
||
## Build eBPF | ||
|
||
```bash | ||
cargo xtask build-ebpf | ||
``` | ||
|
||
To perform a release build you can use the `--release` flag. | ||
You may also change the target architecture with the `--target` flag. | ||
|
||
## Build Userspace | ||
|
||
```bash | ||
cargo build | ||
``` | ||
|
||
## Run | ||
|
||
```bash | ||
RUST_LOG=info cargo xtask run | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "kill-the-devil-common" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[features] | ||
default = [] | ||
user = ["aya"] | ||
|
||
[dependencies] | ||
aya = { git = "https://github.com/aya-rs/aya.git", optional = true } | ||
|
||
[lib] | ||
path = "src/lib.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#![no_std] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[build] | ||
target-dir = "../target" | ||
target = "bpfel-unknown-none" | ||
|
||
[unstable] | ||
build-std = ["core"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"rust-analyzer.cargo.target": "bpfel-unknown-none", | ||
"rust-analyzer.checkOnSave.allTargets": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"rust-analyzer.cargo.target": "bpfel-unknown-none", | ||
"rust-analyzer.checkOnSave.allTargets": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
[package] | ||
name = "kill-the-devil-ebpf" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
aya-bpf = { git = "https://github.com/aya-rs/aya.git" } | ||
aya-log-ebpf = { git = "https://github.com/aya-rs/aya.git" } | ||
kill-the-devil-common = { path = "../kill-the-devil-common" } | ||
network-types = "0.0.4" | ||
[[bin]] | ||
name = "kill-the-devil" | ||
path = "src/main.rs" | ||
|
||
[profile.dev] | ||
opt-level = 3 | ||
debug = false | ||
debug-assertions = false | ||
overflow-checks = false | ||
lto = true | ||
panic = "abort" | ||
incremental = false | ||
codegen-units = 1 | ||
rpath = false | ||
|
||
[profile.release] | ||
lto = true | ||
panic = "abort" | ||
codegen-units = 1 | ||
|
||
[workspace] | ||
members = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[toolchain] | ||
channel = "nightly" | ||
# The source code of rustc, provided by the rust-src component, is needed for | ||
# building eBPF programs. | ||
components = [ | ||
"cargo", | ||
"clippy", | ||
"rust-docs", | ||
"rust-src", | ||
"rust-std", | ||
"rustc", | ||
"rustfmt", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#![no_std] | ||
#![no_main] | ||
#![allow(nonstandard_style, dead_code)] | ||
|
||
use aya_bpf::{ | ||
bindings::xdp_action, | ||
macros::{map, xdp}, | ||
maps::HashMap, | ||
programs::XdpContext, | ||
}; | ||
use aya_log_ebpf::info; | ||
|
||
use core::mem; | ||
use network_types::{ | ||
eth::{EthHdr, EtherType}, | ||
ip::Ipv4Hdr, | ||
}; | ||
|
||
#[panic_handler] | ||
fn panic(_info: &core::panic::PanicInfo) -> ! { | ||
unsafe { core::hint::unreachable_unchecked() } | ||
} | ||
|
||
#[map] // | ||
static BLOCKLIST: HashMap<u32, u32> = HashMap::<u32, u32>::with_max_entries(1024, 0); | ||
|
||
#[xdp] | ||
pub fn kill_the_devil(ctx: XdpContext) -> u32 { | ||
match try_kill_the_devil(ctx) { | ||
Ok(ret) => ret, | ||
Err(_) => xdp_action::XDP_ABORTED, | ||
} | ||
} | ||
|
||
#[inline(always)] | ||
unsafe fn ptr_at<T>(ctx: &XdpContext, offset: usize) -> Result<*const T, ()> { | ||
let start = ctx.data(); | ||
let end = ctx.data_end(); | ||
let len = mem::size_of::<T>(); | ||
|
||
if start + offset + len > end { | ||
return Err(()); | ||
} | ||
|
||
let ptr = (start + offset) as *const T; | ||
Ok(&*ptr) | ||
} | ||
|
||
// | ||
fn block_ip(address: u32) -> bool { | ||
unsafe { BLOCKLIST.get(&address).is_some() } | ||
} | ||
|
||
fn try_kill_the_devil(ctx: XdpContext) -> Result<u32, ()> { | ||
let ethhdr: *const EthHdr = unsafe { ptr_at(&ctx, 0)? }; | ||
match unsafe { (*ethhdr).ether_type } { | ||
EtherType::Ipv4 => {} | ||
_ => return Ok(xdp_action::XDP_PASS), | ||
} | ||
|
||
let ipv4hdr: *const Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; | ||
let source = u32::from_be(unsafe { (*ipv4hdr).src_addr }); | ||
|
||
// | ||
let action = if block_ip(source) { | ||
xdp_action::XDP_DROP | ||
} else { | ||
xdp_action::XDP_PASS | ||
}; | ||
if action == xdp_action::XDP_DROP { | ||
info!(&ctx, "SRC: {:i}, ACTION: {} DROPPED", source, action); | ||
} | ||
|
||
Ok(action) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
name = "kill-the-devil" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
aya = { git = "https://github.com/aya-rs/aya.git", features = ["async_tokio"] } | ||
aya-log = { git = "https://github.com/aya-rs/aya.git" } | ||
clap = { version = "4.1", features = ["derive"] } | ||
kill-the-devil-common = { path = "../kill-the-devil-common", features = [ | ||
"user", | ||
] } | ||
anyhow = "1" | ||
env_logger = "0.10" | ||
libc = "0.2" | ||
log = "0.4" | ||
tokio = { version = "1.25", features = [ | ||
"macros", | ||
"rt", | ||
"rt-multi-thread", | ||
"net", | ||
"signal", | ||
] } | ||
|
||
[[bin]] | ||
name = "kill-the-devil" | ||
path = "src/main.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
use anyhow::Context; | ||
use aya::{ | ||
include_bytes_aligned, | ||
maps::HashMap, | ||
programs::{Xdp, XdpFlags}, | ||
Bpf, | ||
}; | ||
use aya_log::BpfLogger; | ||
use clap::Parser; | ||
use log::{info, warn}; | ||
use std::net::Ipv4Addr; | ||
use tokio::signal; | ||
|
||
#[derive(Debug, Parser)] | ||
struct Opt { | ||
#[clap(short, long, default_value = "eth0")] | ||
iface: String, | ||
#[clap(short, long, default_value = "1.1.1.1")] | ||
blocklist: String, | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<(), anyhow::Error> { | ||
let opt = Opt::parse(); | ||
|
||
env_logger::init(); | ||
|
||
// This will include your eBPF object file as raw bytes at compile-time and load it at | ||
// runtime. This approach is recommended for most real-world use cases. If you would | ||
// like to specify the eBPF program at runtime rather than at compile-time, you can | ||
// reach for `Bpf::load_file` instead. | ||
#[cfg(debug_assertions)] | ||
let mut bpf = Bpf::load(include_bytes_aligned!( | ||
"../../target/bpfel-unknown-none/debug/kill-the-devil" | ||
))?; | ||
#[cfg(not(debug_assertions))] | ||
let mut bpf = Bpf::load(include_bytes_aligned!( | ||
"../../target/bpfel-unknown-none/release/kill-the-devil" | ||
))?; | ||
if let Err(e) = BpfLogger::init(&mut bpf) { | ||
// This can happen if you remove all log statements from your eBPF program. | ||
warn!("failed to initialize eBPF logger: {}", e); | ||
} | ||
let program: &mut Xdp = bpf.program_mut("kill_the_devil").unwrap().try_into()?; | ||
program.load()?; | ||
program.attach(&opt.iface, XdpFlags::default()) | ||
.context("failed to attach the XDP program with default flags - try changing XdpFlags::default() to XdpFlags::SKB_MODE")?; | ||
|
||
// | ||
let mut blocklist: HashMap<_, u32, u32> = HashMap::try_from(bpf.map_mut("BLOCKLIST").unwrap())?; | ||
|
||
// | ||
|
||
let addrs = &opt | ||
.blocklist | ||
.split_terminator('.') | ||
.map(|s| s.parse::<u8>().unwrap()) | ||
.collect::<Vec<u8>>(); | ||
let block_addr: u32 = Ipv4Addr::new(addrs[0], addrs[1], addrs[2], addrs[3]).try_into()?; | ||
|
||
// | ||
blocklist.insert(block_addr, 0, 0)?; | ||
|
||
info!("Waiting for Ctrl-C..."); | ||
signal::ctrl_c().await?; | ||
info!("Exiting..."); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[package] | ||
name = "xtask" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
anyhow = "1" | ||
clap = { version = "4.1", features = ["derive"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use std::{path::PathBuf, process::Command}; | ||
|
||
use clap::Parser; | ||
|
||
#[derive(Debug, Copy, Clone)] | ||
pub enum Architecture { | ||
BpfEl, | ||
BpfEb, | ||
} | ||
|
||
impl std::str::FromStr for Architecture { | ||
type Err = String; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
Ok(match s { | ||
"bpfel-unknown-none" => Architecture::BpfEl, | ||
"bpfeb-unknown-none" => Architecture::BpfEb, | ||
_ => return Err("invalid target".to_owned()), | ||
}) | ||
} | ||
} | ||
|
||
impl std::fmt::Display for Architecture { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.write_str(match self { | ||
Architecture::BpfEl => "bpfel-unknown-none", | ||
Architecture::BpfEb => "bpfeb-unknown-none", | ||
}) | ||
} | ||
} | ||
|
||
#[derive(Debug, Parser)] | ||
pub struct Options { | ||
/// Set the endianness of the BPF target | ||
#[clap(default_value = "bpfel-unknown-none", long)] | ||
pub target: Architecture, | ||
/// Build the release target | ||
#[clap(long)] | ||
pub release: bool, | ||
} | ||
|
||
pub fn build_ebpf(opts: Options) -> Result<(), anyhow::Error> { | ||
let dir = PathBuf::from("kill-the-devil-ebpf"); | ||
let target = format!("--target={}", opts.target); | ||
let mut args = vec![ | ||
"build", | ||
target.as_str(), | ||
"-Z", | ||
"build-std=core", | ||
]; | ||
if opts.release { | ||
args.push("--release") | ||
} | ||
|
||
// Command::new creates a child process which inherits all env variables. This means env | ||
// vars set by the cargo xtask command are also inherited. RUSTUP_TOOLCHAIN is removed | ||
// so the rust-toolchain.toml file in the -ebpf folder is honored. | ||
|
||
let status = Command::new("cargo") | ||
.current_dir(dir) | ||
.env_remove("RUSTUP_TOOLCHAIN") | ||
.args(&args) | ||
.status() | ||
.expect("failed to build bpf program"); | ||
assert!(status.success()); | ||
Ok(()) | ||
} |
Oops, something went wrong.