Repository: metron Updated Branches: refs/heads/feature/METRON-1554-pcap-query-panel 076a6a197 -> 14e80b3c2
METRON-1739 UDP packets are not handled (merrimanr) closes apache/metron#1168 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/14e80b3c Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/14e80b3c Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/14e80b3c Branch: refs/heads/feature/METRON-1554-pcap-query-panel Commit: 14e80b3c229ea2e5a8d615c87d822d4b44d8ec98 Parents: 076a6a1 Author: merrimanr <merrim...@gmail.com> Authored: Fri Aug 17 08:47:32 2018 -0500 Committer: rmerriman <merrim...@gmail.com> Committed: Fri Aug 17 08:47:32 2018 -0500 ---------------------------------------------------------------------- .../src/app/pcap/model/pdml.mock.ts | 31 ++++++++ .../pcap-packet-line.component.spec.ts | 53 ++++++++++++-- .../pcap-packet-line.component.ts | 15 ++-- .../java/org/apache/metron/pcap/PcapHelper.java | 18 ++++- .../org/apache/metron/pcap/PcapHelperTest.java | 76 ++++++++++++++++++++ 5 files changed, 180 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts b/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts index 6316b92..2520da1 100644 --- a/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts +++ b/metron-interface/metron-alerts/src/app/pcap/model/pdml.mock.ts @@ -60,3 +60,34 @@ export const fakePacket = { } as PdmlProto ] } as PdmlPacket; + +export const fakeUdpPacket = { + "name": '', + "expanded": false, + "protos": [ + { + "name": "geninfo", + "showname": "", + "fields": [ + { "name": "timestamp", "pos": "0", "showname": "Captured Time", "size": "342", "value": "1534414874.932794000", "show": "Aug 16, 2018 10:21:14.932794000 UTC", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField + ] + } as PdmlProto, + { + "name": "ip", + "showname": "", + "fields": [ + { "name": "ip.proto", "pos": "23", "showname": "Protocol: UDP (17)", "size": "1", "value": "11", "show": "17", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField, + { "name": "ip.src", "pos": "26", "showname": "Source: 0.0.0.0 (0.0.0.0)", "size": "4", "value": "00000000", "show": "0.0.0.0", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField, + { "name": "ip.dst", "pos": "30", "showname": "Destination: 255.255.255.255 (255.255.255.255)", "size": "4", "value": "ffffffff", "show": "255.255.255.255", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField + ] + } as PdmlProto, + { + "name": "udp", + "showname": "User Datagram Protocol, Src Port: bootpc (68), Dst Port: bootps (67)", + "fields": [ + { "name": "udp.srcport", "pos": "34", "showname": "Source port: bootpc (68)", "size": "2", "value": "0044", "show": "68", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField, + { "name": "udp.dstport", "pos": "36", "showname": "Destination port: bootps (67)", "size": "2", "value": "0043", "show": "67", "unmaskedvalue": null, "hide": null, "fields": null, "protos": null } as PdmlField + ], + } as PdmlProto + ] +} as PdmlPacket; http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts index d01c0cb..00f081f 100644 --- a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts +++ b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts @@ -17,6 +17,7 @@ */ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { fakePacket } from '../model/pdml.mock'; +import { fakeUdpPacket } from '../model/pdml.mock'; import { PcapPacketLineComponent } from './pcap-packet-line.component'; @@ -34,8 +35,6 @@ describe('PcapPacketLineComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(PcapPacketLineComponent); component = fixture.componentInstance; - component.packet = fakePacket; - fixture.detectChanges(); }); it('should be created', () => { @@ -43,6 +42,8 @@ describe('PcapPacketLineComponent', () => { }); it('should extract timestamp fields', () => { + component.packet = fakePacket; + fixture.detectChanges(); expect(component.ip.timestamp).toEqual({ "name": "timestamp", "pos": "0", @@ -59,6 +60,8 @@ describe('PcapPacketLineComponent', () => { }); it('should extract ipSrcAddr fields', () => { + component.packet = fakePacket; + fixture.detectChanges(); expect(component.ip.ipSrcAddr).toEqual({ "name": "ip.src", "pos": "26", @@ -74,6 +77,8 @@ describe('PcapPacketLineComponent', () => { }); it('should extract ipSrcPort fields', () => { + component.packet = fakePacket; + fixture.detectChanges(); expect(component.ip.ipSrcPort).toEqual({ "name": "tcp.srcport", "pos": "34", @@ -88,7 +93,9 @@ describe('PcapPacketLineComponent', () => { }); }); - it('should extract ipDestAddr fields', () => { + it('should extract TCP ipDestAddr fields', () => { + component.packet = fakePacket; + fixture.detectChanges(); expect(component.ip.ipDestAddr).toEqual({ "name": "ip.dst", "pos": "30", @@ -103,7 +110,9 @@ describe('PcapPacketLineComponent', () => { }); }); - it('should extract ipDestPort fields', () => { + it('should extract TCP ipDestPort fields', () => { + component.packet = fakePacket; + fixture.detectChanges(); expect(component.ip.ipDestPort).toEqual({ "name": "tcp.dstport", "pos": "36", @@ -119,6 +128,8 @@ describe('PcapPacketLineComponent', () => { }); it('should extract protocol fields', () => { + component.packet = fakePacket; + fixture.detectChanges(); expect(component.ip.protocol).toEqual({ "name": "ip.proto", "pos": "23", @@ -132,4 +143,38 @@ describe('PcapPacketLineComponent', () => { "protos": null }); }); + + it('should extract UDP ipSrcPort fields', () => { + component.packet = fakeUdpPacket; + fixture.detectChanges(); + expect(component.ip.ipSrcPort).toEqual({ + "name": "udp.srcport", + "pos": "34", + "showname": "Source port: bootpc (68)", + "size": "2", + "value": "0044", + "show": "68", + "unmaskedvalue": null, + "hide": null, + "fields": null, + "protos": null + }); + }); + + it('should extract UDP ipDestPort fields', () => { + component.packet = fakeUdpPacket; + fixture.detectChanges(); + expect(component.ip.ipDestPort).toEqual({ + "name": "udp.dstport", + "pos": "36", + "showname": "Destination port: bootps (67)", + "size": "2", + "value": "0043", + "show": "67", + "unmaskedvalue": null, + "hide": null, + "fields": null, + "protos": null + }); + }); }); http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts index bb160a0..b1546af 100644 --- a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts +++ b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts @@ -25,28 +25,29 @@ import { PdmlPacket, PdmlProto, PdmlField } from '../model/pdml' }) export class PcapPacketLineComponent implements OnInit { - @Input() packet: PdmlPacket + @Input() packet: PdmlPacket; ip: { timestamp: PdmlField, ipSrcAddr: PdmlField, ipSrcPort: PdmlField, ipDestAddr: PdmlField, ipDestPort: PdmlField, protocol: PdmlField - } + }; constructor() { } ngOnInit() { - const genProto: PdmlProto = this.packet.protos.filter(p => p.name == "geninfo")[0] - const ipProto: PdmlProto = this.packet.protos.filter(p => p.name == "ip")[0] - const tcpProto: PdmlProto = this.packet.protos.filter(p => p.name == "tcp")[0] + const genProto: PdmlProto = this.packet.protos.filter(p => p.name == "geninfo")[0]; + const ipProto: PdmlProto = this.packet.protos.filter(p => p.name == "ip")[0]; + const tcpProto: PdmlProto = this.packet.protos.filter(p => p.name == "tcp")[0]; + const udpProto: PdmlProto = this.packet.protos.filter(p => p.name == "udp")[0]; this.ip = { timestamp: PdmlProto.findField(genProto,'timestamp'), ipSrcAddr: PdmlProto.findField(ipProto,'ip.src'), - ipSrcPort: PdmlProto.findField(tcpProto,'tcp.srcport'), + ipSrcPort: tcpProto ? PdmlProto.findField(tcpProto,'tcp.srcport') : PdmlProto.findField(udpProto,'udp.srcport'), ipDestAddr: PdmlProto.findField(ipProto,'ip.dst'), - ipDestPort: PdmlProto.findField(tcpProto,'tcp.dstport'), + ipDestPort: tcpProto ? PdmlProto.findField(tcpProto,'tcp.dstport') : PdmlProto.findField(udpProto,'udp.dstport'), protocol: PdmlProto.findField(ipProto,'ip.proto') }; } http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java b/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java index 1ebdf7c..aa3eafe 100644 --- a/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java +++ b/metron-platform/metron-pcap/src/main/java/org/apache/metron/pcap/PcapHelper.java @@ -257,9 +257,23 @@ public class PcapHelper { if(pi.getTcpPacket().getDestination() != null ) { ret.put(org.apache.metron.common.Constants.Fields.DST_PORT.getName(), pi.getTcpPacket().getDestination().getPort()); } - if(pi.getIpv4Packet() != null) { - ret.put(org.apache.metron.common.Constants.Fields.PROTOCOL.getName(), pi.getIpv4Packet().getProtocol()); + } + if(pi.getUdpPacket() != null) { + if (pi.getUdpPacket().getSource() != null) { + if(pi.getUdpPacket().getSource().getAddress() != null) { + ret.put(org.apache.metron.common.Constants.Fields.SRC_ADDR.getName(), pi.getUdpPacket().getSource().getAddress().getHostAddress()); + } + ret.put(org.apache.metron.common.Constants.Fields.SRC_PORT.getName(), pi.getUdpPacket().getSource().getPort()); } + if (pi.getUdpPacket().getDestination() != null) { + if(pi.getUdpPacket().getDestination().getAddress() != null ) { + ret.put(org.apache.metron.common.Constants.Fields.DST_ADDR.getName(), pi.getUdpPacket().getDestination().getAddress().getHostAddress()); + } + ret.put(org.apache.metron.common.Constants.Fields.DST_PORT.getName(), pi.getUdpPacket().getDestination().getPort()); + } + } + if(pi.getIpv4Packet() != null) { + ret.put(org.apache.metron.common.Constants.Fields.PROTOCOL.getName(), pi.getIpv4Packet().getProtocol()); } return ret; } http://git-wip-us.apache.org/repos/asf/metron/blob/14e80b3c/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java b/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java index 5d2bee0..73f359d 100644 --- a/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java +++ b/metron-platform/metron-pcap/src/test/java/org/apache/metron/pcap/PcapHelperTest.java @@ -27,11 +27,22 @@ import org.apache.hadoop.io.SequenceFile; import org.apache.metron.spout.pcap.Endianness; import org.junit.Assert; import org.junit.Test; +import org.krakenapps.pcap.decoder.ip.Ipv4Packet; +import org.krakenapps.pcap.decoder.tcp.TcpPacket; +import org.krakenapps.pcap.decoder.udp.UdpPacket; import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; + +import static org.apache.metron.common.Constants.Fields; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class PcapHelperTest { public static List<byte[]> readSamplePackets(String pcapLoc) throws IOException { @@ -75,4 +86,69 @@ public class PcapHelperTest { } } } + + @Test + public void packetToFieldsShouldProperlyParserTcpPackets() throws Exception { + PacketInfo packetInfo = mock(PacketInfo.class); + when(packetInfo.getPacketBytes()).thenReturn("packet bytes".getBytes(StandardCharsets.UTF_8)); + TcpPacket tcpPacket = mock(TcpPacket.class); + // Tcp source address and port + InetAddress tcpSourceInetAddress = mock(InetAddress.class); + when(tcpSourceInetAddress.getHostAddress()).thenReturn("tcp source address"); + when(tcpPacket.getSourceAddress()).thenReturn(tcpSourceInetAddress); + InetSocketAddress tcpSourceInetSocketAddress = new InetSocketAddress(22); + when(tcpPacket.getSource()).thenReturn(tcpSourceInetSocketAddress); + // Tcp destination address and port + InetAddress tcpDestinationInetAddress = mock(InetAddress.class); + when(tcpDestinationInetAddress.getHostAddress()).thenReturn("tcp destination address"); + when(tcpPacket.getDestinationAddress()).thenReturn(tcpDestinationInetAddress); + InetSocketAddress tcpDestinationInetSocketAddress = new InetSocketAddress(55791); + when(tcpPacket.getDestination()).thenReturn(tcpDestinationInetSocketAddress); + when(packetInfo.getTcpPacket()).thenReturn(tcpPacket); + + Ipv4Packet ipv4Packet = mock(Ipv4Packet.class); + when(ipv4Packet.getProtocol()).thenReturn(6); + when(packetInfo.getIpv4Packet()).thenReturn(ipv4Packet); + + Map<String, Object> actualFields = PcapHelper.packetToFields(packetInfo); + Assert.assertArrayEquals("packet bytes".getBytes(StandardCharsets.UTF_8), + (byte[]) actualFields.get(PcapHelper.PacketFields.PACKET_DATA.getName())); + Assert.assertEquals("tcp source address", actualFields.get(Fields.SRC_ADDR.getName())); + Assert.assertEquals(22, actualFields.get(Fields.SRC_PORT.getName())); + Assert.assertEquals("tcp destination address", actualFields.get(Fields.DST_ADDR.getName())); + Assert.assertEquals(55791, actualFields.get(Fields.DST_PORT.getName())); + Assert.assertEquals(6, actualFields.get(Fields.PROTOCOL.getName())); + } + + @Test + public void packetToFieldsShouldProperlyParserUdpPackets() throws Exception { + PacketInfo packetInfo = mock(PacketInfo.class); + when(packetInfo.getPacketBytes()).thenReturn("packet bytes".getBytes(StandardCharsets.UTF_8)); + + UdpPacket udpPacket = mock(UdpPacket.class); + // Udp source address and port + InetAddress udpSourceInetAddress = mock(InetAddress.class); + when(udpSourceInetAddress.getHostAddress()).thenReturn("udp source address"); + InetSocketAddress udpSourceInetSocketAddress = new InetSocketAddress(udpSourceInetAddress, 68); + when(udpPacket.getSource()).thenReturn(udpSourceInetSocketAddress); + // Udp destination address and port + InetAddress udpDestinationInetAddress = mock(InetAddress.class); + when(udpDestinationInetAddress.getHostAddress()).thenReturn("udp destination address"); + InetSocketAddress udpDestinationInetSocketAddress = new InetSocketAddress(udpDestinationInetAddress, 67); + when(udpPacket.getDestination()).thenReturn(udpDestinationInetSocketAddress); + when(packetInfo.getUdpPacket()).thenReturn(udpPacket); + + Ipv4Packet ipv4Packet = mock(Ipv4Packet.class); + when(ipv4Packet.getProtocol()).thenReturn(17); + when(packetInfo.getIpv4Packet()).thenReturn(ipv4Packet); + + Map<String, Object> actualFields = PcapHelper.packetToFields(packetInfo); + Assert.assertArrayEquals("packet bytes".getBytes(StandardCharsets.UTF_8), + (byte[]) actualFields.get(PcapHelper.PacketFields.PACKET_DATA.getName())); + Assert.assertEquals("udp source address", actualFields.get(Fields.SRC_ADDR.getName())); + Assert.assertEquals(68, actualFields.get(Fields.SRC_PORT.getName())); + Assert.assertEquals("udp destination address", actualFields.get(Fields.DST_ADDR.getName())); + Assert.assertEquals(67, actualFields.get(Fields.DST_PORT.getName())); + Assert.assertEquals(17, actualFields.get(Fields.PROTOCOL.getName())); + } }