diff --git a/README.md b/README.md index a735d19..d5cc607 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,9 @@ ndntdump emits two output files. The **packets** file is a [pcapng](https://datatracker.ietf.org/doc/draft-ietf-opsawg-pcapng/) file. It contains Ethernet packets that carry NDN traffic. -IP anonymization has been performed on these packets. +Address anonymization has been performed on these packets. When feasible, NDN packet payload, including Interest ApplicationParameters and Data Content, is zeroized, so that the output can be compressed effectively. +Payload blanking may be disabled with `--keep-payload` flag. The **records** file is a [Newline delimited JSON (NDJSON)](https://github.com/ndjson/ndjson-spec) file. Each line in this file is a JSON object that describes a NDN packet, either layer 2 or layer 3. @@ -71,6 +72,7 @@ This may be used with [logrotate](https://man7.org/linux/man-pages/man8/logrotat To ensure privacy compliance, ndntdump anonymizes IP and MAC addresses before output files are written. 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, which is consistent in each run, so that the same original address yields the same anonymized address. +Notice that this is a very simple and limited anonymization procedure, and we will incorporate better anonymization techniques in the future. For WebSocket traffic, HTTP request header `X-Forwarded-For` may contain full client address. This address is anonymized by changing the lower bits to zeros. diff --git a/cmd/ndntdump/main.go b/cmd/ndntdump/main.go index cb941dc..358b1eb 100644 --- a/cmd/ndntdump/main.go +++ b/cmd/ndntdump/main.go @@ -69,6 +69,10 @@ var app = &cli.App{ Name: "keep-mac", Usage: "don't anonymize MAC addresses", }, + &cli.BoolFlag{ + Name: "keep-payload", + Usage: "don't zeroize payload", + }, }, Action: func(c *cli.Context) (e error) { if input, e = pcapinput.Open(c.String("ifname"), c.String("input"), c.String("local")); e != nil { @@ -82,6 +86,7 @@ var app = &cli.App{ TCPPort: c.Int("tcp-port"), WebSocketPort: c.Int("wss-port"), Anonymizer: ndntdump.NewAnonymizer(keepIPs, c.Bool("keep-mac")), + KeepPayload: c.Bool("keep-payload"), }) if output, e = fileoutput.Open(c.String("json"), c.String("pcapng")); e != nil { diff --git a/reader.go b/reader.go index 2619015..f3668cc 100644 --- a/reader.go +++ b/reader.go @@ -46,11 +46,12 @@ func saveFlowPorts[P ~uint8, N ~uint16](flow []byte, dir Direction, proto P, src // Reader reads NDN packets from ZeroCopyPacketDataSource. type Reader struct { - src gopacket.ZeroCopyPacketDataSource - isLocal func(net.HardwareAddr) bool - tcpPort layers.TCPPort - wssPort layers.TCPPort - anon *Anonymizer + src gopacket.ZeroCopyPacketDataSource + isLocal func(net.HardwareAddr) bool + tcpPort layers.TCPPort + wssPort layers.TCPPort + anon *Anonymizer + zeroizePayload bool dlp *gopacket.DecodingLayerParser dlpTLV *gopacket.DecodingLayerParser @@ -186,15 +187,21 @@ func (r *Reader) readPacket(rec *Record) bool { case pkt.Interest != nil: pktType = PktTypeInterest rec.SaveInterest(*pkt.Interest, an.NackNone) - zeroizeInterestPayload(pkt.Interest) + if r.zeroizePayload { + zeroizeInterestPayload(pkt.Interest) + } case pkt.Data != nil: pktType = PktTypeData rec.SaveData(*pkt.Data) - zeroizeDataPayload(pkt.Data) + if r.zeroizePayload { + zeroizeDataPayload(pkt.Data) + } case pkt.Nack != nil: pktType = PktTypeNack rec.SaveInterest(pkt.Nack.Interest, pkt.Nack.Reason) - zeroizeInterestPayload(&pkt.Nack.Interest) + if r.zeroizePayload { + zeroizeInterestPayload(&pkt.Nack.Interest) + } default: return false } @@ -250,11 +257,12 @@ func (Reader) readFragment(lpl3 ndn.LpL3, frag ndn.LpFragment, rec *Record) { // NewReader creates Reader. func NewReader(src gopacket.ZeroCopyPacketDataSource, opts ReaderOptions) (r *Reader) { r = &Reader{ - src: src, - isLocal: opts.IsLocal, - tcpPort: layers.TCPPort(opts.TCPPort), - wssPort: layers.TCPPort(opts.WebSocketPort), - anon: opts.Anonymizer, + src: src, + isLocal: opts.IsLocal, + tcpPort: layers.TCPPort(opts.TCPPort), + wssPort: layers.TCPPort(opts.WebSocketPort), + anon: opts.Anonymizer, + zeroizePayload: !opts.KeepPayload, } if r.wssPort == 0 { r.wssPort = 9696 @@ -273,6 +281,7 @@ type ReaderOptions struct { TCPPort int WebSocketPort int Anonymizer *Anonymizer + KeepPayload bool } type incompleteTLV struct {