Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Binaries and object files
bin/
*.o
*.elf

# Rust build artifacts
**/target/
**/Cargo.lock

# Go build/test artifacts
*.test
*.out

# Logs
logs/
*.log

# Editor and system files
.DS_Store
*.swp
*.swo
*.bak
*.tmp

# IDE/editor folders
.vscode/
.idea/

# Node or frontend stuff (if added in future)
node_modules/
dist/
Binary file removed bin/connect_count.o
Binary file not shown.
Binary file removed bin/ssh_block.o
Binary file not shown.
Binary file modified bin/ssh_monitor.o
Binary file not shown.
Binary file removed bin/udp_monitor.o
Binary file not shown.
25 changes: 0 additions & 25 deletions bpf/connect_count.c

This file was deleted.

58 changes: 0 additions & 58 deletions bpf/ssh_monitor.c

This file was deleted.

50 changes: 0 additions & 50 deletions bpf/udp_monitor.c

This file was deleted.

12 changes: 12 additions & 0 deletions core/iputils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package core

import (
"encoding/binary"
"net"
)

func FormatIPv4(ip uint32) string {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, ip)
return net.IP(b).String()
}
95 changes: 93 additions & 2 deletions core/ssh.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,102 @@
package core

import (

"encoding/binary"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"time"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/link"
)

// Must match the Rust struct `SshKey { pid: u32, ip: u32 }`
type sshKey struct {
PID uint32
IP uint32
}

func RunSSHMonitor() {
runMonitor("bin/ssh_monitor.o", "count_ssh", "ssh_attempts", "kprobe", "sys_connect")
const (
bpfFile = "bin/ssh_monitor.o"
progName = "trace_ssh"
mapName = "ssh_attempts"
)

fmt.Printf("Starting SSH monitor: %s on tracepoint sys_enter_connect\n", progName)

spec, err := ebpf.LoadCollectionSpec(bpfFile)
if err != nil {
log.Fatalf("Failed to load eBPF spec: %v", err)
}

coll, err := ebpf.NewCollection(spec)
if err != nil {
log.Fatalf("Failed to create eBPF collection: %v", err)
}
defer coll.Close()

prog, ok := coll.Programs[progName]
if !ok {
log.Fatalf("Program %s not found in .o file", progName)
}
defer prog.Close()

kprobe, err := link.Kprobe("tcp_v4_connect", prog, nil)
if err != nil {
log.Fatalf("Failed to attach kprobe: %v", err)
}
defer kprobe.Close()


m, ok := coll.Maps[mapName]
if !ok {
log.Fatalf("Map %s not found", mapName)
}
defer m.Close()

fmt.Println("eBPF program attached. Watching SSH connections every 3 seconds...")

sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)

ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()

for {
select {
case <-ticker.C:
iter := m.Iterate()
var key sshKey
var value uint32
total := uint32(0)

fmt.Println("[ssh_attempts] PID@IP -> Count")
for iter.Next(&key, &value) {
ipStr := formatIPv4(key.IP)
fmt.Printf(" %d@%s -> %d\n", key.PID, ipStr, value)
total += value
}

if err := iter.Err(); err != nil {
log.Printf("Map iteration error: %v", err)
}
fmt.Printf("[ssh_attempts] Total Attempts: %d\n\n", total)

case <-sig:
fmt.Println("Stopping SSH monitor...")
return
}
}
}

// Converts uint32 IP to dotted IPv4 string
func formatIPv4(ip uint32) string {
ipBytes := make([]byte, 4)
binary.LittleEndian.PutUint32(ipBytes, ip)
return net.IP(ipBytes).String()
}
9 changes: 1 addition & 8 deletions core/udp.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package core

import (
"encoding/binary"
"fmt"
"log"
"os"
Expand Down Expand Up @@ -78,7 +77,7 @@ func RunUDPMonitor() {

fmt.Println("[udp_attempts] PID@IP -> Count")
for iter.Next(&key, &value) {
ipStr := formatIPv4(key.DstIP)
ipStr := FormatIPv4(key.DstIP)
fmt.Printf(" %d@%s -> %d\n", key.PID, ipStr, value)
total += value
}
Expand All @@ -94,9 +93,3 @@ func RunUDPMonitor() {
}
}
}

func formatIPv4(n uint32) string {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, n)
return fmt.Sprintf("%d.%d.%d.%d", b[0], b[1], b[2], b[3])
}
9 changes: 9 additions & 0 deletions ebpf-programs/ssh_monitor/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### https://raw.github.com/github/gitignore/master/Rust.gitignore

# Generated by Cargo
# will have compiled files and executables
debug/
target/

# These are backup files generated by rustfmt
**/*.rs.bk
18 changes: 18 additions & 0 deletions ebpf-programs/ssh_monitor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "ssh_monitor_ebpf"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["staticlib"]
name = "ssh_monitor_ebpf"

[dependencies]
aya-ebpf = { version = "0.1.1", default-features = false }

[profile.release]
opt-level = "z"
lto = true
panic = "abort"
codegen-units = 1
strip = "debuginfo"
4 changes: 4 additions & 0 deletions ebpf-programs/ssh_monitor/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[toolchain]
channel = "nightly"
components = ["rust-src"]
targets = ["bpfel-unknown-none"]
Loading