Re-routing TCP packets

Home Forums Discussions Support Portal Re-routing TCP packets

This topic contains 20 replies, has 4 voices, and was last updated by  fitland 13 years, 1 month ago.

Viewing 15 posts - 1 through 15 (of 21 total)
  • Author
    Posts
  • #4839

    Voxen
    Participant

    Hello,

    I’m writting a filter that has to re-route outgoing POP3 packets to a local POP3 server so the mailer actually connects to the local server instead of the real one. I’m very new to TCP/IP programming.

    Here is my thread’s loop:

    // Loop filtering packets
    while (!Terminated)
    ..{
    ..WaitForSingleObject(hEvent, INFINITE);
    ..ResetEvent(hEvent);

    ..while (!Terminated && NdisApi.ReadPacket(&Request))
    ….{
    ….if (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND)
    ……{
    ……// Sent packet
    ……ether_header* pEthHeader = (ether_header*)PacketBuffer.m_IBuffer;
    ……if (ntohs(pEthHeader->h_proto) == ETH_P_IP)
    ……..{
    ……..// IP
    ……..iphdr_ptr pIp = (iphdr_ptr)&PacketBuffer.m_IBuffer[sizeof(ether_header)];
    ……..if (pIp->ip_p == IPPROTO_TCP)
    ……….{
    ……….// TCP
    ……….tcphdr_ptr pTcp = (tcphdr_ptr)(((PUCHAR)pIp) + sizeof(DWORD)*pIp->ip_hl);
    ……….in_addr IPs = pIp->ip_src;
    ……….in_addr IPd = pIp->ip_dst;
    ……….if (ntohs(pTcp->th_dport) == 110)
    …………{
    …………if (!strcmp(inet_ntoa(IPd), “211.182.33.20”))
    …………..{
    …………..// Change destination IP and port
    …………..pIp->ip_dst.S_un.S_addr = inet_addr(“192.168.0.3”);
    …………..pTcp->th_dport = 115;
    …………..RecalculateIPChecksum(&PacketBuffer);
    …………..RecalculateTCPChecksum(&PacketBuffer);
    …………..}
    …………}
    ……….}
    ……..}

    ……..// Place packet on the network interface
    ……..NdisApi.SendPacketToAdapter(&Request);
    ……..}
    ……else
    ……..{
    ……..// Indicate packet to MSTCP
    ……..NdisApi.SendPacketToMstcp(&Request);
    ……..}
    ……}
    ….}

    Of course this doesn’t work. All the code seems correct, because if I disable the IP and port modification, the filter runs ok (checksum calculation methods are correct).
    I belive something is missing, but what?

    Thanks for your help!

    #5521

    bk
    Participant

    Why don’t you install ethereal and check if the checksums are really correct (perhaps thew work correctly if you don’t change the data)?

    #5522

    Voxen
    Participant

    I captured the packets with Ethereal, the checksum are both correct.
    The mail client loops sending SYN but gets no reply.

    Do I need to modify the destination MAC address as well (copy source MAC address to destination)?

    #5523

    Vadim Smirnov
    Moderator

    After outgoing packet modification I would indicate it to MSTCP instead sending it over the network.

    Hope it helps…

    #5524

    Voxen
    Participant

    You mean calling NdisApi.SendPacketToMstcp(&Request) instead of NdisApi.SendPacketToAdapter(&Request) in my example above?

    I’ve just tried this and it doesn’t work any better.
    Should I modify something else in the packet?
    Or should I switch this “sent” packet into a “receive” one?

    Sorry but I’m a bit lost…

    #5525

    bk
    Participant

    @voxen wrote:

    Do I need to modify the destination MAC address as well (copy source MAC address to destination)?

    Yes, if the destination host is not the same machine as the original destination you need to change the mac address, unless you are using a gateway and the destination is not the gateway itself.

    If you are sending packets through a gateway, the destination MAC address should be the MAC of the gateway. If both the (original and changed) destination IP are reachable through the GW, then you should not need to change the dest MAC since the destination MAC is the same.

    But since the original IP seems to be on the internet while the new destination seems to be on the local net, you must change the MAC to the one of the new host.

    Let me explain: the MAC address is the low level address of a host on a local net. The IP address is a higher level address, and may be outside the local net.

    If you send a packet through different nets, the IP address can be the true destination across networks, while the MAC address must be the destination of the next step on the local net. As an example, suppose you have a local host with IP 192.168.0.2 and MAC address “MACa”, a local gateway with IP 192.168.0.1 and “MACb”. Your destination is an external host with IP 212.144.155.166. Since the destination is not on the local net, the packets must be routed through the local gateway. You don’t need and don’t know the real destination MAC address. You packet should then have IP destination 212.144.155.166 BUT MAC address MACb. If you change the destination IP BUT the next step along the path is still the gateway, then the MAC address is still MACb since the next step is still the GW on the local net.
    Let’s suppose that you change the destination to a local IP address, then if you don’t change the MAC address to the MAC of the new local destination the packets will still be sent to the GW, which can route the packets or throw them away, depending on how it’s configured.
    The best bet is to send the packets to the real destination host, and since it’s on the local net, you can set the correct MAC address to reach it.
    Btw, the CORRECT thing to do is to set the MAC address to the MAC of the next host along the router. Also notice that if the destination is on a different network interface, you must send the packet to the correct one.

    Suppose you have this config:

    A is connected to the internet through a local net, with gateway B
    A il also conneted to another local net, using another ethernet card, with the host C.

    If you send a packet to the internet, then your OS will use the first interface, set the IP destination to the destination host on the internet and MAC address of B, since B is the next step on the path.
    When you catch the outgoing packets with winpkfilter, then routing has already been done: the OS has already chosen the first interface, MAC of B.
    If you want to route the packet to C, then you must change the IP to the IP address of B, the MAC to the MAC address of B, AND QUEUE THE PACKET on the SECOND interface.

    #5526

    Voxen
    Participant

    Thank you bk for this very clear explanation.

    As I’m running both the mail client, the POP3 server and the packet filter on the same PC, I guess that what I must do is:
    – capture the outgoing packet
    – change its IP and port to localhost/110
    – change its MAC address to PC’s MAC address
    – recalculate checksums
    – send the packet to MSTCP (as stated by SerpentFly above) and not Adapter

    So, since the packet originator is the mail client running on the same PC, the source MAC address it the one I should set as MAC destination, right?

    #5527

    bk
    Participant

    @voxen wrote:

    As I’m running both the mail client, the POP3 server and the packet filter on the same PC, I guess that what I must do is:
    – capture the outgoing packet
    – change its IP and port to localhost/110
    – change its MAC address to PC’s MAC address
    – recalculate checksums
    – send the packet to MSTCP (as stated by SerpentFly above) and not Adapter

    So, since the packet originator is the mail client running on the same PC, the source MAC address it the one I should set as MAC destination, right?

    Ehm, this is a kind of a special case. You can’t catch internal packets with winpkfilter, so I’m not sure you can also send localhost packets to windows that way. The steps above are correct, but I’m not sure you can inject a packet with localhost destination using winpkfilter. Windows might decide to throw your packets away.. 😕

    #5528

    bk
    Participant

    If changing to localhost does not work, try with the IP address of the ethernet card you are catching the packets from (and make up a fake source IP address if source == destination does not work). This way your packets should appear as coming from an external host to the adapter and should work.

    #5529

    Voxen
    Participant

    I’ll try that! Thanks again bk.

    #5530

    Voxen
    Participant

    Well I’ve not been able to make it work within the same machine 😥

    I’ve been able to reroute to another PC in the local area network but it doesn’t totally work either. This is roughly what Ethereal reports:
    PCA -> SYN -> PCB
    PCA < - SYN/ACK <- PCB
    PCA < - SYN/ACK <- PCB
    PCA -> RST -> PCB (ZeroWindow)

    #5531

    Vadim Smirnov
    Moderator

    It looks that something was wrong when processing the packets below:
    PCA < - SYN/ACK <- PCB
    PCA < - SYN/ACK <- PCB
    and connection was terminated due to time out. I would try to check what happens there.

    #5532

    Voxen
    Participant

    SerpentFly, could you tell me if WinpkFilter is able to process internal packets as bk said it probably doesn’t? I need to reroute packets sent from local machine to local machine instead of Internet.

    #5533

    Vadim Smirnov
    Moderator

    If you mean packet sent to localhost (127.X.X.X) then the answer is NO. These packets (actually they never have the form of packets with IP and TCP headers, just chunks of data) are processed internally by TCP/IP and never reach NDIS level.

    #5534

    bk
    Participant

    Voxen, I’ve seen now your post:

    PCA -> SYN -> PCB
    PCA < - SYN/ACK <- PCB
    PCA < - SYN/ACK <- PCB
    PCA -> RST -> PCB (ZeroWindow)

    From what I understand, PCA does not respond to the SYN/ACK packet coming from PCB. I could help you better if you describe me exactly what you do, but I have a hint.
    PCA generates a packet, you change the destination and PCB receives it.
    PCB responds to the packet, sending the answer to PCA. But since PCA is not expeting an ACK from PCB (he thinks he’s talking with the original host you substituted) it will throw the packet away.
    When you receive a packet from PCB, you must reverse what you’ve done before: substitute che source from PCB to the original destination.

    I.e:

    1) PCA sends a packet to PCX. You change the destination to PCB.
    2) PCB answers to PCA, but PCA is expecting an answer from PCX, NOT PCB!
    So you must reverse the changes you’ve done in step 1, reverting the sender from PCB to PCX.

    I’m not sure it’s your problem, since you don’t describe exactly what you do. Btw, you are trying to NAT che packets, try reading some papers on this subject.

Viewing 15 posts - 1 through 15 (of 21 total)

You must be logged in to reply to this topic.