// LISTENS TO VPN ADAPTER AND SENDS THE SPECIFIC PACKETS OUT THE NORMAL ADAPTER private static void TreatOUTPacketsVPNtoNormal(NdisApiDotNet outNdisapi, NetworkAdapter vpnAdapter, NetworkAdapter normalAdapter) { // Lists for re-injecting packets List <RawPacket> toAdapter = new List <RawPacket>(); List <RawPacket> toMstcp = new List <RawPacket>(); // Unmanaged memory resource for sending receiving bulk of packets // Maximum number of packets to send/receive = 64 NdisBufferResource buffer = new NdisBufferResource(64); outNdisapi.SetAdapterMode(vpnAdapter.Handle, MSTCP_FLAGS.MSTCP_FLAG_TUNNEL); outNdisapi.SetPacketEvent(vpnAdapter.Handle, outPacketEvent); do { outPacketEvent.WaitOne(); var packetList = outNdisapi.ReadPackets(vpnAdapter.Handle, buffer); while (packetList.Item1) { foreach (var packet in packetList.Item2) { Packet p = null; EthernetPacket ethernetPacket = null; TcpPacket tcpPacket = null; IPv4Packet ipv4Packet = null; ushort sport = 0; ushort dport = 0; try { p = Packet.ParsePacket(LinkLayers.Ethernet, packet.Data); ethernetPacket = (EthernetPacket)p; tcpPacket = (TcpPacket)((IPPacket)((EthernetPacket)p).PayloadPacket).PayloadPacket; ipv4Packet = (IPv4Packet)((EthernetPacket)p).PayloadPacket; sport = tcpPacket.SourcePort; dport = tcpPacket.DestinationPort; } catch (Exception ex) { if (packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE) { toMstcp.Add(packet); } else { toAdapter.Add(packet); } Console.WriteLine($"An exeption {ex.Message} occured while trying to parse network packet. Packet will be let thru without any changes"); continue; } DumpSourceChangingFilteredPacket(packet.DeviceFlags, ipv4Packet.SourceAddress.ToString(), sport.ToString(), ipv4Packet.DestinationAddress.ToString(), dport.ToString(), p.Bytes.Length, packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE); if (packet.DeviceFlags == PACKET_FLAG.PACKET_FLAG_ON_RECEIVE) { // Packet was received on VPN adapter, leave it as it is toMstcp.Add(packet); } else { if (ipv4Packet.SourceAddress.Equals(vpnIP)) { // Change the Source for outgoing packets that will later be sent thru normal adapter ipv4Packet.SourceAddress = localIp; ethernetPacket.SourceHardwareAddress = localMacAddress; ipv4Packet.UpdateIPChecksum(); tcpPacket.UpdateTcpChecksum(); ethernetPacket.UpdateCalculatedValues(); var newPackage = new RawPacket() { Data = p.Bytes, FilterId = packet.FilterId, Dot1q = packet.Dot1q, NdisFlags = packet.NdisFlags, DeviceFlags = packet.DeviceFlags }; toAdapter.Add(newPackage); } else { toAdapter.Add(packet); } } } if (toMstcp.Count > 0) { // If we have packets to forward upwards the network stack then do it here // RECEIVED SHOULD BE TREATED BY VPN ADAPTER outNdisapi.SendPacketsToMstcp(vpnAdapter.Handle, buffer, toMstcp); toMstcp.Clear(); } if (toAdapter.Count > 0) { // If we have packets to forward downwards the network stack then do it here // SENT SHOULD BE TREATED BY NORMAL ADAPTER outNdisapi.SendPacketsToAdapter(normalAdapter.Handle, buffer, toAdapter); toAdapter.Clear(); } packetList = outNdisapi.ReadPackets(vpnAdapter.Handle, buffer); } ; outPacketEvent.Reset(); } while (!stopCapturing); // // Release driver and associated resources // buffer.Dispose(); outNdisapi.SetPacketEvent(vpnAdapter.Handle, null); outNdisapi.SetAdapterMode(vpnAdapter.Handle, 0); }
/// <summary> /// 実行する /// </summary> public List <ScanResponse> Execute() { var ret = new List <ScanResponse>(); // デバイス変換 var device = _captureDevice as NpcapDevice; if (device == null) { throw new InvalidCastException(string.Format("デバイス {0} を NpcapDevice に変換できません", device.Description)); } // 送信元IPアドレス var srcIPAddress = GetIPv4(device); // SYNスキャン foreach (var request in _scanRequests) { // 送信先MACアドレス var arp = new ARP(device); var targetMacAddress = arp.Resolve(request.IPAddress); if (targetMacAddress == null) { ret.Add(new ScanResponse() { IPAddress = request.IPAddress, Port = request.Port, Status = PortStatus.UnResolved }); continue; //throw new InvalidOperationException(string.Format("アドレス {0} を ARP 解決できません", request.IPAddress.ToString())); } // TCPヘッダ生成 var tcpPacket = new TcpPacket(1024, request.Port); tcpPacket.Synchronize = !tcpPacket.Synchronize; tcpPacket.WindowSize = 4096; // IPヘッダ生成 var ipPacket = new IPv4Packet(srcIPAddress, request.IPAddress); // Ehternetヘッダ生成 var ethernetPacket = new EthernetPacket(device.Interface.MacAddress, targetMacAddress, EthernetType.None); // TCPパケット生成 ipPacket.PayloadPacket = tcpPacket; tcpPacket.UpdateTcpChecksum(); ethernetPacket.PayloadPacket = ipPacket; ipPacket.UpdateIPChecksum(); for (int retryCount = 0; retryCount < _maxRetryCount; retryCount++) { // オープン device.Open(DeviceMode.Normal, 1000); // フィルタセット device.Filter = "src host " + request.IPAddress + " and src port " + request.Port + " and (tcp[13] & 18 != 0) or (tcp[13] & 4 != 0)"; try { // TCPパケット送信 device.SendPacket(ethernetPacket); // 受信パケット取得 var rawpacket = device.GetNextPacket(); if (rawpacket == null) { if ((retryCount + 1) >= _maxRetryCount) { ret.Add(new ScanResponse() { IPAddress = request.IPAddress, Port = request.Port, Status = PortStatus.Timeout }); break; } continue; } else { // SYN/ACKフラグが立っていたら、open判定 // RSTフラグが立っていたらclosed判定 var response = Packet.ParsePacket(rawpacket.LinkLayerType, rawpacket.Data); if (response is EthernetPacket eth) { var ip = response.Extract <IPPacket>(); if (ip != null) { var tcp = response.Extract <TcpPacket>(); if (tcp != null) { if (tcp.Acknowledgment && tcp.Synchronize) { ret.Add(new ScanResponse() { IPAddress = request.IPAddress, Port = request.Port, Status = PortStatus.Open }); } else if (tcp.Reset) { ret.Add(new ScanResponse() { IPAddress = request.IPAddress, Port = request.Port, Status = PortStatus.Closed }); } else { ret.Add(new ScanResponse() { IPAddress = request.IPAddress, Port = request.Port, Status = PortStatus.UnKnown }); } } } } break; } } catch (Exception ex) { throw new Exception(ex.Message); } finally { if (device.Opened) { device.Close(); } } } } return(ret); }