Project

General

Profile

Actions

Bug #7454

open

Inconsistent behavior for ftp rules

Added by Antonin Bas 10 days ago.

Status:
New
Priority:
Normal
Assignee:
Target version:
Affected Versions:
Effort:
Difficulty:
Label:

Description

I am trying to allow FTP traffic only for a tenant. My (limited) understanding is that the following rules should do the trick:

reject ip any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/egress-allow-ftp"; flow: to_server, established; sid: 1;)
pass ftp-data any any -> any any (msg: "Allow ftp-data by AntreaNetworkPolicy:default/egress-allow-ftp"; sid: 2;)
pass ftp any any -> any any (msg: "Allow ftp by AntreaNetworkPolicy:default/egress-allow-ftp"; sid: 3;)

However, I have observed some inconsistent behavior at runtime when trying to download a file over FTP, with a command such as

curl -u user:123 ftp://10.10.2.5/1.txt

Sometimes (rarely) the command succeeds. Most of the time the connection gets reset (presumably by Suricata since everything works without the rules) after a few packets.
I am not sure why sometimes it succeeds, maybe because of some lucky timing.

To understand the problem further, I took a packet capture of my FTP traffic (without Suricata running), and the pcap is attached. I am showing the first few packets here for convenience:

15:49:54.898968 IP 10.10.1.3.43452 > 10.10.2.5.ftp: Flags [S], seq 958067332, win 64860, options [mss 1410,sackOK,TS val 3098977097 ecr 0,nop,wscale 7], length 0
15:49:54.903716 IP 10.10.2.5.ftp > 10.10.1.3.43452: Flags [S.], seq 1381416639, ack 958067333, win 64308, options [mss 1410,sackOK,TS val 2432257073 ecr 3098977097,nop,wscale 7], length 0
15:49:54.903893 IP 10.10.1.3.43452 > 10.10.2.5.ftp: Flags [.], ack 1, win 507, options [nop,nop,TS val 3098977101 ecr 2432257073], length 0
15:49:54.907422 IP 10.10.2.5.ftp > 10.10.1.3.43452: Flags [P.], seq 1:17, ack 1, win 503, options [nop,nop,TS val 2432257078 ecr 3098977101], length 16: FTP: 220 FTP Server
15:49:54.907510 IP 10.10.1.3.43452 > 10.10.2.5.ftp: Flags [.], ack 17, win 507, options [nop,nop,TS val 3098977105 ecr 2432257078], length 0
15:49:54.907658 IP 10.10.1.3.43452 > 10.10.2.5.ftp: Flags [P.], seq 1:12, ack 17, win 507, options [nop,nop,TS val 3098977105 ecr 2432257078], length 11: FTP: USER user
15:49:54.907836 IP 10.10.2.5.ftp > 10.10.1.3.43452: Flags [.], ack 12, win 503, options [nop,nop,TS val 2432257078 ecr 3098977105], length 0
15:49:54.907945 IP 10.10.2.5.ftp > 10.10.1.3.43452: Flags [P.], seq 17:51, ack 12, win 503, options [nop,nop,TS val 2432257078 ecr 3098977105], length 34: FTP: 331 Please specify the password.
15:49:54.908105 IP 10.10.1.3.43452 > 10.10.2.5.ftp: Flags [P.], seq 12:22, ack 51, win 507, options [nop,nop,TS val 3098977106 ecr 2432257078], length 10: FTP: PASS 123
15:49:54.949660 IP 10.10.2.5.ftp > 10.10.1.3.43452: Flags [.], ack 22, win 503, options [nop,nop,TS val 2432257120 ecr 3098977106], length 0
...

After taking the capture, I ran Suricata in offline mode, on my pcap:

root@353df7c5a170:/# suricata -r src/ftp.pcap -S src/ftp.rules
Info: conf-yaml-loader: Including configuration file /etc/suricata/antrea.yml.
Info: conf-yaml-loader: Configuration node 'outputs' redefined.
i: suricata: This is Suricata version 7.0.7 RELEASE running in USER mode
W: counters: stats are enabled but no loggers are active
i: threads: Threads created -> RX: 1 W: 8 FM: 1 FR: 1   Engine started.
i: suricata: Signal Received.  Stopping engine.
i: pcap: read 1 file, 37 packets, 2841 bytes

And this is the first event in the JSON file:

{"timestamp":"2024-12-11T23:49:54.907510+0000","flow_id":764813614361772,"pcap_cnt":5,"event_type":"alert","src_ip":"10.10.1.3","src_port":43452,"dest_ip":"10.10.2.5","dest_port":21,"proto":"TCP","pkt_src":"wire/pcap","alert":{"action":"blocked","gid":1,"signature_id":1,"rev":0,"signature":"Reject by AntreaNetworkPolicy:default/egress-allow-ftp","category":"","severity":3},"direction":"to_server","flow":{"pkts_toserver":3,"pkts_toclient":2,"bytes_toserver":206,"bytes_toclient":156,"start":"2024-12-11T23:49:54.898968+0000","src_ip":"10.10.1.3","dest_ip":"10.10.2.5","src_port":43452,"dest_port":21},"packet":"9raZVAw5Iu7C8LElCABFAAA0O2hAAEAG6EAKCgEDCgoCBam8ABU5GvKFUla+0IAQAfs91gAAAQEICri2o1GQ+Uw2","packet_info":{"linktype":1}}

For some reason, the 5th packet (empty ACK from client to server) is being blocked by Suricata (and I assume a RST packet will be generated due to the use of the reject action).

While I can somewhat make sense of this behavior (this is an empty TCP packet so maybe theoretically not a FTP control packet, and it is blocked by the default reject rule?), it doesn't really make sense to me: 1) it makes FTP rules hard to use in my case, and more importantly 2) I have never observed this behavior with an "equivalent" HTTP rule .
The fact that the runtime behavior (real deployment, not offline mode) is also not always consistent is confusing to me.

For what it's worth I have tried adding --runmode=single to the offline command, and it didn't change the behavior.


Files

ftp.pcap (3.38 KB) ftp.pcap Antonin Bas, 12/12/2024 12:20 AM

No data to display

Actions

Also available in: Atom PDF