Skip to content

Commit

Permalink
Merge pull request #7 from nberlee/docs
Browse files Browse the repository at this point in the history
chore: update docs
  • Loading branch information
nberlee committed Mar 27, 2023
2 parents d6059be + f84be2e commit 2fd7718
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 12 deletions.
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
MIT License

Copyright (c) 2018 Cihangir Akturk
Copyright (c) 2023 Nico Berlee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
158 changes: 146 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,150 @@
### Netstat implementation for Talos Linux
# go-netstat
go-netstat is a Golang library that provides a fast and multi-threaded implementation of the netstat utility on Linux. It is designed to be feature-complete with the net-tools netstat implementation and supports network namespaces for containers. It was written with Talos Linux in mind.

## Installation
You can install go-netstat by running the following command:
```bash
go get github.com/nberlee/go-netstat/netstat
```
Usage of ./go-netstat:
-4 display only IPv4 sockets
-6 display only IPv6 sockets
-U display udplite sockets
-a display all sockets (default: connected)
-l display listening server sockets
-n don't resolve names (default true)
-p display PID/Program name for sockets
-t display tcp sockets
-u display udp sockets
-w display raw sockets

## Usage
Here's an example of how to use go-netstat:

```go
import (
"context"
"fmt"

"github.com/nberlee/go-netstat/netstat"
)

func main() {
ctx := context.Background()

features := netstat.EnableFeatures{
TCP: true,
TCP6: true,
UDP: true,
UDP6: true,
UDPLite: true,
UDPLite6: true,
Raw: true,
Raw6: true,
PID: true,
NoHostNetwork: false,
AllNetNs: true,
NetNsName: []string{},
NetNsPids: []uint32{},
}

fn := netstat.NoopFilter

netstatResp, err := netstat.Netstat(ctx, features, fn)
if err != nil {
panic(err)
}

for _, entry := range netstatResp {
fmt.Println(entry)
}
}
```
The `features` struct specifies which types of sockets and connections to include in the result, while the `fn` function can be used to filter the results further.

## Contributing
We welcome contributions to go-netstat! If you have bug fixes, feature requests, or performance improvements, feel free to submit a pull request. We are especially interested in contributions that are close to the core functionality and that benefit Talos Linux netstat.

## Credits
The initial version of go-netstat was written by Cihangir Akturk, who contributed the functions ParseAddr, ParseIpv4, and ParseIpv6. Nico Berlee later rewrote and reworked every other function to make it faster by multi-threading and to add features like network namespaces, udplite+raw support and tests.

## License
go-netstat is released under the MIT License. See [LICENSE](https://github.com/nberlee/go-netstat/blob/main/LICENSE) for details.

## Types
### EnableFeatures
The EnableFeatures struct specifies which types of sockets and connections to include in the result.
```go
type EnableFeatures struct {
TCP bool
TCP6 bool
UDP bool
UDP6 bool
UDPLite bool
UDPLite6 bool
Raw bool
Raw6 bool
PID bool
NoHostNetwork bool
AllNetNs bool
NetNsName []string
NetNsPids []uint32
}
```

### SockTabEntry
The SockTabEntry struct represents each line of the /proc/net/[tcp|udp] file.
```go
type SockTabEntry struct {
Transport string
LocalEndpoint *SockEndpoint
RemoteEndpoint *SockEndpoint
State SkState
TxQueue uint64
RxQueue uint64
Tr TimerActive
TimerWhen uint64
Retrnsmt uint64
UID uint32
Timeout uint64
Inode uint64
Ref uint64
Process *common.Process
NetNS string
}
```

### SockEndpoint

The `SockEndpoint` struct represents an IP address and port.

```go
type SockEndpoint struct {
IP net.IP
Port uint16
}
```
The `IP` field can be an IPv4 or IPv6 address.

## Filter Function
The fn function is used to filter the results of the Netstat function.
```go
type FilterFunc func(*SockTabEntry) bool
```

Here are some examples of filter functions:
```go
func NoopFilter(s *SockTabEntry) bool {
return true
}

func ConnectedFilter(s *SockTabEntry) bool {
return s.State != Listen
}

func ListeningFilter(s *SockTabEntry) bool {
return s.State == Listen
}
```

## Design decisions
* /proc/net/[tcp|udp|udplite|raw] are chosen over syscalls as accessing directly kernel data structures is can be faster than making syscalls with context switching overhead.
* `go-netstat` does not enter an network namespace, instead it gets the process id and reads the /proc/`processid`/net/[tcp|udp|udplite|raw]. This is safer and faster.

### Flows

#### Network namespace
Network Namespace Name -> Find in `/var/run/netns` -> Follow bindmount to /proc/`processid`/ns/net, get the symlink which is if for `net:[12345678]`. Search in /proc/`processid`/ns/net for the file descriptor with the same symlink.

#### Process ID + Name
To enrich netstat entries with the process id, the inode is matched against /proc/`processid`/fd/* symlinks.

0 comments on commit 2fd7718

Please sign in to comment.