Adding new protocol to suricata with rust

Hello, is there any guide lines for adding a new parser to Suricata with rust ? I was trying to add a very easy protocol ( the DIS protocol ) but i don’t have any clue about where i need to start from ( for now i have installed rust and i was trying to understeand some of the parser already done ). The protocol it’s very easy infact is and UDP type with brodcast message so i don’t think will be a big deal from that point. If someone can expalin me from where i can start it’s a big help. Thanks in advance ^.^

1 Like

Hi Robullo!
Welcome to our forum! :slight_smile:
We are hosting a webinar on 25th Feb in which one of our current interns will be sharing their experience and some tips about this. In case this interests you, please register: Webinar - A Beginner's Guide to Adding New Features to Suricata Tickets, Thu, Feb 25, 2021 at 7:30 AM | Eventbrite

You could also pick up your favorite protocol parser in Rust and check the closed pull requests corresponding to that on our GitHub. It’ll be easy to see what changed in the C side and how did the development take place in steps.

3 Likes

Hey Robullo! I’m Juliana, who spoke about adding initial PostgreSQL support to Suricata (in Rust), in the webinar Shivani mentioned. I remember someone asked during the webinar if we could offer a more detailed explanation on how to add a new protocol to Suricata. I’m in the process of writing an about that here on the forum, most likely. Would you like to share any questions you’d like to see answered, with that entry post?

1 Like

hello Juliana! First of all, I really enjoyed the webinar. Thanks to your intervention I understood which are the files to create and which to modify. My only doubts at the moment are about “app-layer - *. C and .h” in these two files I should describe how Suricata has to call the functions created in the rust files right?

1 Like

Thanks, and I’m glad to hear that! So, I’m implementing PostgreSQL using the py script, as I’ve mentioned, so those files were also generated with it. But your reasoning is correct, and in simple cases, basically one has to define a function that calls the rust binding to registering the parser, and the one for the unittests, and that’s it.

app-layer-krb5.c and app-layer-krb5.h, are like that, for instance.

1 Like

Thanks for all ^_^. From now on i will try to implement it as best i can do. One last question, for debugging i use “Trace” like the SCLogDebug function ??

You are most welcome! I’m not sure I get your question, can you be more specific? Do you want to know if you can use SCLogDebug level for debugging, or something else?

Oh sorry if i wasn’t clear. I just want know the best metodh for debug at runtime. If im not wrong i think the function SCLogDebug can be really usefull, am i right ?? btw im really happy that you answered all my doubts.

1 Like

It’s ok, communicating can be tricky sometimes :stuck_out_tongue: Yes, it can, from what I was explained, you could also go with SCLogNotice!, which will always show, and once you’re done with debugging you could then delete the unnecessary ones, or change them to Debug level. I also really like to have the unittests, for some cases, because then I don’t even have to run suricata, to check how specific functions work.

(It’s also nice to be able to offer some help! Happy coding! ^^ )

1 Like

Hi, i have some new about the parser. It’s seem to work when i start suricata in pcap offline mode. But when i go in live mode Suricata can understeand only once ( i explain better this part ). If i start the comunication between a server and a client Suricata recognize the new protocol implemented on the specific port, when the server and client stop comunication and make a new one it’s seems that the parser is never re-called and so i feel that Suri it’s blind. It’s possible that i need to tell to Suricata how to enable again the parser ? Also i find that when Suricata end to recognize the end of the comunication between the client and the server, write this json in the eve.json:

{“timestamp”:“2021-03-18T18:06:26.150325+0100”,“flow_id”:2088039287448777,
“in_iface”:“netmap:suricata”,“event_type”:“flow”,“src_ip”:“192.168.1.102”,
“src_port”:55137,“dest_ip”:“192.168.1.50”,“dest_port”:6662,“proto”:“TCP”,
“app_proto”:“hl7”,“flow”:{“pkts_toserver”:40,“pkts_toclient”:21,
“bytes_toserver”:17423,“bytes_toclient”:3378,
“start”:“2021-03-18T18:04:01.025801+0100”,“end”:“2021-03-18T18:04:02.155417+0100”,
“age”:1,“state”:“closed”,“reason”:“unknown”,“alerted”:false},
“tcp”:{“tcp_flags”:“1b”,“tcp_flags_ts”:“1b”,“tcp_flags_tc”:“1b”,
“syn”:true,“fin”:true,“psh”:true,“ack”:true,“state”:“closed”}}

Have you looked at our DHCP parser? I recommend taking a look at that as its UDP, and also processes broadcast type messages. One of the issues with DHCP is there is no real session end, at least for the broadcast messages. As they’re generally from the same src/dst and same ports. So its timeouts that determine when a session ends/starts, and this behaviour is going to be different on the wire or pcaps, but shouldn’t be that much different.

Also, did you start your parser with the app-layer-setup script?

Hi Jason, yes i started my parser with the app-layer-setup, but this behaviour that you explained it’s also valid for a TCP connection ? in my case if you see the trace from the eve.json it’s concerne a TCP connection between the two hosts. Btw thx i will check what you pointed. :slight_smile:

So you get a flow entry for each TCP session? But your parser is only invoked for the first one?

Yes only the frist time. =(