179 lines
6.2 KiB
C#
179 lines
6.2 KiB
C#
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using skyscraper5.Ietf.Rfc2460;
|
|
using skyscraper5.Ietf.Rfc768;
|
|
using skyscraper5.Ietf.Rfc971;
|
|
using skyscraper5.Skyscraper.Plugins;
|
|
using skyscraper8.Skyscraper.Net.VirtualNetworks;
|
|
using skyscraper8.Skyscraper.Scraper.Storage;
|
|
|
|
namespace skyscraper8.Skyscraper.Net;
|
|
|
|
[SkyscraperPlugin]
|
|
[StorageId(3)]
|
|
[StorageName("Packet Discarder")]
|
|
public class BlackholeIpTrafficHandler : IpTrafficHandler
|
|
{
|
|
public void Dispose()
|
|
{
|
|
// TODO release managed resources here
|
|
}
|
|
|
|
public void HandleIpPacket(VirtualNetworkIdentifier pid, byte[] payload)
|
|
{
|
|
if (payload == null || payload.Length == 0)
|
|
return;
|
|
|
|
int ipVersion = (payload[0] & 0xF0) >> 4;
|
|
bool isIpv4 = ipVersion == 4;
|
|
bool isUdp = false;
|
|
int udpOffset = -1;
|
|
byte proto;
|
|
IPAddress srcAddr;
|
|
IPAddress dstAddr;
|
|
if (isIpv4)
|
|
{
|
|
InternetHeader ipv4 = new InternetHeader(payload);
|
|
isUdp = ipv4.Protocol == 17;
|
|
udpOffset = ipv4.NextHeaderOffset;
|
|
srcAddr = ipv4.SourceAddress;
|
|
dstAddr = ipv4.DestinationAddress;
|
|
proto = ipv4.Protocol;
|
|
}
|
|
else
|
|
{
|
|
bool isIpv6 = ipVersion == 6;
|
|
if (isIpv6)
|
|
{
|
|
Ipv6Header ipv6 = new Ipv6Header(payload);
|
|
isUdp = ipv6.NextHeader == 17;
|
|
udpOffset = ipv6.HeaderEndOffset;
|
|
srcAddr = ipv6.SourceAddress;
|
|
dstAddr = ipv6.DestinationAddress;
|
|
proto = ipv6.NextHeader;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (isUdp)
|
|
{
|
|
UserDatagram userDatagram = new UserDatagram(new Span<byte>(payload).Slice(udpOffset).ToArray());
|
|
TrackUdpContent(srcAddr, dstAddr, userDatagram.SourcePort, userDatagram.DestinationPort, userDatagram.Payload);
|
|
}
|
|
|
|
TrackIpContent(srcAddr, dstAddr, proto, payload.Length - udpOffset);
|
|
|
|
}
|
|
|
|
private void TrackIpContent(IPAddress srcAddr, IPAddress dstAddr, byte proto, int payloadLength)
|
|
{
|
|
if (_ipContents == null)
|
|
_ipContents = new Dictionary<Tuple<IPAddress, IPAddress, byte>, TrafficTracking>();
|
|
|
|
Tuple<IPAddress,IPAddress,byte> coordinate = new Tuple<IPAddress, IPAddress, byte>(srcAddr, dstAddr, proto);
|
|
if (!_ipContents.ContainsKey(coordinate))
|
|
{
|
|
TrafficTracking tracking = new TrafficTracking();
|
|
tracking.Count(payloadLength);
|
|
_ipContents.Add(coordinate, tracking);
|
|
}
|
|
else
|
|
{
|
|
_ipContents[coordinate].Count(payloadLength);
|
|
}
|
|
}
|
|
|
|
public void HandleLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination,
|
|
ushort etherType, byte[] contents)
|
|
{
|
|
Tuple<PhysicalAddress, ushort, byte, byte> coordinate = new Tuple<PhysicalAddress, ushort, byte, byte>(destination, etherType, contents[0], contents[1]);
|
|
|
|
if (_llcContents == null)
|
|
_llcContents = new Dictionary<Tuple<PhysicalAddress, ushort, byte, byte>, TrafficTracking>();
|
|
|
|
if (!_llcContents.ContainsKey(coordinate))
|
|
{
|
|
TrafficTracking tracking = new TrafficTracking();
|
|
tracking.Count(contents.Length - 2);
|
|
_llcContents.Add(coordinate, tracking);
|
|
}
|
|
else
|
|
{
|
|
_llcContents[coordinate].Count(contents.Length - 2);
|
|
}
|
|
}
|
|
|
|
private void TrackUdpContent(IPAddress src, IPAddress dst, ushort srcPort, ushort dstPort, byte[] contents)
|
|
{
|
|
if (_udpContents == null)
|
|
{
|
|
_udpContents = new Dictionary<Tuple<IPAddress, IPAddress, ushort, ushort>, TrafficTracking>();
|
|
}
|
|
|
|
Tuple<IPAddress,IPAddress,ushort,ushort> coordinate = new Tuple<IPAddress, IPAddress, ushort, ushort>(src, dst, srcPort, dstPort);
|
|
if (!_udpContents.ContainsKey(coordinate))
|
|
{
|
|
TrafficTracking tracking = new TrafficTracking();
|
|
tracking.Count(contents.Length);
|
|
_udpContents.Add(coordinate, tracking);
|
|
}
|
|
else
|
|
{
|
|
_udpContents[coordinate].Count(contents.Length);
|
|
}
|
|
}
|
|
|
|
|
|
private Dictionary<Tuple<PhysicalAddress, ushort, byte, byte>, TrafficTracking> _llcContents;
|
|
private Dictionary<Tuple<IPAddress, IPAddress, byte>, TrafficTracking> _ipContents;
|
|
private Dictionary<Tuple<IPAddress, IPAddress, ushort, ushort>, TrafficTracking> _udpContents;
|
|
|
|
public class TrafficTracking
|
|
{
|
|
public void Count(int length)
|
|
{
|
|
NumPackets++;
|
|
NumBytes += length;
|
|
}
|
|
|
|
public int NumPackets { get; set; }
|
|
|
|
public int NumBytes { get; set; }
|
|
}
|
|
|
|
public bool? TestForUdpTraffic(string srcIp, string dstIp, int stcPort, int dstPort)
|
|
{
|
|
IPAddress ipL = IPAddress.Parse(srcIp);
|
|
IPAddress ipR = IPAddress.Parse(dstIp);
|
|
ushort portL = Convert.ToUInt16(stcPort);
|
|
ushort portR = Convert.ToUInt16(dstPort);
|
|
return TestForUdpTraffic(ipL, ipR, portL, portR);
|
|
}
|
|
|
|
private bool? TestForUdpTraffic(IPAddress srcIp, IPAddress dstIp, ushort stcPort, ushort dstPort)
|
|
{
|
|
Tuple<IPAddress, IPAddress, ushort, ushort> coordinate = new Tuple<IPAddress, IPAddress, ushort, ushort>(srcIp, dstIp, stcPort, dstPort);
|
|
return _udpContents.ContainsKey(coordinate);
|
|
}
|
|
|
|
public bool TestForLlcTraffic(string mac, int ethertype, int ssap, int dsap)
|
|
{
|
|
PhysicalAddress srcMac = PhysicalAddress.Parse(mac);
|
|
ushort etherType16 = Convert.ToUInt16(ethertype);
|
|
byte ssap8 = Convert.ToByte(ssap);
|
|
byte dsap8 = Convert.ToByte(dsap);
|
|
return TestForLlcTraffic(srcMac, etherType16, ssap8, dsap8);
|
|
}
|
|
|
|
private bool TestForLlcTraffic(PhysicalAddress srcMac, ushort etherType16, byte ssap8, byte dsap8)
|
|
{
|
|
if (_llcContents == null)
|
|
return false;
|
|
|
|
Tuple<PhysicalAddress, ushort, byte, byte> coordinate = new Tuple<PhysicalAddress, ushort, byte, byte>(srcMac, etherType16, ssap8, dsap8);
|
|
return _llcContents.ContainsKey(coordinate);
|
|
}
|
|
} |