- New Host connections tracking from interface like
eth0
usinggoogle/gopacket (pcap)
library- Logging new connections to console output
- Functionality is limited to read the ipv4 layer
- HTTP server with
/metrics
endpoint and new connections countertcptracker_new_connections
- Using locally,
8081
port,http://localhost:8081/metrics
- Using locally,
- Using BPF Filter
tcp[tcpflags] &(tcp-syn) != 0 and tcp[tcpflags] &(tcp-ack) = 0
- Port scan detection
- Single source IP connects to more than 3 host ports in the previous minute
- Blocking source ip using Firewall/IPtables using separate chain
tcptracker
- Using fast cache with 1 minute TTL to expire connections
- Application tries to get
Host IP Address
on start up to put it onallow list
(because we are checking inbound and outbound traffic)
- golang 1.8
- go modules for dependency management
- go-chi - lightweight, idiomatic and composable router for building Go HTTP services
- google/gopacket - Provides packet processing capabilities for Go (pcap)
- coreos/go-iptables - library to manage iptables
- eko/gocache - cache manager
- dgraph-io/ristretto - cache implementation, a high performance memory-bound Go cache
- It provides the TTL functionality
- It's thread safe
- rs/zerolog - logging with minimum allocations
- prometheus/client_golang - metrics
- testing - testify assertions, google/gomock mocks, go-cmp - easy comparisons
- Makefile - for easy build / test scripting, most of the development is done locally, it is good enough to get fast feedback
- Dockerfile - for containerization
- golangci-lint linters
- Github Actions CI - build, lint, tests
- Codecov - test coverage
To download Golang dependencies make dep
dep:
go mod tidy
Libraries below are needed to run or build the application, libpcap
and iptables
iptables
is usually pre-installed. Package on my OS is iptables-nft
.
Packages on the Host and in docker container should match, if not some tables might be visible with different binary when checking iptables -vnL
apt-get dnf package manager
apt-get install libpcap libpcap-dev iptables
dnf package manager
dnf install libpcap libpcap-devel iptables
You can check the installed iptables
package with
sudo update-alternatives --config iptables
There is 1 program that provides 'iptables'.
Selection Command
-----------------------------------------------
*+ 1 /usr/sbin/iptables-nft
make build
BINARY_NAME=tcptracker
build:
go build -o bin/${BINARY_NAME} ./cmd/main.go
For simplification/shortcut you can try using sudo
but it's not safe enough.
I have faced few issues when using sudo on my local machine this is why you may want to avoid it.
https://dbpilot.net/3-ways-to-list-all-iptables-rules-by-a-non-root-user/
make gorun
- to run with Go
make run
- to run a binary from ./bin/tcptracker
To pass the device interface name to binary you can use -devicename eth0
flag
make DEVICE=eth0 run
DEVICE=eth0
gorun:
sudo setcap cap_net_admin,cap_net_raw+ep go run ./cmd/main.go
run:
sudo setcap cap_net_admin,cap_net_raw+ep ./bin/tcptracker
sudo ./bin/tcptracker -deviceName ${DEVICE}
Docker needs to be installed on the machine and docker daemon needs to be running
make docker_build
BINARY_NAME=tcptracker
docker_build:
docker build -t ${BINARY_NAME} .
make DEVICE=eth0 docker_run
BINARY_NAME=tcptracker
DEVICE=eth0
docker_run:
docker run --name ${BINARY_NAME} --net=host --cap-add NET_ADMIN -t tcptracker:latest -deviceName ${DEVICE}
docker_run_detach:
docker run -d --name ${BINARY_NAME} --net=host --cap-add NET_ADMIN -t tcptracker:latest -deviceName ${DEVICE}
docker_start:
docker start tcptracker
docker_exec:
docker exec -it tcptracker sh
- Running a binary requires additional permissions
setcap cap_net_admin,cap_net_raw+ep ${BINARY_NAME}
- Running a docker with a privileges to Host network requires NET_ADMIN
docker run --name ${BINARY_NAME} --net=host --cap-add NET_ADMIN tcptracker:latest
- Added
TODOs
in source code to document shortcuts - More tests in table tests style
- Concurrent tests are quite basic with a room for improvements
- Code structure could be probably more modular, but depends on the new requirements I would refactor it
- Dockerfile needs some work to have more consistent behaviour with
iptables
packages - Running docker container as root - would need some work to run it in rootless mode
RUN update-alternatives --install /sbin/iptables iptables /sbin/iptables-nft 10
inside the Dockerfile, my OS is using this by default- I would add better Configuration of the application with env variables, in 12factor manner
- Not considered as production ready, something to take look https://github.com/kgoralski/microservice-production-readiness-checklist (but that's for backend development)
- I would add fixtures for tests
- permissions to filter table
"running [/sbin/iptables -t filter -S tcptracker 1 --wait]: exit status 3: iptables v1.8.8 (legacy): can't initialize iptables table `filter': Permission denied\nPerhaps iptables or your kernel needs to be upgraded.\n"
fix sudo modprobe iptable_filter
Found it somewhere here https://github.com/nuBacuk/docker-openvpn-arm64#errors
- iptables device is busy / linked etc.
$ sudo iptables -L INPUT --line-numbers -vn
$ sudo iptables -D INPUT <line_number> # li
or even remove whole chain
$ sudo iptables --flush tcptracker
$ sudo iptables -X tcptracker