Products > Embedded Computing

Running a web server on an embedded system - risky?

<< < (7/7)

DiTBho:
the mysteries of outer space ... what rides packets on the internet these days.

peter-h:
What kind of "firewall" feature is common on embedded products these days?

Mine has LWIP on it. ETH uses the STM code, where the dedicated DMA controller moves data into RAM buffers. One "hopes" that the DMA length is set to not overflow the buffer ;)

The plan is to put in a feature whereby a list of IPs can be permitted. This could get quite complicated though if you also want to allow IPs with masks, etc. Maybe some code already exists but my worry is that all this stuff is so buggy. I have a part-time guy doing the ETH side and I reckon he spent a few months fixing bugs in the ST code. Then a few more months fixing MbedTLS.

Nominal Animal:

--- Quote from: peter-h on November 16, 2021, 10:36:11 am ---What kind of "firewall" feature is common on embedded products these days?
--- End quote ---
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.


--- Quote from: peter-h on November 16, 2021, 10:36:11 am ---The plan is to put in a feature whereby a list of IPs can be permitted.
--- End quote ---
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.

peter-h:
This is super useful info - many thanks!

Yes it needs to be just stateless. It is just to prevent crude hacking. Nobody will be attacking this product, but somebody could well try attacking the whole class of products containing a widely used code library.

Navigation

[0] Message Index

[*] Previous page

There was an error while thanking
Thanking...
Go to full version