The solution I have settled on (for now) is a simple packet filter using iptables. I think a better solution would be an IDS such as Snort (www.snort.org) but Intrusion Detection is outside my current area of expertise.
I am posting my code just in case someone else wants to try this. First I tried a whitelisting approach:
iptables -N Inverter 2>/dev/null
iptables -A FORWARD -i eth0 -o wlan1 -d 10.42.0.219 -j Inverter
iptables -A Inverter -p tcp --dport 8899 -j ACCEPT
iptables -A Inverter -p tcp --tcp-flags ACK,PSH ACK -j ACCEPT
iptables -A Inverter -p tcp -m length --length 40:80 -j ACCEPT
iptables -A Inverter -p tcp -j LOG --log-level info --log-prefix "GivEnergy "
iptables -A Inverter -p tcp -j DROP
which works, but prevents the dongle from reconnecting. So when I try to change a setting in the portal, it fails with Inverter Timeout (as it should) and the portal drops the connection. Then the dongle sits flashing because to reconnect it needs to get data from the server which the filter prevents from happening.
So I have switched to a blacklisting approach which blocks modbus packets with the 06 (write single register) function code.
iptables -N Inverter 2>/dev/null
iptables -N Blacklist 2>/dev/null
iptables -A FORWARD -i eth0 -o wlan1 -d 10.42.0.219 -j Inverter
iptables -A Inverter -p tcp --dport 8899 -j ACCEPT
iptables -A Inverter -p tcp -m length --length 40:80 -j ACCEPT
iptables -A Inverter -p tcp -m u32 -–u32 “50&0xFFFF=0x5959 && 76&0xff=6” -j Blacklist
iptables -A Blacklist -j LOG --log-level info --log-prefix "GivEnergy "
iptables -A Blacklist -j DROP
This blocks register changes correctly, but will probably be ineffective against other changes such as a firmware update.
Suggestions for improvements very welcome.