IP packet handling issues in virtio-net on certain OS/kernel versions on KVM VM

Hi I am constantly using Suricata on KVM.
I installed a new OS to change the OS version of the VM, but Suricata encounters an unknown issue.

Problem:
When I configure the virtio-net interface as an af-packet pair and an IP packet is sent through that interface, no reply packet is returned to the client
In e1000 Ethernet, everything works normally.
There is a problem with IP packets in virtio-net, but ICMP works normally.

Environment
Host: Fedora 35 Kernel: 5.14.10-300.fc35.x86_64, qemu-6.1.0-10.fc35
Host: CentOS Stream 8 Kernel: 5.14.0-1.el8.elrepo.x86_64 qemu-6.0.0.-29.el8s
VM OS: Fedora 35, 36, Rocky9.0
Suricata: 6.0.6

Fedora 34 and Centos8 were normally used as Suricata VM OS. However, even if the same settings (apply all configs such as yaml) are applied in the OS where the problem occurs, IP packets do not work properly. Even after a lot of reinstallation, it still doesn’t work.
suricata.yaml (68.4 KB)
sysctl.rules (2.1 KB)

I don’t have an answer for you as I’ve never done this setup within KVM, but do have a few questions for more information that may help:

  • Which OS is your IPS VM? Fedora, or Rocky and if Fedora, which version? You list many, easier to focus in one one.
  • Which OS is your VM host machine? You list many, probably easier to focus in on one.

Your configuration file looks OK, so I’m thinking this might have more to do with the network setup of the hypervisor itself. Can you comment on how you do that?

I have done this type of setup with VirtualBox for testing. Where in my IPS VM I use either nat or bridged for the EXTERNAL interface, and then use a host-only adapter for the second interface which I consider INTERNAL. Then my protected VMs only have a host-only adapter. This gives a network scenario where the INTERNAL interface of the VM machine, and the network interfaces of the protected machines are on the same switch, without access to the internet unless the IPS machine bridges INTERNAL to EXTERNAL.

I’m not sure how I would do this on KVM. I have tried on Fedora as the VM host, but without a pre-configured interface like VirtualBox’s host-only, I haven’t had any success. Some custom network configuration is likely required on the VM host.

I document this is a bit here: VirtualBoxIpsTestSetup · jasonish/suricata Wiki · GitHub - you may also be interested in trying a more traditional Linux ethernet bridge between the 2 interfaces. That should tell you if your setup is correct without brining Suricata into the picture. This is also documented at the above link.

  1. IPS VM is Fedora 36. Host Machine is Fedora 35.

  2. Hypervisor configuration was performed using libvirtd, a VM management tool of KVM. The current configuration is the same as in Figure 1.

  3. The two interfaces used as af-packet pairs in Suricata VMs handle communication between the internal VMs, not the external internet, so only the internal interfaces are used.

  4. Result of packet response (SYN-ACK) according to vNIC from Suricata VM (client makes a request to HTTP server with curl and receives 200 OK response)

    linux bridge (Suricata Process Off)
    - virtio: Success
    - e1000: Sucess

    Suricata af-packet (linux bridge Off)
    - virtio: Fail
    - e1000: Sucess

The af-packet in Suricata VM configured with Fedora 36 on Hyper-V worked fine.
In addition, in very few cases, a packet response may come in virtio mode. However, there were a lot of retransmissions and it took a very long time to get a response. See Figure 3.


Fig. 1 Suricata VM Network Config


Fig. 2 VM/Network Diagram


Fig. 3 tcpdump capture from server

So it sounds like an issue with KVM and virtio? Probably worth further research to see if its something that can be supported.

I didn’t have much luck creating this myself. How did you define your test network? Specifically the one shared by the client and the Suricata VM?

The example attached above uses openvswitch, but the same problem occurs through switch, which is basically supported by kvm.
For a simple configuration example, I attach again.

test1 vSwitch

<network>
  <name>test1</name>
  <uuid>e06c0d8e-0fba-43e5-87bc-c5029aa8847e</uuid>
  <bridge name='virbr1' stp='on' delay='0'/>
  <mac address='52:54:00:04:41:2d'/>
</network>

test2 vSwitch

<network>
  <name>test2</name>
  <uuid>e06c0d8e-0fba-43e5-87bc-c5029aa8847a</uuid>
  <bridge name='virbr2' stp='on' delay='0'/>
  <mac address='52:54:00:04:41:2e'/>
</network>

image
Suricata VM Network Config (basic support switch)