Skip to content

Commit

Permalink
capture list of ports (#935)
Browse files Browse the repository at this point in the history
Co-authored-by: Leonid Bugaev <leonsbox@gmail.com>

Added a way to capture multiple ports at the same time, with a single listener. 
Ports should be separated by comma like this: --input-raw :80,8080,3000
  • Loading branch information
DimaGolomozy authored Jun 10, 2021
1 parent 58ff886 commit 642bb35
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 21 deletions.
20 changes: 12 additions & 8 deletions capture/capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type Listener struct {
Reading chan bool // this channel is closed when the listener has started reading packets
PcapOptions
Engine EngineType
port uint16 // src or/and dst port
ports []uint16 // src or/and dst ports
trackResponse bool

host string // pcap file name or interface (name, hardware addr, index or ip address)
Expand Down Expand Up @@ -99,15 +99,15 @@ func (eng *EngineType) String() (e string) {
// NewListener creates and initialize a new Listener. if transport or/and engine are invalid/unsupported
// is "tcp" and "pcap", are assumed. l.Engine and l.Transport can help to get the values used.
// if there is an error it will be associated with getting network interfaces
func NewListener(host string, port uint16, transport string, engine EngineType, trackResponse bool) (l *Listener, err error) {
func NewListener(host string, ports []uint16, transport string, engine EngineType, trackResponse bool) (l *Listener, err error) {
l = &Listener{}

l.host = host
if l.host == "localhost" {
l.host = "127.0.0.1"
}

l.port = port

l.Transport = "tcp"
if transport != "" {
l.Transport = transport
Expand Down Expand Up @@ -181,7 +181,7 @@ func (l *Listener) Filter(ifi pcap.Interface) (filter string) {
hosts = interfaceAddresses(ifi)
}

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

if len(hosts) != 0 {
filter = fmt.Sprintf("((%s) and (%s))", filter, hostsFilter("dst", hosts))
Expand All @@ -190,7 +190,7 @@ func (l *Listener) Filter(ifi pcap.Interface) (filter string) {
}

if l.trackResponse {
responseFilter := portsFilter(l.Transport, "src", l.port)
responseFilter := portsFilter(l.Transport, "src", l.ports)

if len(hosts) != 0 {
responseFilter = fmt.Sprintf("((%s) and (%s))", responseFilter, hostsFilter("src", hosts))
Expand Down Expand Up @@ -501,12 +501,16 @@ func listenAll(addr string) bool {
return false
}

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

return fmt.Sprintf("%s %s port %d", transport, direction, port)
var filters []string
for _, port := range ports {
filters = append(filters, fmt.Sprintf("%s %s port %d", transport, direction, port))
}
return strings.Join(filters, " or ")
}

func hostsFilter(direction string, hosts []string) string {
Expand Down
33 changes: 20 additions & 13 deletions input_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"net"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -61,7 +62,7 @@ type RAWInputConfig struct {
Stats bool `json:"input-raw-stats"`
quit chan bool // Channel used only to indicate goroutine should shutdown
host string
port uint16
ports []uint16
}

// RAWInput used for intercepting traffic for given address
Expand All @@ -81,22 +82,28 @@ func NewRAWInput(address string, config RAWInputConfig) (i *RAWInput) {
i.RAWInputConfig = config
i.message = make(chan *tcp.Message, 10000)
i.quit = make(chan bool)
var host, _port string
var err error
var port int
host, _port, err = net.SplitHostPort(address)

host, _ports, err := net.SplitHostPort(address)
if err != nil {
log.Fatalf("input-raw: error while parsing address: %s", err)
}
if _port != "" {
port, err = strconv.Atoi(_port)
}

if err != nil {
log.Fatalf("parsing port error: %v", err)
var ports []uint16
if _ports != "" {
portsStr := strings.Split(_ports, ",")

for _, portStr := range portsStr {
port, err := strconv.Atoi(strings.TrimSpace(portStr))
if err != nil {
log.Fatalf("parsing port error: %v", err)
}
ports = append(ports, uint16(port))

}
}

i.host = host
i.port = uint16(port)
i.ports = ports

i.listen(address)

Expand Down Expand Up @@ -141,7 +148,7 @@ func (i *RAWInput) PluginRead() (*Message, error) {

func (i *RAWInput) listen(address string) {
var err error
i.listener, err = capture.NewListener(i.host, i.port, "", i.Engine, i.TrackResponse)
i.listener, err = capture.NewListener(i.host, i.ports, "", i.Engine, i.TrackResponse)
if err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -172,7 +179,7 @@ func (i *RAWInput) messageEmitter(m *tcp.Message) {
}

func (i *RAWInput) String() string {
return fmt.Sprintf("Intercepting traffic from: %s:%d", i.host, i.port)
return fmt.Sprintf("Intercepting traffic from: %s:%s", i.host, strings.Join(strings.Fields(fmt.Sprint(i.ports)), ","))
}

// GetStats returns the stats so far and reset the stats
Expand Down

0 comments on commit 642bb35

Please sign in to comment.