mirror of
https://github.com/buger/goreplay.git
synced 2024-04-21 12:32:02 +00:00
more exact bpf filter for only incoming traffic
This commit is contained in:
+52
-12
@@ -9,6 +9,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
filter = fmt.Sprintf("%s dst %s", l.Transport, port)
|
||||
if l.trackResponse {
|
||||
filter = fmt.Sprintf("%s %s", l.Transport, port)
|
||||
}
|
||||
|
||||
hosts := []string{l.host}
|
||||
if listenAll(l.host) || isDevice(l.host, ifi) {
|
||||
return "(" + filter + ")"
|
||||
hosts = interfaceAddresses(ifi)
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
|
||||
@@ -481,6 +492,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", "[::]", "::":
|
||||
@@ -489,6 +512,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:
|
||||
|
||||
Reference in New Issue
Block a user