snifferlib

package module
v0.0.0-...-0926741 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 11, 2025 License: MIT Imports: 24 Imported by: 0

README

sniffer

GoDoc Go Report Card License

A modern alternative network traffic sniffer inspired by bandwhich(Rust) and nethogs(C++).

https://user-images.githubusercontent.com/19553554/147360587-a3cfee18-7eb6-464b-9173-9afe6ee86cdf.mov

Introduction

中文介绍

sniffer is designed for network troubleshooting. It can be started at any time to analyze the processes or connections causing increases in network traffic without loading any kernel modules. By the way, the TUI of it is responsive that can fit with terminals of all sizes automatically.

sniffer manipulates gopacket to sniff the interfaces and record packets' info. gopacket wraps the Golang port of libpacp library, and provides some additional features. One of the projects that inspired the sniffer is bandwhich, which has a sophisticated interface and multiple ways to display data, but it does not support BPF filters. Another one is nethlogs, which supports BPF filters, but can only view data by process, without connections or remote address perspective. sniffer combines the advantages of those two projects also adhering a new Plot mode.

Connections and Process Matching

On Linux, sniffer refers to the ways in which the ss tool used, obtaining the connections of the ESTABLISHED state by netlink socket. Since that approach is more efficient than reading the /proc/net/* files directly. But both need to aggregate and calculate the network traffic of the process by matching the inode information under /proc/${pid}/fd.

On macOS, the lsof command is invoked, which relies on capturing the command output for analyzing process connections information. And sniffer manipulates the API provided by gopsutil directly on Windows.

Installation

sniffer relies on the libpcap library to capture user-level packets hence you need to have it installed first.

Linux / Windows

Debian/Ubuntu

$ sudo apt-get install libpcap-dev

CentOS/Fedora

$ sudo yum install libpcap libpcap-devel

Windows

Windows need to have npcap installed for capturing packets.

After that, install sniffer by go get command.

$ go get -u github.com/chenjiandongx/sniffer
MacOS
$ brew install sniffer

Usages

❯ sniffer -h
# A modern alternative network traffic sniffer.

Usage:
  sniffer [flags]

Examples:
  # bytes mode in MB unit
  $ sniffer -u MB

  # only capture the TCP protocol packets with lo,eth prefixed devices
  $ sniffer -b tcp -d lo -d eth

Flags:
  -a, --all-devices                  listen all devices if present
  -b, --bpf string                   specify string pcap filter with the BPF syntax (default "tcp or udp")
  -d, --devices-prefix stringArray   prefixed devices to monitor (default [en,lo,eth,em,bond])
  -h, --help                         help for sniffer
  -i, --interval int                 interval for refresh rate in seconds (default 1)
  -l, --list                         list all devices name
  -m, --mode int                     view mode of sniffer (0: bytes 1: packets 2: plot)
  -n, --no-dns-resolve               disable the DNS resolution
  -u, --unit string                  unit of traffic stats, optional: B, Kb, KB, Mb, MB, Gb, GB (default "KB")
  -v, --version                      version for sniffer

Hotkeys

Keys Description
Space pause refreshing
Tab rearrange tables
s switch next view mode
q quit

Performance

iperf is a tool for active measurements of the maximum achievable bandwidth on IP networks. Next we use this tool to forge massive packets on the lo device.

$ iperf -s -p 5001
$ iperf -c localhost --parallel 40 -i 1 -t 2000

sniffer vs bandwhich vs nethogs

As you can see, CPU overheads bandwhich > sniffer > nethogs, memory overheads sniffer > nethogs > bandwhich.

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 128405 root      20   0  210168   5184   3596 S  31.0   0.3   1:21.69 bandwhich
 128596 root      20   0 1449872  21912   8512 S  20.7   1.1   0:28.54 sniffer
 128415 root      20   0   18936   7464   6900 S   5.7   0.4   0:11.56 nethogs

See what stats they show, sniffer and bandwhich output are very approximate(~ 2.5GB/s). netlogs can only handles packets 1.122GB/s.

sniffer bandwhich nethogs
Upload 2.5GiBps 2.5GiBps 1.12GiBps

View Mode

Bytes Mode: display traffic stats in bytes by the Table widget.

Packets Mode: display traffic stats in packets by the Table widget.

License

MIT ©chenjiandongx

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ListAllDevices

func ListAllDevices() ([]pcap.Interface, error)

func UseAllDevices

func UseAllDevices() []string

Types

type Connection

type Connection struct {
	Local  LocalSocket
	Remote RemoteSocket
}

type ConnectionData

type ConnectionData struct {
	DownloadBytes   int
	UploadBytes     int
	UploadPackets   int
	DownloadPackets int
	ProcessName     string
	InterfaceName   string
	ProcessId       int32
}

func (*ConnectionData) DivideBy

func (d *ConnectionData) DivideBy(n int)

type ConnectionInfo

type ConnectionInfo struct {
	Interface       string
	UploadPackets   int
	DownloadPackets int
	UploadBytes     int
	DownloadBytes   int
}

type ConnectionsResult

type ConnectionsResult struct {
	Conn Connection
	Data *ConnectionData
}

type DNSResolver

type DNSResolver struct {
	// contains filtered or unexported fields
}

func NewDnsResolver

func NewDnsResolver() *DNSResolver

func (*DNSResolver) Close

func (c *DNSResolver) Close()

func (*DNSResolver) Lookup

func (c *DNSResolver) Lookup(ip string) string

Lookup resolve remote ip to the domains.

type Direction

type Direction uint8
const (
	DirectionUpload Direction = iota
	DirectionDownload
)

type LocalSocket

type LocalSocket struct {
	IP       string
	Port     uint16
	Protocol Protocol
}

type Lookup

type Lookup func(string) string

type NetworkData

type NetworkData struct {
	UploadBytes     int
	DownloadBytes   int
	UploadPackets   int
	DownloadPackets int
	ConnCount       int
}

func (*NetworkData) DivideBy

func (d *NetworkData) DivideBy(n int)

type OpenSockets

type OpenSockets map[LocalSocket]ProcessInfo

type Options

type Options struct {
	// BPFFilter is the string pcap filter with the BPF syntax
	// eg. "tcp and port 80"
	BPFFilter string

	// Interval is the interval for refresh rate in seconds
	Interval int

	// ViewMode represents the sniffer view mode, optional: bytes, packets, processes
	ViewMode ViewMode

	// DevicesPrefix represents prefixed devices to monitor
	DevicesPrefix []string

	// Unit of stats in processes mode, optional: B, Kb, KB, Mb, MB, Gb, GB
	Unit Unit

	// DisableDNSResolve decides whether if disable the DNS resolution
	DisableDNSResolve bool

	// AllDevices specifies whether to listen all devices or not
	AllDevices bool
}

Options is the options set for the sniffer instance.

func DefaultOptions

func DefaultOptions() Options

func (Options) Validate

func (o Options) Validate() error

type PcapClient

type PcapClient struct {
	// contains filtered or unexported fields
}

func NewPcapClient

func NewPcapClient(lookup Lookup, opt Options) (*PcapClient, error)

func (*PcapClient) Close

func (c *PcapClient) Close()

type ProcessInfo

type ProcessInfo struct {
	Pid       int
	Name      string
	ProcessId int32
}

func (ProcessInfo) ProcId

func (p ProcessInfo) ProcId() int32

func (ProcessInfo) String

func (p ProcessInfo) String() string

type ProcessesResult

type ProcessesResult struct {
	ProcessName string
	Data        *NetworkData
}

type Protocol

type Protocol string
const (
	ProtoTCP Protocol = "tcp"
	ProtoUDP Protocol = "udp"
)

type RemoteAddrsResult

type RemoteAddrsResult struct {
	Addr string
	Data *NetworkData
}

type RemoteSocket

type RemoteSocket struct {
	IP   string
	Port uint16
}

type Segment

type Segment struct {
	Interface  string
	DataLen    int
	Connection Connection
	Direction  Direction
}

type Sinker

type Sinker struct {
	// contains filtered or unexported fields
}

func NewSinker

func NewSinker() *Sinker

func (*Sinker) Fetch

func (c *Sinker) Fetch(seg Segment)

func (*Sinker) GetUtilization

func (c *Sinker) GetUtilization() Utilization

type Snapshot

type Snapshot struct {
	Processes            map[string]*NetworkData
	RemoteAddrs          map[string]*NetworkData
	Connections          map[Connection]*ConnectionData
	TotalUploadBytes     int
	TotalDownloadBytes   int
	TotalUploadPackets   int
	TotalDownloadPackets int
	TotalConnections     int
}

func (*Snapshot) TopNConnections

func (s *Snapshot) TopNConnections(n int, mode ViewMode) []ConnectionsResult

func (*Snapshot) TopNProcesses

func (s *Snapshot) TopNProcesses(n int, mode ViewMode) []ProcessesResult

func (*Snapshot) TopNRemoteAddrs

func (s *Snapshot) TopNRemoteAddrs(n int, mode ViewMode) []RemoteAddrsResult

type Sniffer

type Sniffer struct {
	// contains filtered or unexported fields
}

func NewSniffer

func NewSniffer(opts Options) (*Sniffer, error)

func (*Sniffer) Close

func (s *Sniffer) Close()

func (*Sniffer) Refresh

func (s *Sniffer) Refresh()

func (*Sniffer) Start

func (s *Sniffer) Start()

func (*Sniffer) SwitchViewMode

func (s *Sniffer) SwitchViewMode()

type SnifferLib

type SnifferLib struct {
	// contains filtered or unexported fields
}

func NewSnifferLib

func NewSnifferLib() *SnifferLib

func (*SnifferLib) Close

func (s *SnifferLib) Close()

func (*SnifferLib) GetStats

func (s *SnifferLib) GetStats() *Snapshot

type SocketFetcher

type SocketFetcher interface {
	GetOpenSockets() (OpenSockets, error)
}

func GetSocketFetcher

func GetSocketFetcher() SocketFetcher

type Stat

type Stat struct {
	OpenSockets OpenSockets
	Utilization Utilization
}

type StatsManager

type StatsManager struct {
	// contains filtered or unexported fields
}

func NewStatsManager

func NewStatsManager(opt Options) *StatsManager

func (*StatsManager) GetStats

func (s *StatsManager) GetStats() interface{}

func (*StatsManager) Put

func (s *StatsManager) Put(stat Stat)

type Unit

type Unit string
const (
	UnitB  Unit = "B"
	UnitKB Unit = "KB"
	UnitKb Unit = "Kb"
	UnitMB Unit = "MB"
	UnitMb Unit = "Mb"
	UnitGB Unit = "GB"
	UnitGb Unit = "Gb"
)

func (Unit) Ratio

func (u Unit) Ratio() float64

func (Unit) String

func (u Unit) String() string

func (Unit) Validate

func (u Unit) Validate() error

type Utilization

type Utilization map[Connection]*ConnectionInfo

type ViewMode

type ViewMode uint8
const (
	ModeTableBytes ViewMode = iota
	ModeTablePackets
	ModePlotProcesses
)

func (ViewMode) Validate

func (vm ViewMode) Validate() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL