2014-01-13 2 views
3

GET 요청을 시뮬레이트하기 위해 테스트 서버에 유효한 TCP 연결을 만들려고합니다. 잘만되면 나는 해결책에 가깝다.Pcap.NET에서 유효한 TCP 연결 만들기

그러나 enter image description here

, 내가 ACK 표시 할 수없는 것 : 실제 요청에서 와이어 샤크의 데이터를 사용하여

, 나는 PacketCommunicator.SendPacket()를 사용하여 하나 개의 패키지를 보낼 때 SYN & SYN-ACK를 얻기 위해 관리했습니다 . 후자 (현재 비 작동)은 단지 HttpRequestLayer + 언급 된 것들을 사용하면서

첫번째 패킷, EthernetLayer, 및 IpV4LayerTcpLayer하여 구성된다.

마지막 패킷 TcpLayerControlBitsTcpControlBits.Acknowledgment으로 설정됩니다. 그럼에도 불구하고 내 "실제"GET 요청처럼 WireShark에 표시되지 않습니다.

코드의 관련 부분을 게시했습니다. 그렇지 않다면 알려주세요.

답변

6

다음은 작동하는 초안입니다 (확인했습니다).

HttpGetSender 인스턴스를 구성 할 때 필요한 값을 원하는 값으로 변경하십시오.

까다로운 부분은 시퀀스 및 승인 번호를 올바르게 얻는 것입니다.

using System; 
using System.Collections.Generic; 
using PcapDotNet.Core; 
using PcapDotNet.Packets; 
using PcapDotNet.Packets.Ethernet; 
using PcapDotNet.Packets.Http; 
using PcapDotNet.Packets.IpV4; 
using PcapDotNet.Packets.Transport; 

namespace SendingHttpGet 
{ 
    internal class HttpGetSender 
    { 
     public HttpGetSender() 
     { 
     } 

     public MacAddress SourceMac { get; set; } 
     public MacAddress DestinationMac { get; set; } 
     public IpV4Address SourceIpV4 { get; set; } 
     public IpV4Address DestinationIpV4 { get; set; } 
     public string Host { get; set; } 

     public void Run(PacketDevice device) 
     { 
      using (PacketCommunicator communicator = device.Open(100, // name of the device 
                   PacketDeviceOpenAttributes.Promiscuous, 
                   // promiscuous mode 
                   100)) // read timeout 
      { 
       SendSyn(communicator); 
       WaitForAck(communicator); 
      } 
     } 

     private void WaitForAck(PacketCommunicator communicator) 
     { 
      communicator.SetFilter("tcp and src " + DestinationIpV4 + " and dst " + SourceIpV4 + " and src port " + _destinationPort + " and dst port " + _sourcePort); 
      Packet packet; 
      while (true) 
      { 
       if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok) 
       { 
        if (packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber == _expectedAckNumber) 
        { 
         _seqNumber = _expectedAckNumber; 
         _ackNumber = packet.Ethernet.IpV4.Tcp.SequenceNumber + 1; 
         SendGet(communicator); 
         break; 
        } 

       } 
       SendSyn(communicator); 
      } 
      WaitForResponse(communicator); 
     } 

     private void WaitForResponse(PacketCommunicator communicator) 
     { 
      communicator.SetFilter("tcp and src " + DestinationIpV4 + " and dst " + SourceIpV4 + " and src port " + _destinationPort + " and dst port " + _sourcePort); 
      Packet packet; 
      while (true) 
      { 
       if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok) 
       { 
        Console.WriteLine("Expected ack number: " + _expectedAckNumber); 
        Console.WriteLine("Received ack number: " + packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber); 
        if (packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber == _expectedAckNumber) 
        { 
         break; 
        } 

       } 
       SendGet(communicator); 
      } 
     } 

     private void SendSyn(PacketCommunicator communicator) 
     { 
      // Ethernet Layer 
      EthernetLayer ethernetLayer = new EthernetLayer 
               { 
                Source = SourceMac, 
                Destination = DestinationMac, 
               }; 

      // IPv4 Layer 
      IpV4Layer ipV4Layer = new IpV4Layer 
             { 
              Source = SourceIpV4, 
              CurrentDestination = DestinationIpV4, 
              Ttl = 128, 
              Fragmentation = 
               new IpV4Fragmentation(IpV4FragmentationOptions.DoNotFragment, 0), 
              Identification = 1234, 
             }; 

      // TCP Layer 
      TcpLayer tcpLayer = new TcpLayer 
            { 
             SourcePort = _sourcePort, 
             DestinationPort = _destinationPort, 
             SequenceNumber = _seqNumber, 
             ControlBits = TcpControlBits.Synchronize, 
             Window = _windowSize, 
            }; 

      communicator.SendPacket(PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, tcpLayer)); 
      _expectedAckNumber = _seqNumber + 1; 
     } 

     private void SendGet(PacketCommunicator communicator) 
     { 
      // Ethernet Layer 
      EthernetLayer ethernetLayer = new EthernetLayer 
      { 
       Source = SourceMac, 
       Destination = DestinationMac, 
      }; 

      // IPv4 Layer 
      IpV4Layer ipV4Layer = new IpV4Layer 
      { 
       Source = SourceIpV4, 
       CurrentDestination = DestinationIpV4, 
       Ttl = 128, 
       Fragmentation = 
        new IpV4Fragmentation(IpV4FragmentationOptions.DoNotFragment, 0), 
       Identification = 1235, 
      }; 

      // TCP Layer 
      TcpLayer tcpLayer = new TcpLayer 
      { 
       SourcePort = _sourcePort, 
       DestinationPort = _destinationPort, 
       SequenceNumber = _seqNumber, 
       AcknowledgmentNumber = _ackNumber, 
       ControlBits = TcpControlBits.Acknowledgment, 
       Window = _windowSize, 
      }; 

      // HTTP Layer 
      HttpLayer httpLayer = new HttpRequestLayer 
      { 
       Uri = "/", 
       Header = new HttpHeader(HttpField.CreateField("Host", Host)), 
       Method = new HttpRequestMethod(HttpRequestKnownMethod.Get), 
       Version = HttpVersion.Version11, 
      }; 

      Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, tcpLayer, httpLayer); 
      communicator.SendPacket(packet); 
      _expectedAckNumber = (uint) (_seqNumber + packet.Ethernet.IpV4.Tcp.PayloadLength); 
     } 

     private ushort _sourcePort = (ushort) (4123 + new Random().Next() % 1000); 
     private ushort _destinationPort = 80; 
     private uint _seqNumber = (uint) new Random().Next(); 
     private uint _expectedAckNumber; 
     private ushort _windowSize = 8192; 
     private uint _ackNumber; 
    } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      // Retrieve the device list from the local machine 
      IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine; 

      if (allDevices.Count == 0) 
      { 
       Console.WriteLine("No interfaces found! Make sure WinPcap is installed."); 
       return; 
      } 

      // Print the list 
      for (int i = 0; i != allDevices.Count; ++i) 
      { 
       LivePacketDevice device = allDevices[i]; 
       Console.Write((i + 1) + ". " + device.Name); 
       if (device.Description != null) 
        Console.WriteLine(" (" + device.Description + ")"); 
       else 
        Console.WriteLine(" (No description available)"); 
      } 

      int deviceIndex = 0; 
      do 
      { 
       Console.WriteLine("Enter the interface number (1-" + allDevices.Count + "):"); 
       string deviceIndexString = Console.ReadLine(); 
       if (!int.TryParse(deviceIndexString, out deviceIndex) || 
        deviceIndex < 1 || deviceIndex > allDevices.Count) 
       { 
        deviceIndex = 0; 
       } 
      } while (deviceIndex == 0); 

      // Take the selected adapter 
      PacketDevice selectedDevice = allDevices[deviceIndex - 1]; 

      HttpGetSender sender = new HttpGetSender 
             { 
              SourceMac = new MacAddress("your:host:mac:address:1:2"), 
              DestinationMac = new MacAddress("gateway:mac:address:1:2:3"), 
              SourceIpV4 = new IpV4Address("your.host.ip.address"), 
              DestinationIpV4 = new IpV4Address("target.host.ip.address"), 
              Host = "targethost.com", 
             }; 

      sender.Run(selectedDevice); 
     } 
    } 
} 
+0

시간을내어 주셔서 감사합니다. 이제 WireShark에서 훨씬 좋아 보입니다. 그러나, 서버는 그것을 데리러하지 않습니다. 수정해야하는 '보낸 사람'속성 외에 다른 것이 있습니까? 예를 들어'HttpLayer '의'Uri'를'/'로 설정해야합니까? – Johan

+0

이 패킷을 보내는 데 사용중인 호스트가 활성화되어 있으면 보내지 않은 TCP 연결에 대한 응답을 볼 수 있으며 서버에서 연결을 종료하는 RST 패킷을 보냅니다. 그리고 예, 당신은 보통 정상적인 HTTP GET 패킷을보고 비슷한 것을 보내야합니다. – brickner