mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 00:24:40 +01:00
Allow to intercept more kernel connections (#513)
* Allow to intercept some kernel connections Some connections are initiated from kernel space, like WireGuard VPNs (#454), NFS or SMB connections (#502) and ip tunnels (#500). Note: This feature is complete for x86_64, WIP for aarch64, and not supported for armhf and i386 https://github.com/evilsocket/opensnitch/pull/513#issuecomment-924400824 More information regarding this change: #493
This commit is contained in:
parent
2c1acdbfc1
commit
0526b84309
4 changed files with 100 additions and 17 deletions
|
@ -36,6 +36,15 @@ func (p *Process) setCwd(cwd string) {
|
|||
p.CWD = cwd
|
||||
}
|
||||
|
||||
func (p *Process) readComm() error {
|
||||
data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/comm", p.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Comm = core.Trim(string(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Process) readCwd() error {
|
||||
link, err := os.Readlink(fmt.Sprintf("/proc/%d/cwd", p.ID))
|
||||
if err != nil {
|
||||
|
@ -74,6 +83,9 @@ func (p *Process) readPath() error {
|
|||
|
||||
func (p *Process) readCmdline() {
|
||||
if data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", p.ID)); err == nil {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
for i, b := range data {
|
||||
if b == 0x00 {
|
||||
data[i] = byte(' ')
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/core"
|
||||
"github.com/evilsocket/opensnitch/daemon/log"
|
||||
"github.com/evilsocket/opensnitch/daemon/procmon/audit"
|
||||
)
|
||||
|
@ -86,9 +87,6 @@ func GetPIDFromINode(inode int, inodeKey string) int {
|
|||
// If it exists in /proc, a new Process{} object is returned with the details
|
||||
// to identify a process (cmdline, name, environment variables, etc).
|
||||
func FindProcess(pid int, interceptUnknown bool) *Process {
|
||||
if interceptUnknown && pid == -100 {
|
||||
return NewProcess(-100, "Linux kernel")
|
||||
}
|
||||
if interceptUnknown && pid < 0 {
|
||||
return NewProcess(0, "")
|
||||
}
|
||||
|
@ -115,22 +113,32 @@ func FindProcess(pid int, interceptUnknown bool) *Process {
|
|||
return proc
|
||||
}
|
||||
}
|
||||
|
||||
linkName := fmt.Sprint("/proc/", pid, "/exe")
|
||||
if _, err := os.Lstat(linkName); err != nil {
|
||||
// if the PID dir doesn't exist, the process may have exited or be a kernel connection
|
||||
// XXX: can a kernel connection exist without an entry in ProcFS?
|
||||
if core.Exists(fmt.Sprint("/proc/", pid)) == false {
|
||||
log.Debug("PID can't be read /proc/", pid)
|
||||
return nil
|
||||
}
|
||||
|
||||
if link, err := os.Readlink(linkName); err == nil {
|
||||
proc := NewProcess(pid, link)
|
||||
linkName := fmt.Sprint("/proc/", pid, "/exe")
|
||||
link, err := os.Readlink(linkName)
|
||||
proc := NewProcess(pid, link)
|
||||
proc.readCmdline()
|
||||
proc.readCwd()
|
||||
proc.readEnv()
|
||||
proc.cleanPath()
|
||||
|
||||
proc.readCmdline()
|
||||
proc.readCwd()
|
||||
proc.readEnv()
|
||||
proc.cleanPath()
|
||||
|
||||
addToActivePidsCache(uint64(pid), proc)
|
||||
return proc
|
||||
if len(proc.Args) == 0 {
|
||||
proc.readComm()
|
||||
proc.Args = make([]string, 0)
|
||||
proc.Args = append(proc.Args, proc.Comm)
|
||||
}
|
||||
return nil
|
||||
|
||||
// If the link to the binary can't be read, the PID may be of a kernel task
|
||||
if err != nil || proc.Path == "" {
|
||||
proc.Path = "Kernel connection"
|
||||
}
|
||||
|
||||
addToActivePidsCache(uint64(pid), proc)
|
||||
return proc
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ type procStatm struct {
|
|||
// Process holds the details of a process.
|
||||
type Process struct {
|
||||
ID int
|
||||
Comm string
|
||||
Path string
|
||||
Args []string
|
||||
Env map[string]string
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
//uncomment if building on x86_32
|
||||
//#define OPENSNITCH_x86_32
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/version.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <uapi/linux/tcp.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/udp_tunnel.h>
|
||||
#include <net/inet_sock.h>
|
||||
|
||||
#define MAPSIZE 12000
|
||||
|
@ -97,6 +100,7 @@ struct udpv6_value_t{
|
|||
u64 counter;
|
||||
}__attribute__((packed));
|
||||
|
||||
|
||||
// on x86_32 "struct sock" is arranged differently from x86_64 (at least on Debian kernels).
|
||||
// We hardcode offsets of IP addresses.
|
||||
struct sock_on_x86_32_t {
|
||||
|
@ -224,7 +228,6 @@ int kprobe__tcp_v4_connect(struct pt_regs *ctx)
|
|||
return 0;
|
||||
};
|
||||
|
||||
|
||||
SEC("kretprobe/tcp_v4_connect")
|
||||
int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
|
||||
{
|
||||
|
@ -253,6 +256,7 @@ int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
|
|||
tcp_value.uid = bpf_get_current_uid_gid() & 0xffffffff;
|
||||
tcp_value.counter = *val;
|
||||
bpf_map_update_elem(&tcpMap, &tcp_key, &tcp_value, BPF_ANY);
|
||||
|
||||
u64 newval = *val + 1;
|
||||
bpf_map_update_elem(&tcpcounter, &zero_key, &newval, BPF_ANY);
|
||||
bpf_map_delete_elem(&tcpsock, &pid_tgid);
|
||||
|
@ -274,6 +278,7 @@ int kprobe__tcp_v6_connect(struct pt_regs *ctx)
|
|||
bpf_map_update_elem(&tcpv6sock, &pid_tgid, &skp, BPF_ANY);
|
||||
return 0;
|
||||
};
|
||||
|
||||
SEC("kretprobe/tcp_v6_connect")
|
||||
int kretprobe__tcp_v6_connect(struct pt_regs *ctx)
|
||||
{
|
||||
|
@ -309,6 +314,7 @@ int kretprobe__tcp_v6_connect(struct pt_regs *ctx)
|
|||
tcpv6_value.uid = bpf_get_current_uid_gid() & 0xffffffff;
|
||||
tcpv6_value.counter = *val;
|
||||
bpf_map_update_elem(&tcpv6Map, &tcpv6_key, &tcpv6_value, BPF_ANY);
|
||||
|
||||
u64 newval = *val + 1;
|
||||
bpf_map_update_elem(&tcpv6counter, &zero_key, &newval, BPF_ANY);
|
||||
bpf_map_delete_elem(&tcpv6sock, &pid_tgid);
|
||||
|
@ -359,6 +365,7 @@ int kprobe__udp_sendmsg(struct pt_regs *ctx)
|
|||
udp_value.uid = bpf_get_current_uid_gid() & 0xffffffff;
|
||||
udp_value.counter = *counterVal;
|
||||
bpf_map_update_elem(&udpMap, &udp_key, &udp_value, BPF_ANY);
|
||||
|
||||
u64 newval = *counterVal + 1;
|
||||
bpf_map_update_elem(&udpcounter, &zero_key, &newval, BPF_ANY);
|
||||
}
|
||||
|
@ -427,6 +434,61 @@ int kprobe__udpv6_sendmsg(struct pt_regs *ctx)
|
|||
|
||||
};
|
||||
|
||||
SEC("kprobe/iptunnel_xmit")
|
||||
int kprobe__iptunnel_xmit(struct pt_regs *ctx)
|
||||
{
|
||||
#ifdef OPENSNITCH_x86_32
|
||||
// TODO
|
||||
return 0;
|
||||
#else
|
||||
struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM3(ctx);
|
||||
u32 src = (u32)PT_REGS_PARM4(ctx);
|
||||
u32 dst = (u32)PT_REGS_PARM5(ctx);
|
||||
#endif
|
||||
|
||||
u16 sport = 0;
|
||||
unsigned char *head;
|
||||
u16 pkt_hdr;
|
||||
__builtin_memset(&head, 0, sizeof(head));
|
||||
__builtin_memset(&pkt_hdr, 0, sizeof(pkt_hdr));
|
||||
bpf_probe_read(&head, sizeof(head), &skb->head);
|
||||
bpf_probe_read(&pkt_hdr, sizeof(pkt_hdr), &skb->transport_header);
|
||||
struct udphdr *udph;
|
||||
__builtin_memset(&udph, 0, sizeof(udph));
|
||||
|
||||
udph = (struct udphdr *)(head + pkt_hdr);
|
||||
bpf_probe_read(&sport, sizeof(sport), &udph->source);
|
||||
sport = (sport >> 8) | ((sport << 8) & 0xff00);
|
||||
|
||||
struct udp_key_t udp_key;
|
||||
struct udp_value_t udp_value;
|
||||
u32 zero_key = 0;
|
||||
__builtin_memset(&udp_key, 0, sizeof(udp_key));
|
||||
__builtin_memset(&udp_value, 0, sizeof(udp_value));
|
||||
|
||||
bpf_probe_read(&udp_key.sport, sizeof(udp_key.sport), &sport);
|
||||
bpf_probe_read(&udp_key.dport, sizeof(udp_key.dport), &udph->dest);
|
||||
bpf_probe_read(&udp_key.saddr, sizeof(udp_key.saddr), &src);
|
||||
bpf_probe_read(&udp_key.daddr, sizeof(udp_key.daddr), &dst);
|
||||
|
||||
u64 *counterVal = bpf_map_lookup_elem(&udpcounter, &zero_key);
|
||||
if (counterVal == NULL){return 0;}
|
||||
|
||||
struct udp_value_t *lookedupValue = bpf_map_lookup_elem(&udpMap, &udp_key);
|
||||
u64 pid = bpf_get_current_pid_tgid() >> 32;
|
||||
if ( lookedupValue == NULL || lookedupValue->pid != pid) {
|
||||
udp_value.pid = pid;
|
||||
udp_value.uid = bpf_get_current_uid_gid() & 0xffffffff;
|
||||
udp_value.counter = *counterVal;
|
||||
bpf_map_update_elem(&udpMap, &udp_key, &udp_value, BPF_ANY);
|
||||
u64 newval = *counterVal + 1;
|
||||
bpf_map_update_elem(&udpcounter, &zero_key, &newval, BPF_ANY);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
};
|
||||
|
||||
// debug only: increment key's value by 1 in map "bytes"
|
||||
void increment(u32 key){
|
||||
u32 *lookedupValue = bpf_map_lookup_elem(&bytes, &key);
|
||||
|
|
Loading…
Add table
Reference in a new issue