diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 98f4a5a..d5e8c27 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,3 +13,5 @@ jobs: with: go-version-file: go.mod - run: go build ./... + - run: go test ./... + - run: go vet ./... diff --git a/anonymizer.go b/anonymizer.go index c90adf5..6f10bc1 100644 --- a/anonymizer.go +++ b/anonymizer.go @@ -10,13 +10,16 @@ import ( "go4.org/netipx" ) +// AnonymizerSecretLen is the length of secret key inside Anonymizer. +const AnonymizerSecretLen = 14 + // Anonymizer anonymizes IP addresses and MAC addresses. // IPv4 address keeps its leading 24 bits; IPv6 address keeps its leading 48 bits; MAC address keeps its leading 24 bits. // Lower bits are XOR'ed with a random value. type Anonymizer struct { keepIPs *netipx.IPSet keepMAC bool - secret [14]byte + secret [AnonymizerSecretLen]byte } // AnonymizeIP anonymizes an IP address. @@ -41,12 +44,16 @@ func (anon *Anonymizer) AnonymizeMAC(mac net.HardwareAddr) { } // NewAnonymizer creates Anonymizer. -func NewAnonymizer(keepIPs *netipx.IPSet, keepMAC bool) (anon *Anonymizer) { +func NewAnonymizer(keepIPs *netipx.IPSet, keepMAC bool, secret *[AnonymizerSecretLen]byte) (anon *Anonymizer) { anon = &Anonymizer{ keepIPs: keepIPs, keepMAC: keepMAC, } - rand.Read(anon.secret[:]) + if secret == nil { + rand.Read(anon.secret[:]) + } else { + anon.secret = *secret + } return } diff --git a/anonymizer_test.go b/anonymizer_test.go new file mode 100644 index 0000000..389f65f --- /dev/null +++ b/anonymizer_test.go @@ -0,0 +1,57 @@ +package ndntdump_test + +import ( + "bytes" + "net" + "net/netip" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/usnistgov/ndntdump" + "go4.org/netipx" +) + +func TestAnonymizer(t *testing.T) { + assert, require := assert.New(t), require.New(t) + keepIPs, e := ndntdump.ParseIPSet([]string{ + "10.0.4.32/28", + "10.0.10.0/23", + "fc44:966b:ce32:f10a::/64", + }) + require.NoError(e) + var expectKeepIPsBuilder netipx.IPSetBuilder + expectKeepIPsBuilder.AddPrefix(netip.MustParsePrefix("10.0.4.0/24")) + expectKeepIPsBuilder.AddPrefix(netip.MustParsePrefix("10.0.10.0/23")) + expectKeepIPsBuilder.AddPrefix(netip.MustParsePrefix("fc44:966b:ce32::/48")) + expectKeepIPs, _ := expectKeepIPsBuilder.IPSet() + assert.True(keepIPs.Equal(expectKeepIPs)) + + secret := [ndntdump.AnonymizerSecretLen]byte(bytes.Repeat([]byte{0x01}, ndntdump.AnonymizerSecretLen)) + anon := ndntdump.NewAnonymizer(keepIPs, false, &secret) + + for _, ipPair := range [][2]string{ + {"10.0.4.2", "10.0.4.2"}, + {"10.0.5.2", "10.0.5.3"}, + {"10.0.11.2", "10.0.11.2"}, + {"10.0.12.2", "10.0.12.3"}, + {"fc44:966b:ce32:52c6:74cd:f818:963b:202b", "fc44:966b:ce32:52c6:74cd:f818:963b:202b"}, + {"fc9b:fd7b:5f42:47d0:78c0:fcb6:85c7:84a3", "fc9b:fd7b:5f42:46d1:79c1:fdb7:84c6:85a2"}, + } { + ip := net.ParseIP(ipPair[0]) + if ip4 := ip.To4(); ip4 != nil { + ip = ip4 + } + anon.AnonymizeIP(ip) + assert.Equal(ipPair[1], ip.String()) + } + + badIP := net.IP{0xF0, 0xF1, 0xF2, 0xF3, 0xF4} // neither IPv4 nor IPv6 + anon.AnonymizeIP(badIP) + assert.Equal(net.IP{0xF0, 0xF1, 0xF2, 0xF3, 0xF4}, badIP) // unchanged + + hwaddr, e := net.ParseMAC("02:bf:8f:44:91:da") + require.NoError(e) + anon.AnonymizeMAC(hwaddr) + assert.Equal("02:bf:8f:45:90:db", hwaddr.String()) +} diff --git a/cmd/ndntdump/main.go b/cmd/ndntdump/main.go index 358b1eb..859f06c 100644 --- a/cmd/ndntdump/main.go +++ b/cmd/ndntdump/main.go @@ -85,7 +85,7 @@ var app = &cli.App{ IsLocal: input.IsLocal, TCPPort: c.Int("tcp-port"), WebSocketPort: c.Int("wss-port"), - Anonymizer: ndntdump.NewAnonymizer(keepIPs, c.Bool("keep-mac")), + Anonymizer: ndntdump.NewAnonymizer(keepIPs, c.Bool("keep-mac"), nil), KeepPayload: c.Bool("keep-payload"), }) diff --git a/go.mod b/go.mod index f7170ae..f359496 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( github.com/google/gopacket v1.1.19 github.com/klauspost/compress v1.17.2 + github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.25.7 github.com/usnistgov/ndn-dpdk v0.0.0-20231012213844-da654608dfe8 github.com/zyedidia/generic v1.2.1 @@ -13,9 +14,12 @@ require ( require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 7849cee..1824a2d 100644 --- a/go.sum +++ b/go.sum @@ -44,5 +44,7 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=