Skip to content

Commit

Permalink
Merge pull request #19 from yuuki/public_private_filter
Browse files Browse the repository at this point in the history
--filter option
  • Loading branch information
yuuki authored Aug 20, 2019
2 parents 09438c7 + 37565ac commit 9bcdc52
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 3 deletions.
19 changes: 16 additions & 3 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ func (c *CLI) Run(args []string) int {
numeric bool
processes bool
json bool
ver bool
credits bool
debug bool
filter string

ver bool
credits bool
debug bool
)
flags := flag.NewFlagSet(name, flag.ContinueOnError)
flags.SetOutput(c.errStream)
Expand All @@ -72,6 +74,8 @@ func (c *CLI) Run(args []string) int {
flags.BoolVar(&processes, "processes", false, "")
flags.BoolVar(&numeric, "", false, "")
flags.BoolVar(&json, "json", false, "")
flags.StringVar(&filter, "f", tcpflow.FilterAll, "")
flags.StringVar(&filter, "filter", tcpflow.FilterAll, "")
flags.BoolVar(&ver, "version", false, "")
flags.BoolVar(&credits, "credits", false, "")
flags.BoolVar(&debug, "debug", false, "")
Expand All @@ -91,8 +95,16 @@ func (c *CLI) Run(args []string) int {
return exitCodeOK
}

if !(filter == tcpflow.FilterAll ||
filter == tcpflow.FilterPublic ||
filter == tcpflow.FilterPrivate) {
fmt.Fprint(c.errStream, helpText)
return exitCodeErr
}

flows, err := tcpflow.GetHostFlows(&tcpflow.GetHostFlowsOption{
Processes: processes,
Filter: filter,
})
if err != nil {
if dlog.Debug {
Expand Down Expand Up @@ -156,6 +168,7 @@ Options:
--numeric, -n show numerical addresses instead of trying to determine symbolic host names.
--processes, -p show process using socket
--json print results as json format
--filter, -f filter results by "all", "public" or "private" (default: "all")
--version, -v print version
--help, -h print help
--credits print CREDITS
Expand Down
33 changes: 33 additions & 0 deletions netutil/netutil.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package netutil

import (
"fmt"
"net"
"strings"

Expand All @@ -18,6 +19,25 @@ type UserEnt struct {
pgrp int // process group id
}

var privateIPBlocks []*net.IPNet

func init() {
for _, cidr := range []string{
"10.0.0.0/8", // RFC1918
"172.16.0.0/12", // RFC1918
"192.168.0.0/16", // RFC1918
"::1/128", // IPv6 loopback
"fe80::/10", // IPv6 link-local
"fc00::/7", // IPv6 unique local addr
} {
_, block, err := net.ParseCIDR(cidr)
if err != nil {
panic(fmt.Errorf("parse error on %q: %v", cidr, err))
}
privateIPBlocks = append(privateIPBlocks, block)
}
}

// Inode returns inode.
func (u *UserEnt) Inode() uint32 {
return u.inode
Expand Down Expand Up @@ -81,3 +101,16 @@ func LocalIPAddrs() ([]string, error) {
}
return addrStrings, nil
}

// IsPrivateIP returns whether 'ip' is in private network space.
func IsPrivateIP(ip net.IP) bool {
if ip.IsLoopback() {
return true
}
for _, block := range privateIPBlocks {
if block.Contains(ip) {
return true
}
}
return false
}
19 changes: 19 additions & 0 deletions netutil/netutil_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package netutil

import (
"net"
"testing"
)

Expand All @@ -23,3 +24,21 @@ func TestLocalListeningPorts(t *testing.T) {
t.Error("localIPAddrs() should not be len == 0")
}
}

func TestIsPrivateIP(t *testing.T) {
tests := []struct {
in string
out bool
}{
{"192.168.10.111", true},
{"172.16.10.111", true},
{"10.1.10.111", true},
{"192.0.2.111", false},
}
for _, tt := range tests {
in := net.ParseIP(tt.in)
if IsPrivateIP(in) != tt.out {
t.Errorf("IsPrivateIP(%v) got: %v", in, tt.out)
}
}
}
5 changes: 5 additions & 0 deletions tcpflow/tcpflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const (
FlowActive
// FlowPassive are 'passive open'
FlowPassive

FilterAll = "all"
FilterPublic = "public"
FilterPrivate = "private"
)

// String returns string representation.
Expand Down Expand Up @@ -135,4 +139,5 @@ func contains(strs []string, s string) bool {
// GetHostFlowsOption represens an option for func GetHostFlows().
type GetHostFlowsOption struct {
Processes bool
Filter string
}
12 changes: 12 additions & 0 deletions tcpflow/tcpflow_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ func GetHostFlowsByNetlink(opt *GetHostFlowsOption) (HostFlows, error) {
continue
}

switch opt.Filter {
case FilterAll:
case FilterPublic:
if netutil.IsPrivateIP(conn.DstIP()) {
continue
}
case FilterPrivate:
if !netutil.IsPrivateIP(conn.DstIP()) {
continue
}
}

var ent *netutil.UserEnt
// inode 0 means that it provides no process information
if userEnts != nil && conn.Inode != 0 {
Expand Down
14 changes: 14 additions & 0 deletions tcpflow/tcpflow_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package tcpflow

import (
"fmt"
"net"

gnet "github.com/shirou/gopsutil/net"
"github.com/yuuki/lstf/netutil"
Expand All @@ -26,6 +27,19 @@ func GetHostFlows(opt *GetHostFlowsOption) (HostFlows, error) {
if conn.Status == "LISTEN" {
continue
}

switch opt.Filter {
case FilterAll:
case FilterPublic:
if netutil.IsPrivateIP(net.ParseIP(conn.Raddr.IP)) {
continue
}
case FilterPrivate:
if !netutil.IsPrivateIP(net.ParseIP(conn.Raddr.IP)) {
continue
}
}

lport := fmt.Sprintf("%d", conn.Laddr.Port)
rport := fmt.Sprintf("%d", conn.Raddr.Port)
if contains(ports, lport) {
Expand Down

0 comments on commit 9bcdc52

Please sign in to comment.