/// <summary> /// This routine creates an instance of the Ipv4Header class from a byte /// array that is a received IGMP packet. This is useful when a packet /// is received from the network and the header object needs to be /// constructed from those values. /// </summary> /// <param name="ipv4Packet">Byte array containing the binary IPv4 header</param> /// <param name="bytesCopied">Number of bytes used in header</param> /// <returns>Returns the Ipv4Header object created from the byte array</returns> static public Ipv4Header Create(byte[] ipv4Packet, ref int bytesCopied) { Ipv4Header ipv4Header = new Ipv4Header(); // Make sure byte array is large enough to contain an IPv4 header if (ipv4Packet.Length < Ipv4Header.Ipv4HeaderLength) { return(null); } // Decode the data in the array back into the class properties ipv4Header.ipVersion = (byte)((ipv4Packet[0] >> 4) & 0xF); ipv4Header.ipLength = (byte)(ipv4Packet[0] & 0xF); ipv4Header.ipTypeOfService = ipv4Packet[1]; ipv4Header.ipTotalLength = BitConverter.ToUInt16(ipv4Packet, 2); ipv4Header.ipId = BitConverter.ToUInt16(ipv4Packet, 4); ipv4Header.ipOffset = BitConverter.ToUInt16(ipv4Packet, 6); ipv4Header.ipTtl = ipv4Packet[8]; ipv4Header.ipProtocol = ipv4Packet[9]; ipv4Header.ipChecksum = BitConverter.ToUInt16(ipv4Packet, 10); ipv4Header.ipSourceAddress = new IPAddress(BitConverter.ToUInt32(ipv4Packet, 12)); ipv4Header.ipDestinationAddress = new IPAddress(BitConverter.ToUInt32(ipv4Packet, 16)); bytesCopied = ipv4Header.Length; return(ipv4Header); }
public void Encapsulate(VpnChannel channel, VpnPacketBufferList packets, VpnPacketBufferList encapulatedPackets) { var vpnSendPacketBuffer = channel.GetVpnSendPacketBuffer(); while (packets.Size > 0) //can't iterate over packets { var packet = packets.RemoveAtEnd(); var packetAppId = packet.AppId; var packetBuffer = packet.Buffer; var fromBuffer = DataReader.FromBuffer(packetBuffer); var fromBufferUnconsumedBufferLength = fromBuffer.UnconsumedBufferLength; var bytes = new byte[fromBufferUnconsumedBufferLength]; fromBuffer.ReadBytes(bytes); var bytesRead = 0; var ipv4Header = Ipv4Header.Create(bytes, ref bytesRead); var vpnPacketBufferStatus = packet.Status; var packetTransportAffinity = packet.TransportAffinity; var packetTransportContext = packet.TransportContext; encapulatedPackets.Append(packet); //parse ip datagram and inspect destination IP //if destIP isn't found in peer list, drop and send ICMP "no route to host"? } }
public static byte[] AddUdpIpHeader(IPEndPoint srcAdr, IPEndPoint dstAdr, byte[] packet) { srcAdr = new IPEndPoint(IPAddress.Parse("25.175.152.176"), 9959); dstAdr = new IPEndPoint(IPAddress.Parse("25.175.152.176"), 9958); byte[] builtPacket = new byte[packet.Length]; ArrayList headerList = new ArrayList(); UdpHeader udpPacket = new UdpHeader(); udpPacket.SourcePort = (ushort)srcAdr.Port; udpPacket.DestinationPort = (ushort)dstAdr.Port; udpPacket.Length = (ushort)(UdpHeader.UdpHeaderLength + packet.Length); udpPacket.Checksum = 0; if (srcAdr.AddressFamily == AddressFamily.InterNetwork) { Ipv4Header ipv4Packet = new Ipv4Header(); ipv4Packet.Version = 4; ipv4Packet.Protocol = (byte)ProtocolType.Udp; ipv4Packet.Ttl = 2; ipv4Packet.Offset = 0; ipv4Packet.Length = (byte)Ipv4Header.Ipv4HeaderLength; ipv4Packet.TotalLength = Convert.ToUInt16(Ipv4Header.Ipv4HeaderLength + UdpHeader.UdpHeaderLength + packet.Length); ipv4Packet.SourceAddress = srcAdr.Address; ipv4Packet.DestinationAddress = dstAdr.Address; udpPacket.Ipv4PacketHeader = ipv4Packet; headerList.Add(ipv4Packet); } else if (srcAdr.AddressFamily == AddressFamily.InterNetworkV6) { Ipv6Header ipv6Packet = new Ipv6Header(); ipv6Packet.Version = 6; ipv6Packet.TrafficClass = 1; ipv6Packet.Flow = 2; ipv6Packet.HopLimit = 2; ipv6Packet.NextHeader = (byte)ProtocolType.Udp; ipv6Packet.PayloadLength = (ushort)(UdpHeader.UdpHeaderLength + packet.Length); ipv6Packet.SourceAddress = srcAdr.Address; ipv6Packet.DestinationAddress = dstAdr.Address; udpPacket.Ipv6PacketHeader = ipv6Packet; headerList.Add(ipv6Packet); } headerList.Add(udpPacket); builtPacket = udpPacket.BuildPacket(headerList, packet); return(builtPacket); }
/// <summary> /// /// </summary> /// <param name="ipFrom"></param> public static void IgmpQuery(string ipFrom) { try { ArrayList headerList = new ArrayList(); Ipv4Header ipv4Header = new Ipv4Header() { Version = 4, Protocol = (Byte)ProtocolType.Igmp, Ttl = 1, Offset = 0, Length = 20, TotalLength = (ushort)Convert.ToUInt16(IgmpHeader.IgmpHeaderLength /* + padByteCount*/), SourceAddress = IPAddress.Parse(ipFrom), DestinationAddress = IgmpHeader.AllSystemsAddress }; IgmpHeader igmpHeader = new IgmpHeader() { VersionType = IgmpHeader.IgmpMembershipQuery, MaximumResponseTime = 10, GroupAddress = IPAddress.Parse("0.0.0.0") }; headerList.Add(ipv4Header); headerList.Add(igmpHeader); Byte[] igmpPacket = igmpHeader.BuildPacket(headerList, new Byte[] { }); Socket igmpSocket = new Socket(IPAddress.Parse("0.0.0.0").AddressFamily, SocketType.Raw, ProtocolType.Igmp); igmpSocket.Bind(new IPEndPoint(IPAddress.Parse(ipFrom), 0)); igmpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1); igmpSocket.SendTo(igmpPacket, new IPEndPoint(IgmpHeader.AllSystemsAddress, 0)); } catch (Exception x) { LogManager.GetCurrentClassLogger().Log(LogLevel.Error, "Excepcion: " + x.Message, x); } }
public static byte[] Construct(IPAddress sourceAddress, ushort sourcePort, IPAddress destinationAddress, ushort destinationPort, byte[] payload) { var bindAddress = IPAddress.Any; // Make sure parameters are consistent //if ((sourceAddress.AddressFamily != destinationAddress.AddressFamily) || (sourceAddress.AddressFamily != bindAddress.AddressFamily)) //{ // throw new Exception("Source and destination address families don't match!"); //} // Start building the headers byte[] builtPacket; UdpHeader udpPacket = new UdpHeader(); ArrayList headerList = new ArrayList(); //Socket rawSocket = null; //SocketOptionLevel socketLevel = SocketOptionLevel.IP; // Fill out the UDP header first Console.WriteLine("Filling out the UDP header..."); udpPacket.SourcePort = sourcePort; udpPacket.DestinationPort = destinationPort; udpPacket.Length = (ushort)(UdpHeader.UdpHeaderLength + payload.Length); udpPacket.Checksum = 0; if (sourceAddress.AddressFamily == AddressFamily.InterNetwork) { Ipv4Header ipv4Packet = new Ipv4Header(); // Build the IPv4 header Console.WriteLine("Building the IPv4 header..."); ipv4Packet.Version = 4; ipv4Packet.Protocol = (byte)ProtocolType.Udp; ipv4Packet.Ttl = 2; ipv4Packet.Offset = 0; ipv4Packet.Length = (byte)Ipv4Header.Ipv4HeaderLength; ipv4Packet.TotalLength = (ushort)System.Convert.ToUInt16(Ipv4Header.Ipv4HeaderLength + UdpHeader.UdpHeaderLength + payload.Length); ipv4Packet.SourceAddress = sourceAddress; ipv4Packet.DestinationAddress = destinationAddress; // Set the IPv4 header in the UDP header since it is required to calculate the // pseudo header checksum Console.WriteLine("Setting the IPv4 header for pseudo header checksum..."); udpPacket.ipv4PacketHeader = ipv4Packet; // Add IPv4 header to list of headers -- headers should be added in th order // they appear in the packet (i.e. IP first then UDP) Console.WriteLine("Adding the IPv4 header to the list of header, encapsulating packet..."); headerList.Add(ipv4Packet); //socketLevel = SocketOptionLevel.IP; } else if (sourceAddress.AddressFamily == AddressFamily.InterNetworkV6) { Ipv6Header ipv6Packet = new Ipv6Header(); // Build the IPv6 header Console.WriteLine("Building the IPv6 header..."); ipv6Packet.Version = 6; ipv6Packet.TrafficClass = 1; ipv6Packet.Flow = 2; ipv6Packet.HopLimit = 2; ipv6Packet.NextHeader = (byte)ProtocolType.Udp; ipv6Packet.PayloadLength = (ushort)(UdpHeader.UdpHeaderLength + payload.Length); ipv6Packet.SourceAddress = sourceAddress; ipv6Packet.DestinationAddress = destinationAddress; // Set the IPv6 header in the UDP header since it is required to calculate the // pseudo header checksum Console.WriteLine("Setting the IPv6 header for pseudo header checksum..."); udpPacket.ipv6PacketHeader = ipv6Packet; // Add the IPv6 header to the list of headers - headers should be added in the order // they appear in the packet (i.e. IP first then UDP) Console.WriteLine("Adding the IPv6 header to the list of header, encapsulating packet..."); headerList.Add(ipv6Packet); //socketLevel = SocketOptionLevel.IPv6; } // Add the UDP header to list of headers after the IP header has been added Console.WriteLine("Adding the UDP header to the list of header, after IP header..."); headerList.Add(udpPacket); // Convert the header classes into the binary on-the-wire representation Console.WriteLine("Converting the header classes into the binary..."); builtPacket = udpPacket.BuildPacket(headerList, payload); /* * // Create the raw socket for this packet * Console.WriteLine("Creating the raw socket using Socket()..."); * rawSocket = new Socket(sourceAddress.AddressFamily, SocketType.Raw, ProtocolType.Udp); * * // Bind the socket to the interface specified * Console.WriteLine("Binding the socket to the specified interface using Bind()..."); * rawSocket.Bind(new IPEndPoint(bindAddress, 0)); * * // Set the HeaderIncluded option since we include the IP header * Console.WriteLine("Setting the HeaderIncluded option for IP header..."); * rawSocket.SetSocketOption(socketLevel, SocketOptionName.HeaderIncluded, 1); * * try * { * // Send the packet! * Console.WriteLine("Sending the packet..."); * int rc = rawSocket.SendTo(builtPacket, new IPEndPoint(destinationAddress, destinationPort)); * Console.WriteLine("send {0} bytes to {1}", rc, destinationAddress.ToString()); * } * catch (SocketException err) * { * Console.WriteLine("Socket error occurred: {0}", err.Message); * // http://msdn.microsoft.com/en-us/library/ms740668.aspx * } * finally * { * // Close the socket * Console.WriteLine("Closing the socket..."); * rawSocket.Close(); * } */ return(builtPacket); }
/// <summary> /// This is the asynchronous callback that is fired when an async ReceiveFrom. /// An asynchronous ReceiveFrom is posted by calling BeginReceiveFrom. When this /// function is invoked, it calculates the elapsed time between when the ping /// packet was sent and when it was completed. /// </summary> /// <param name="ar">Asynchronous context for operation that completed</param> static void PingReceiveCallback(IAsyncResult ar) { RawSocketPing rawSock = (RawSocketPing)ar.AsyncState; TimeSpan elapsedTime; int bytesReceived = 0; ushort receivedId = 0; try { // Keep a count of how many async operations are outstanding -- one just completed // so decrement the count. Interlocked.Decrement(ref rawSock.pingOutstandingReceives); // If we're done because ping is exiting and the socket has been closed, // set the done event if (rawSock.pingSocket == null) { if (rawSock.pingOutstandingReceives == 0) { rawSock.pingDoneEvent.Set(); } return; } // Complete the receive op by calling EndReceiveFrom. This will return the number // of bytes received as well as the source address of who sent this packet. bytesReceived = rawSock.pingSocket.EndReceiveFrom(ar, ref rawSock.castResponseEndPoint); // Calculate the elapsed time from when the ping request was sent and a response was // received. elapsedTime = DateTime.Now - rawSock.pingSentTime; rawSock.responseEndPoint = (IPEndPoint)rawSock.castResponseEndPoint; // Here we unwrap the data received back into the respective protocol headers such // that we can find the ICMP ID in the ICMP or ICMPv6 packet to verify that // the echo response we received was really a response to our request. if (rawSock.pingSocket.AddressFamily == AddressFamily.InterNetwork) { Ipv4Header v4Header; IcmpHeader icmpv4Header; byte[] pktIcmp; int offset = 0; // Remember, raw IPv4 sockets will return the IPv4 header along with all // subsequent protocol headers v4Header = Ipv4Header.Create(rawSock.receiveBuffer, ref offset); pktIcmp = new byte[bytesReceived - offset]; Array.Copy(rawSock.receiveBuffer, offset, pktIcmp, 0, pktIcmp.Length); icmpv4Header = IcmpHeader.Create(pktIcmp, ref offset); /*Console.WriteLine("Icmp.Id = {0}; Icmp.Sequence = {1}", * icmpv4Header.Id, * icmpv4Header.Sequence * );*/ receivedId = icmpv4Header.Id; } else if (rawSock.pingSocket.AddressFamily == AddressFamily.InterNetworkV6) { Icmpv6Header icmp6Header; Icmpv6EchoRequest echoHeader; byte[] pktEchoRequest; int offset = 0; // For IPv6 raw sockets, the IPv6 header is never returned along with the // data received -- the received data always starts with the header // following the IPv6 header. icmp6Header = Icmpv6Header.Create(rawSock.receiveBuffer, ref offset); pktEchoRequest = new byte[bytesReceived - offset]; Array.Copy(rawSock.receiveBuffer, offset, pktEchoRequest, 0, pktEchoRequest.Length); echoHeader = Icmpv6EchoRequest.Create(pktEchoRequest, ref offset); /*Console.WriteLine("Icmpv6.Id = {0}; Icmp.Sequence = {1}", * echoHeader.Id, * echoHeader.Sequence * );*/ receivedId = echoHeader.Id; } if (receivedId == rawSock.pingId) { string elapsedString; // Print out the usual statistics for ping if (elapsedTime.Milliseconds < 1) { elapsedString = "<1"; } else { elapsedString = "=" + elapsedTime.Milliseconds.ToString(); } Console.WriteLine("Reply from {0}: byte={1} time{2}ms TTL={3} ", rawSock.responseEndPoint.Address.ToString(), bytesReceived, elapsedString, rawSock.pingTtl ); } // Post another async receive if the count indicates for us to do so. if (rawSock.pingCount > 0) { rawSock.pingSocket.BeginReceiveFrom( rawSock.receiveBuffer, 0, rawSock.receiveBuffer.Length, SocketFlags.None, ref rawSock.castResponseEndPoint, rawSock.receiveCallback, rawSock ); // Keep track of outstanding async operations Interlocked.Increment(ref rawSock.pingOutstandingReceives); } else { // If we're done then set the done event if (rawSock.pingOutstandingReceives == 0) { rawSock.pingDoneEvent.Set(); } } // If this is indeed the response to our echo request then signal the main thread // that we received the response so it can send additional echo requests if // necessary. This is done after another async ReceiveFrom is already posted. if (receivedId == rawSock.pingId) { rawSock.pingReceiveEvent.Set(); } } catch (SocketException err) { Console.WriteLine("Socket error occurred in async callback: {0}", err.Message); } }
public static void WireguardTest() { var protocol = new Protocol( HandshakePattern.IK, CipherFunction.ChaChaPoly, HashFunction.Blake2s, PatternModifiers.Psk2 ); var buffer = new byte[Protocol.MaxMessageLength]; var buffer2 = new byte[Protocol.MaxMessageLength]; int bufferRead = 0; using (var hs = protocol.Create(true, new ReadOnlySpan <byte>(Encoding.UTF8.GetBytes("WireGuard v1 zx2c4 [email protected]")), OurPrivate, TheirPublic, new byte[][] { Preshared })) { var now = DateTimeOffset.UtcNow; //replace with Noda.Time? var tai64n = new byte[12]; (4611686018427387914ul + (ulong)now.ToUnixTimeSeconds()).ToBigEndian(tai64n); ((uint)(now.Millisecond * 1e6)).ToBigEndian(tai64n, 8); var initiationPacket = new List <byte> { 1, 0, 0, 0 }; //type initiation initiationPacket.AddRange(((uint)28).ToLittleEndian()); //sender, random 4byte var(bytesWritten, _, _) = hs.WriteMessage(tai64n, buffer); initiationPacket.AddRange(buffer.Take(bytesWritten)); // should be 24byte, ephemeral, static, timestamp var hasher = Blake2s.CreateIncrementalHasher(32); var hashThis = Encoding.UTF8.GetBytes("mac1----").Concat(TheirPublic).ToArray(); hasher.Update(hashThis); var finishedHash = hasher.Finish(); hasher = Blake2s.CreateIncrementalHasher(16, finishedHash); hashThis = initiationPacket.ToArray(); hasher.Update(hashThis); finishedHash = hasher.Finish(); initiationPacket.AddRange(finishedHash); //mac1 initiationPacket.AddRange(Enumerable.Repeat((byte)0, 16)); //mac2 = zeros if no cookie last received var socket = new DatagramSocket(); var responsePacket = new TaskCompletionSource <int>(); var autoResetEvent = new AutoResetEvent(false); socket.MessageReceived += (sender, args) => { bufferRead = args.GetDataStream().AsStreamForRead().Read(buffer); autoResetEvent.Set(); }; socket.ConnectAsync(new HostName("demo.wireguard.com"), "12913").AsTask().Wait(); var streamWriter = new BinaryWriter(socket.OutputStream.AsStreamForWrite()); streamWriter.Write(initiationPacket.ToArray()); streamWriter.Flush(); var successful = autoResetEvent.WaitOne(5000); if (!successful) { return; } if (buffer[0] != 2) //type init response { return; //"response packet type wrong: want %d, got %d" } if (bufferRead != 92) //always this length! for type=2 { return; //"response packet too short: want %d, got %d" } if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0) { return; //"response packet has non-zero reserved fields" } var theirIndex = buffer.LittleEndianToUInt32(4); var ourIndex = buffer.LittleEndianToUInt32(8); if (ourIndex != 28) { return; //log.Fatalf("response packet index wrong: want %d, got %d", 28, ourIndex) } var span = new Span <byte>(buffer); var(bytesRead, handshakeHash, transport) = hs.ReadMessage(span.Slice(12, 48), span.Slice(100)); //write on same buffer behind the received package (which if (bytesRead != 0) { return; //"unexpected payload: %x" } var icmpHeader = new IcmpHeader() { Type = 8, Id = 921, Sequence = 438 }; var pingMessage = icmpHeader.GetProtocolPacketBytes(Encoding.UTF8.GetBytes("WireGuard")); var pingHeader = new Ipv4Header() { Version = 4, Length = 20, TotalLength = (ushort)(20 + pingMessage.Length), Protocol = 1, Ttl = 20, SourceAddress = new IPAddress(new byte[] { 10, 189, 129, 2 }), DestinationAddress = new IPAddress(new byte[] { 10, 189, 129, 1 }) }.GetProtocolPacketBytes(new byte[0]); span[0] = 4; span.Slice(1, 3).Assign((byte)0); theirIndex.ToLittleEndian(buffer, 4); 0L.ToLittleEndian(buffer, 8); //this is the counter, little endian u64 bytesWritten = transport.WriteMessage( pingHeader.Concat(pingMessage).Concat(Enumerable.Repeat((byte)0, 11)).ToArray(), //pad message with 0 to make mod 16=0 span.Slice(16)); //using (var streamWriter = new BinaryWriter(socket.OutputStream.AsStreamForWrite())) streamWriter.Write(span.Slice(0, 16 + bytesWritten).ToArray()); streamWriter.Flush(); successful = autoResetEvent.WaitOne(5000); if (!successful) { return; } if (buffer[0] != 4) { return;//"response packet type wrong: want %d, got %d" } if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0) { return; //"response packet has non-zero reserved fields" } var replyPacket = buffer2.AsSpan(0, transport.ReadMessage(span.Slice(16, bufferRead - 16), buffer2)); if (replyPacket.Length != 48) { return; } var replyHeaderLen = ((int)(replyPacket[0] & 0x0f)) << 2; var replyLen = buffer2.BigEndianToUInt16(2); var our_index_received = buffer.LittleEndianToUInt32(4); if (our_index_received != 28) { return; } var nonce = buffer2.LittleEndianToUInt64(8); //if (nonce != 0)//not parsed correctly? // return; var replyMessage = IcmpHeader.Create(buffer2.AsSpan(replyHeaderLen, replyLen - replyHeaderLen).ToArray(), ref bytesRead); if (replyMessage.Type != 0 || replyMessage.Code != 0) { return; } if (replyMessage.Id != 921 || replyMessage.Sequence != 438) { return; } var replyPayload = Encoding.UTF8.GetString(buffer2.AsSpan(replyLen - replyHeaderLen + bytesRead, replyHeaderLen - bytesRead)); if (replyPayload != "WireGuard") //trim necessary? { return; } } }
public TcpHeader(string src_port, string dest_port, bool? urg, bool? ack, bool? psh, bool? rst, bool? syn, bool? fin, string data) : base() { Random rand = new Random(); try { _src_port = Convert.ToUInt16(src_port); _dst_port = Convert.ToUInt16(dest_port); } catch (Exception ex) { throw ex; } if (urg == true) { _flags |= (byte)TcpFlags.URG; _urgent_pointer = (ushort)rand.Next(); } else _urgent_pointer = 0; if (ack == true) { _flags |= (byte)TcpFlags.ACK; _ack_n = (uint)rand.Next(); } if (ack == false) _ack_n = 1; if (psh == true) _flags |= (byte)TcpFlags.PSH; if (rst == true) _flags |= (byte)TcpFlags.RST; if (syn == true) _flags |= (byte)TcpFlags.SYN; _seq_n = (uint)1000; if (fin == true) _flags |= (byte)TcpFlags.FIN; _win = 256; _offset = (byte)(0xF0 & (5 << 4)); _crc = 0; ipv4PacketHeader = null; }
public TcpHeader() : base() { _src_port = 0; _dst_port = 0; _seq_n = 0; _ack_n = 0; _offset = 0; _flags = 0; _win = 0; _crc = 0; _urgent_pointer = 0; ipv4PacketHeader = null; }