Skip to content

Commit

Permalink
Add ipv6.
Browse files Browse the repository at this point in the history
  • Loading branch information
Drew Vogel committed Jul 25, 2023
1 parent f3d577a commit 1676819
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 13 deletions.
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM debian:12-slim

MAINTAINER Drew Vogel

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update && \
apt-get install -y aptitude build-essential git cmake \
zlib1g-dev libevent-dev \
libelf-dev llvm \
clang libc6-dev-i386

RUN mkdir /opt/certspook
WORKDIR /opt/certspook

ENTRYPOINT ["/bin/bash"]
CMD ["-l"]

16 changes: 16 additions & 0 deletions run-test-container
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

# CAP_BPF and CAP_PERFMON will be supported on AWS Fargate:
# https://github.com/aws/containers-roadmap/issues/1027#issuecomment-1433911314

# In theory this should be able to run with these capabilities but practice
# shows otherwise:
# --cap-add CAP_BPF --cap-add CAP_PERFMON --cap-add CAP_SYS_RESOURCE \

podman run -it \
--privileged \
-v "$PWD/target/debug:/opt/certspook" \
--entrypoint /bin/bash \
certspook:latest \
-l

5 changes: 5 additions & 0 deletions src/bpf/certspook.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,17 @@ SEC("kprobe/__sys_connect")
int BPF_KPROBE(probe_sys_connect, int fd, struct sockaddr *addr, int addrlen) {
__u16 sk_family;
struct sockaddr_in addr_in;
struct sockaddr_in6 addr_in6;

if (bpf_probe_read_user(&sk_family, sizeof(sk_family), &addr->sa_family) == 0) {
if (sk_family == AF_INET) {
if (bpf_probe_read_user(&addr_in, sizeof(addr_in), addr) == 0) {
bpf_ringbuf_output(&connaddrs, &addr_in, sizeof(addr_in), 0);
}
} else if (sk_family == AF_INET6) {
if (bpf_probe_read_user(&addr_in6, sizeof(addr_in6), addr) == 0) {
bpf_ringbuf_output(&connaddrs, &addr_in6, sizeof(addr_in6), 0);
}
}
}

Expand Down
83 changes: 70 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// SPDX-License-Identifier: GPL-3.0

use core::time::Duration;
use std::fmt;
use std::time::Duration;

use anyhow::bail;
use anyhow::Result;
use libbpf_rs::skel::OpenSkel;
use libbpf_rs::skel::Skel;
use libbpf_rs::skel::SkelBuilder;
use libbpf_rs::RingBufferBuilder;
use libc; // TODO: replace custom sockaddr implementations with libc
use plain::Plain;
use std::mem;

Expand All @@ -17,12 +19,19 @@ mod certspook {

use certspook::*;

#[repr(C)]
#[derive(Default, Copy, Clone)]
struct in_addr {
pub s_addr: u32,
}

#[repr(C)]
#[derive(Default, Copy, Clone)]
struct sockaddr_in {
pub sin_family: u16,
pub sin_port: u16,
pub sin_addr: u32,
pub sin_addr: in_addr,
pub sin_zero: [u8; 8],
}

unsafe impl Plain for sockaddr_in {}
Expand All @@ -33,9 +42,59 @@ impl sockaddr_in {
}

fn bytelen() -> usize {
return 16;
// return 16;
// TODO: Why does mem::size_of return 8?
// return mem::size_of::<sockaddr_in>();
return mem::size_of::<sockaddr_in>();
}
}

impl fmt::Display for sockaddr_in {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// TODO: The bytes will be in host order in sockaddr_in so this is not portable.
write!(
f,
"{}.{}.{}.{}:{}",
(self.sin_addr.s_addr & 0xFF),
(self.sin_addr.s_addr >> 8) & 0xFF,
(self.sin_addr.s_addr >> 16) & 0xFF,
(self.sin_addr.s_addr >> 24) & 0xFF,
((self.sin_port >> 8) & 0xFF) | ((self.sin_port << 8) & 0xFF00)
)
}
}

#[repr(C)]
#[derive(Default, Copy, Clone)]
struct sockaddr_in6 {
pub sin6_family: u16,
pub sin6_port: u16,
pub sin6_flowinfo: u32,
pub sin6_addr: [u8; 16],
pub sin6_scope_id: u32,
}

unsafe impl Plain for sockaddr_in6 {}

impl sockaddr_in6 {
fn from_bytes(buf: &[u8]) -> &sockaddr_in6 {
plain::from_bytes(buf).expect("Buffer cannot be decoded into sockaddr_in.")
}

fn bytelen() -> usize {
// return 28;
// TODO: Can this be made to work?
return mem::size_of::<sockaddr_in6>();
}
}

impl fmt::Display for sockaddr_in6 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"[{}]:{}",
std::net::Ipv6Addr::from(self.sin6_addr),
self.sin6_port,
)
}
}

Expand All @@ -56,15 +115,10 @@ fn bump_memlock_rlimit() -> Result<()> {
fn handle_record(bytes: &[u8]) -> i32 {
if bytes.len() == sockaddr_in::bytelen() {
let addr_in = sockaddr_in::from_bytes(bytes);
// TODO: The bytes will be in host order in sockaddr_in so this is not portable.
println!(
"{}.{}.{}.{}:{}",
addr_in.sin_addr & 0xFF,
(addr_in.sin_addr >> 8) & 0xFF,
(addr_in.sin_addr >> 16) & 0xFF,
(addr_in.sin_addr >> 24) & 0xFF,
((addr_in.sin_port >> 8) & 0xFF) | ((addr_in.sin_port << 8) & 0xFF00)
);
println!("ipv4:{}", &addr_in);
} else if bytes.len() == sockaddr_in6::bytelen() {
let addr_in6 = sockaddr_in6::from_bytes(bytes);
println!("ipv6:{}", &addr_in6);
} else {
eprintln!(
"Unrecognized record with byte length of {}, sockaddr_in should have {}",
Expand All @@ -80,6 +134,9 @@ fn handle_lost_events(cpu: i32, count: u64) {
}

fn main() -> Result<()> {
println!("sockaddr_in: {} bytes", sockaddr_in::bytelen());
println!("sockaddr_in6: {} bytes", sockaddr_in6::bytelen());

bump_memlock_rlimit()?;

let mut skel_builder = CertspookSkelBuilder::default();
Expand Down

0 comments on commit 1676819

Please sign in to comment.