capture list of ports (#935)

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
This commit is contained in:
Dima Golomozy
2021-06-10 14:49:17 +03:00
committed by GitHub
parent 58ff8865df
commit 642bb35124
2 changed files with 32 additions and 21 deletions
+12 -8
View File
@@ -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)
@@ -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
@@ -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))
@@ -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))
@@ -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 {
+20 -13
View File
@@ -6,6 +6,7 @@ import (
"log"
"net"
"strconv"
"strings"
"sync"
"time"
@@ -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
@@ -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)
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))
}
}
if err != nil {
log.Fatalf("parsing port error: %v", err)
}
i.host = host
i.port = uint16(port)
i.ports = ports
i.listen(address)
@@ -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)
}
@@ -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