Bug #9006
opentype: ip dataset rejects standard IPv4 addresses
Description
type: ip dataset rejects standard IPv4 addresses¶
Environment¶
Suricata 8.0.6
OPNsense 26.7
FreeBSD 15.1
Problem¶
The ip dataset type is documented to support both IPv4 and IPv6 addresses.
Source:
https://docs.suricata.io/en/suricata-8.0.6/rules/datasets.html#data-types
The documentation states:
8.49.5. File formats Datasets use a simple CSV format where data is per line in the file. 8.49.5.1. data types ipv4 in the file as string ip in the file as string, it can be IPv6 or IPv4 address (standard notation or IPv4 in IPv6 one)
However, a file-backed type: ip dataset rejects standard IPv4 notation.
Dataset configuration:
datasets:
tortest:
type: ip
load: /usr/local/etc/suricata/test-tor.list
Dataset file, aka /usr/local/etc/suricata/test-tor.list:
1.1.1.1 8.8.8.8
Running:
suricata -T -c /usr/local/etc/suricata/suricata.yaml
does not print the dataset error to the terminal. The error is logged in:
/var/log/suricata/latest.log
The log contains:
invalid Ipv6 value tortest in /usr/local/etc/suricata/test-tor.list
The exact same file works correctly when using:
type: ipv4
Relevant code¶
In Suricata 8.0.6, process_ipv6_set() parses the dataset entry using Ipv6Addr::from_str():
https://raw.githubusercontent.com/OISF/suricata/suricata-8.0.6/rust/src/detect/datasets.rs
let ipv6 = match Ipv6Addr::from_str(v[0]) {
Therefore, standard IPv4 input such as 1.1.1.1 is rejected as an IPv6 address before it can be handled as IPv4.
The same function does explicitly handle IPv4-mapped IPv6 addresses such as:
::ffff:1.1.1.1
using to_ipv4_mapped().
This appears inconsistent with the documented behavior of the ip dataset type, which is supposed to accept both IPv4 and IPv6 addresses.
C implementation¶
The corresponding C implementation in Suricata 8.0.6 appears to handle both IPv6 and standard IPv4 input in DatasetParseIpv6String():
https://raw.githubusercontent.com/OISF/suricata/suricata-8.0.6/src/datasets.c
It distinguishes IPv6 and IPv4 input and uses inet_pton(AF_INET6, ...) for IPv6 and inet_pton(AF_INET, ...) for standard IPv4.
This appears to indicate that the current Rust dataset parser does not preserve the previous behavior for standard IPv4 input when processing a dataset of type ip.
Expected behavior¶
The following should load successfully with type: ip:
1.1.1.1 8.8.8.8
Actual behavior¶
Standard IPv4 addresses are rejected as invalid IPv6 values:
invalid Ipv6 value tortest in /usr/local/etc/suricata/test-tor.list
The ipv4 dataset type works correctly with the same IPv4 input.
Note¶
Sorry if I made any mistakes in this report. I used some help from ChatGPT while working on this late at night and being quite tired, but I also checked the relevant documentation, source code, and behavior myself.
I am not very familiar with Rust syntax, so it is possible that I may be misunderstanding something in the process_ipv6_set() implementation. If I have misunderstood the code or the intended behavior, please feel free to correct me.
Thanks a lot for taking the time to look into this and for all the work on Suricata!
Greetings from Switzerland