While my employment has drawn me away from development work and work in the industrial automation space, I have continued to work on a number of smaller projects related to the open source IEC 61131-3 Virtual Machine. One such project has been the development of a Modbus application protocol network filter for the Linux kernel.
While a Modbus filter for Linux has made available by Venkat Pothamsetty and Matthew Franz previously and provided for download from Sourceforge. The most recent version of this code dated from 2004 however was written for Linux kernel 2.6.16 and no longer compiles against recent Linux kernel versions. To this end, this new filter match module for Modbus has been written and includes Modbus frame matching features beyond that available in the previous work by Pothamsetty and Franz.
This new Modbus filter kernel module – and corresponding patch for iptables 1.6, required in order to allow the specification and manipulation of firewall rules using Modbus protocol nomenclature – can be found at https://bitbucket.org/rob_au/modbusfw/.
With this Modbus kernel filter module installed, extended packet matching can be specified using iptables with the -m or –match options, following my the protocol match name “modbus“. It is using this extended packet matching mechanism that Modbus specific filtering rules can defined based upon Modbus frame fields:
[!] --id transaction[:transaction] Transaction or invocation identifier(s) [!] --prot protocol Protocol identifier [!] --len length Frame length [!] --unit addr[:addr] Unit identifier(s) [!] --fc function[:function] Function code(s) [!] --reg register[:register] Register(s)
Using these match extension, Modbus network filtering rules similar to the following can be established:
# Drop all requests with protocol identifier other than zero (Modbus) iptables -I INPUT -p tcp -m tcp --dport 502 -m modbus ! --prot 0 -j DROP # Drop all requests except those directed to Modbus device 7 iptables -I INPUT -p tcp -m tcp --dport 502 -m modbus ! --unit 7 -j DROP # Allow read holding register requests for registers 1-100 iptables -I INPUT -p tcp -m tcp --dport 502 -m modbus --fc 3 --reg 1:100 -j ACCEPT