What kind of "firewall" feature is common on embedded products these days?
lwIP does not have one built-in, but as I explained above, it does have hooks for implementing one.
To filter even ARP and ICMP packets in the firewall, you do need to modify lwIP sources, though.
The lwIP stack is very, very small, and typically you would not try to implement a stateful packet filter; only a simple stateless filtering –– that is, for IP networking, based on source and destination IP addresses (and for TCP over IP, the port numbers), but without any concept of "established connection" per se, just treating each individual packet as a separate entity.
The plan is to put in a feature whereby a list of IPs can be permitted.
Implement
LWIP_HOOK_IP4_INPUT() and/or
LWIP_HOOK_IP6_INPUT() that return
0 if the packet has a valid/acceptable source address (including 0.0.0.0 if you use DHCP!), and nonzero otherwise.
For IPv4, for each whitelisted IP address or subnet, you can use
ip4_addr_net_eq(srcaddr, addr1, mask1) to see if IPv4 address
srcaddr is within the subnet defined by IPv4 address
addr1 and netmask
mask1. (It expands to
(srcaddr & mask1) == (addr1 & mask1).) For specific hosts, the mask is all bits set, otherwise, the
k high bits set and
32-k low bits clear (and the compact address-netmask form is then
ip.ad.dre.ss/k). If the
32-k low bits are cleared in
addr1, then test
(srcaddr & mask1) == addr1 suffices.
If the addresses (and associated netmasks) are in a sorted array without overlaps, a binary search on the addresses in network byte order (most significant byte first), followed by IIRC two
ip4_addr_net_eq() checks should yield the answer.
This does expose the existence of the host to all other hosts on the subnet, which should be okay. (To avoid that for IPv4, you could modify
src/core/ipv4/etharp.c:etharp_input() just after the
/* send ARP response */ comment, so that *only* when if
hdr->sipaddr is a valid source IP address, is the
etharp_raw() call done immediately following the comment; and do a similar check in
src/core/ipv4/icmp.c:icmp_input() to only respond ICMP packets from the explicitly allowed addresses.)
I'm pretty sure that if one would take the couple of hours to properly add
LWIP_HOOK_IP4_FILTER(fromaddr,toaddr) and
LWIP_HOOK_IP6_FILTER(fromaddr,toaddr) and
LWIP_HOOK_TCP_FILTER(fromaddr, fromport, toaddr, toport) support to the proper places and the day or two it would take to test it actually works right (when different features are enabled and disabled; i.e. lots of compile tests, and basic real-life functionality test), it'd be accepted upstream. These return 0 if the packet should be handled normally, and nonzero to blackhole (DROP) the packet. (REJECT support would need a bit of additional code.) This would make it easier to implement the (stateless) packet filter and even intrusion detection to otherwise unused ports (ftp/21, ssh/22, telnet/23, smtp/25, http/80, pop3/110, imap/143, ldap/389, https/443, etc). This would seriously reduce the maintenance burden long term, because one could then use unmodified upstream LWIP stack, just implementing ones own hooks.