buglwIP - A Lightweight TCP/IP stack - Bugs: bug #60607, IP traffic "leaks"...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #60607: IP traffic "leaks" between netifs

Submitted by:  Patrik Lantto <patriklantto>
Submitted on:  Fri 14 May 2021 08:16:37 PM UTC  
 
Category:  IPv4 Severity:  3 - Normal
Item Group:  Faulty Behaviour Status:  None
Privacy:  Public Assigned to:  None
Open/Closed:  Open Planned Release:  None
lwIP version:  git head

Mon 17 May 2021 03:48:34 PM UTC, comment #5: 

Mind that RFC 1122 still does routing based on src and dst IP addresses, lwIP already makes it possible to do that by implementing LWIP_HOOK_IP4_ROUTE_SRC as a user.

We didn't use that because we needed other things and because we already know the interface, so looking up the interface by address is unnecessary overhead.

Other things we needed to do:

- "Fix" ip4_input().
- Always send ICMP replies over the same interface as the received packet.
- Always send TCP RST back over the same interface as the received packet. (I see patch #9988 fixed this in the meantime.)
- Autobind new pcbs created by tcp_listen_input() to the interface the SYN came from.
- Honour p->if_idx for outgoing UDP packets.
- Change SNMP code to send packets over the configured interface.

We do bind most sockets to specific interfaces/addresses in application code too, except TCP listen sockets and some SNMP UDP sockets.

As this is very specific for our use case (hard separation between interfaces), I am not sure how generally useful this is, though for embedded systems you would expect this to be more common. We could split the above into multiple feature defines instead of one we use now.

What is the lwIP maintainers' opinion about this?

Indan Zupancic <indan>
Mon 17 May 2021 11:22:59 AM UTC, comment #4: 

comment #2:

> This is standard IP stack behaviour. Keep in mind the same happens for all outgoing packets.


I realize now I should have read RFC 1122 before stating that this was a "faulty behaviour" - it is as you say standard for "weak host model" stacks. It was me that expected the "strong host model", and it is rather a feature request to support this model.

Perhaps the best way forward here is to add a setting LWIP_STRONG_HOST_MODEL (defaulting to 0) and put that around parts of the code netif search code in ip4_input as well as for the routing (which would now be src aware routing if I understand correctly).

If your patchset would be available, that would obviously help - otherwise I can volunteer creating a patch for review.

Patrik Lantto <patriklantto>
Mon 17 May 2021 09:42:26 AM UTC, comment #3: 

Had a similar situation couple of years ago (see patch #9134).
We eventually switched to a different stack back then, but I would like to see something like this in lwIP.
Multiple interfaces are rather common nowadays, and imho you would usually  prefer clear encapsulation.
TL;DR: 1 Up for interest in patchset.

comment #2:

> At my work we use multiple interfaces for (physical) network redundancy and we need hard separation between networks, both for incoming as well as outgoing packets (in case peers are behind routers in different subnets and standard routing may choose the wrong interface). We changed both incoming as outgoing code paths to guarantee strict network separation.
>
> If there is enough interest I can ask permission to release the full patchset for merging with upstream lwIP.

Elias Reichart <alicer>
Mon 17 May 2021 08:21:20 AM UTC, comment #2: 

This is standard IP stack behaviour. Keep in mind the same happens for all outgoing packets.

The below code is "fixed" by adding an #if or #ifdef just after netif = NULL;.

At my work we use multiple interfaces for (physical) network redundancy and we need hard separation between networks, both for incoming as well as outgoing packets (in case peers are behind routers in different subnets and standard routing may choose the wrong interface). We changed both incoming as outgoing code paths to guarantee strict network separation.

If there is enough interest I can ask permission to release the full patchset for merging with upstream lwIP.

Indan Zupancic <indan>
Sat 15 May 2021 06:14:13 PM UTC, comment #1: 

The code in question has been there since I started with lwIP some 15 years ago. I don't know the exact reason for it, but I suppose one reason could be to communicate with e.g. the ethernet netif's address from behind a PPP remote host (depending on the routing).

However, I agree that in standard, routed netif setups, this should not really be required.

We might want to disable this but add an option for users to enable if needed.

Simon Goldschmidt <goldsimon>
Project Administrator
Fri 14 May 2021 08:16:37 PM UTC, original submission:  

When multiple netifs are used, IP traffic that is passed (via tcpip_input) to lwIP on one netif can be received on a different netif.

The "problematic" part of the code is in ip4_input where ip4_input_accept is called for the netif on which the ethernet frame was received. If that is not accepting the input, e.g. due to not having received an IP address from DHCP yet, all other netifs are searched to see if any of those netifs would accept the input. E.g. a broadcast packet received on one physical netif could be perceived as received on a completely different netif which could obviously lead to very strange issues (corresponding code also exists in ip6_input):

    /* start trying with inp. if that's not acceptable, start walking the
       list of configured netifs. */
    if (ip4_input_accept(inp)) {
      netif = inp;
    } else {
      netif = NULL;
#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
      /* Packets sent to the loopback address must not be accepted on an
       * interface that does not have the loopback address assigned to it,
       * unless a non-loopback interface is used for loopback traffic. */
      if (!ip4_addr_isloopback(ip4_current_dest_addr()))
#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
      {
#if !LWIP_SINGLE_NETIF
        NETIF_FOREACH(netif) {
          if (netif == inp) {
            /* we checked that before already */
            continue;
          }
          if (ip4_input_accept(netif)) {
            break;
          }
        }
#endif /* !LWIP_SINGLE_NETIF */
      }
    }

On a system using ethernet_input, I cannot really see any reason whatsoever why the complete list of netifs should be searched to find an interface that would accept the packet if the input netif does not. But I assume (hope!?) there is some reason for that code to exist?

Patrik Lantto <patriklantto>

 

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by alicer (Posted a comment)
  • -email is unavailable- added by indan (Posted a comment)
  • -email is unavailable- added by goldsimon (Posted a comment)
  • -email is unavailable- added by patriklantto (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

     

     

    No changes have been made to this item

    Back to the top


    Powered by Savane 3.7