Skip to content

Commit

Permalink
Merge branch 'DimaGolomozy-more-exact-bpf-filter'
Browse files Browse the repository at this point in the history
  • Loading branch information
buger committed Jun 9, 2021
2 parents 7e173b0 + b1972fb commit 763ad9b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 36 deletions.
92 changes: 58 additions & 34 deletions capture/capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net"
"os"
"runtime"
"strings"
"sync"
"syscall"
"time"
Expand Down Expand Up @@ -170,21 +171,31 @@ func (l *Listener) ListenBackground(ctx context.Context, handler PacketHandler)
func (l *Listener) Filter(ifi net.Interface) (filter string) {
// https://www.tcpdump.org/manpages/pcap-filter.7.html

port := fmt.Sprintf("portrange 0-%d", 1<<16-1)
if l.port != 0 {
port = fmt.Sprintf("port %d", l.port)
hosts := []string{l.host}
if listenAll(l.host) || isDevice(l.host, ifi) {
hosts = interfaceAddresses(ifi)
}
filter = fmt.Sprintf("%s dst %s", l.Transport, port)
if l.trackResponse {
filter = fmt.Sprintf("%s %s", l.Transport, port)

filter = portsFilter(l.Transport, "dst", l.port)

if len(hosts) != 0 {
filter = fmt.Sprintf("((%s) and (%s))", filter, hostsFilter("dst", hosts))
} else {
filter = fmt.Sprintf("(%s)", filter)
}

if listenAll(l.host) || isDevice(l.host, ifi) {
return "(" + filter + ")"
if l.trackResponse {
responseFilter := portsFilter(l.Transport, "src", l.port)

if len(hosts) != 0 {
responseFilter = fmt.Sprintf("((%s) and (%s))", responseFilter, hostsFilter("src", hosts))
} else {
responseFilter = fmt.Sprintf("(%s)", responseFilter)
}

filter = fmt.Sprintf("%s or %s", filter, responseFilter)
}
filter = fmt.Sprintf("(host %s and (%s))", l.host, filter)

log.Println("BPF filter: " + filter)
return
}

Expand Down Expand Up @@ -259,13 +270,7 @@ func (l *Listener) PcapHandle(ifi net.Interface) (handle *pcap.Handle, err error
if err != nil {
return nil, fmt.Errorf("PCAP Activate device error: %q, interface: %q", err, ifi.Name)
}
if l.BPFFilter != "" {
if l.BPFFilter[0] != '(' || l.BPFFilter[len(l.BPFFilter)-1] != ')' {
l.BPFFilter = "(" + l.BPFFilter + ")"
}
} else {
l.BPFFilter = l.Filter(ifi)
}
l.BPFFilter = l.Filter(ifi)
fmt.Println("Interface:", ifi.Name, ". BPF Filter:", l.BPFFilter)
err = handle.SetBPFFilter(l.BPFFilter)
if err != nil {
Expand All @@ -284,13 +289,7 @@ func (l *Listener) SocketHandle(ifi net.Interface) (handle Socket, err error) {
if err = handle.SetPromiscuous(l.Promiscuous || l.Monitor); err != nil {
return nil, fmt.Errorf("promiscuous mode error: %q, interface: %q", err, ifi.Name)
}
if l.BPFFilter != "" {
if l.BPFFilter[0] != '(' || l.BPFFilter[len(l.BPFFilter)-1] != ')' {
l.BPFFilter = "(" + l.BPFFilter + ")"
}
} else {
l.BPFFilter = l.Filter(ifi)
}
l.BPFFilter = l.Filter(ifi)
fmt.Println("BPF Filter: ", l.BPFFilter)
if err = handle.SetBPFFilter(l.BPFFilter); err != nil {
handle.Close()
Expand Down Expand Up @@ -416,16 +415,12 @@ func (l *Listener) activatePcapFile() (err error) {
if handle, e = pcap.OpenOffline(l.host); e != nil {
return fmt.Errorf("open pcap file error: %q", e)
}
if l.BPFFilter != "" {
if l.BPFFilter[0] != '(' || l.BPFFilter[len(l.BPFFilter)-1] != ')' {
l.BPFFilter = "(" + l.BPFFilter + ")"
}
} else {
addr := l.host
l.host = ""
l.BPFFilter = l.Filter(net.Interface{})
l.host = addr
}

tmp := l.host
l.host = ""
l.BPFFilter = l.Filter(net.Interface{})
l.host = tmp

if e = handle.SetBPFFilter(l.BPFFilter); e != nil {
handle.Close()
return fmt.Errorf("BPF filter error: %q, filter: %s", e, l.BPFFilter)
Expand Down Expand Up @@ -481,6 +476,18 @@ func isDevice(addr string, ifi net.Interface) bool {
return addr == ifi.Name || addr == fmt.Sprintf("%d", ifi.Index) || (addr != "" && addr == ifi.HardwareAddr.String())
}

func interfaceAddresses(ifi net.Interface) []string {
var hosts []string
if addrs, err := ifi.Addrs(); err == nil {
for _, addr := range addrs {
if ip := addr.(*net.IPNet).IP.To16(); ip != nil {
hosts = append(hosts, ip.String())
}
}
}
return hosts
}

func listenAll(addr string) bool {
switch addr {
case "", "0.0.0.0", "[::]", "::":
Expand All @@ -489,6 +496,23 @@ func listenAll(addr string) bool {
return false
}

func portsFilter(transport string, direction string, port uint16) string {
if port == 0 {
return fmt.Sprintf("%s %s portrange 0-%d", transport, direction, 1<<16-1)
}

return fmt.Sprintf("%s %s port %d", transport, direction, port)
}

func hostsFilter(direction string, hosts []string) string {
var hostsFilters []string
for _, host := range hosts {
hostsFilters = append(hostsFilters, fmt.Sprintf("%s host %s", direction, host))
}

return strings.Join(hostsFilters, " or ")
}

func pcapLinkTypeLength(lType int) (int, bool) {
switch layers.LinkType(lType) {
case layers.LinkTypeEthernet:
Expand Down
9 changes: 7 additions & 2 deletions gor.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ var (
memprofile = flag.String("memprofile", "", "write memory profile to this file")
)

func loggingMiddleware(next http.Handler) http.Handler {
func loggingMiddleware(addr string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/loop" {
_, err := http.Get("http://" + addr)
log.Println(err)
}

rb, _ := httputil.DumpRequest(r, false)
log.Println(string(rb))
next.ServeHTTP(w, r)
Expand All @@ -45,7 +50,7 @@ func main() {

Debug(0, "Started example file server for current directory on address ", args[1])

log.Fatal(http.ListenAndServe(args[1], loggingMiddleware(http.FileServer(http.Dir(dir)))))
log.Fatal(http.ListenAndServe(args[1], loggingMiddleware(args[1], http.FileServer(http.Dir(dir)))))
} else {
flag.Parse()
checkSettings()
Expand Down

0 comments on commit 763ad9b

Please sign in to comment.