Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ndpi integration #11671

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

cardigliano
Copy link
Contributor

Make sure these boxes are signed before submitting your Pull Request -- thank you.

Describe changes:

  • Add configure --enable-ndpi and --with-ndpi params to enable nDPI support and link the nDPI library
  • Add nDPI metadata export in alerts/netflow (Eve JSON)
  • Add ndpi-protocol keyword to match Layer-7 protocols detected by nDPI
  • Add ndpi-risk keyword to match flow risks detected by nDPI

lucaderi and others added 3 commits August 28, 2024 17:01
Add configure --enable-ndpi and --with-ndpi params
Add nDPI metadata export in alerts/netflow (Eve JSON)
Add ndpi-protocol signature match
Add ndpi-risk signature match
Copy link

NOTE: This PR may contain new authors.

Copy link

codecov bot commented Aug 28, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.74%. Comparing base (304271e) to head (de33b11).
Report is 135 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #11671      +/-   ##
==========================================
+ Coverage   82.61%   82.74%   +0.13%     
==========================================
  Files         919      912       -7     
  Lines      248997   249108     +111     
==========================================
+ Hits       205717   206135     +418     
+ Misses      43280    42973     -307     
Flag Coverage Δ
fuzzcorpus 60.80% <75.00%> (-0.08%) ⬇️
livemode 18.72% <37.50%> (+0.05%) ⬆️
pcap 44.09% <62.50%> (-0.06%) ⬇️
suricata-verify 62.16% <100.00%> (+0.26%) ⬆️
unittests 58.98% <5.88%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

@jasonish jasonish added the needs ticket Needs (link to) redmine ticket label Aug 28, 2024
@jasonish
Copy link
Member

Thanks for the submission. Could you please create a ticket that discusses this feature, the benefits, etc.

@cardigliano
Copy link
Contributor Author

Thanks for the submission. Could you please create a ticket that discusses this feature, the benefits, etc.

I created https://redmine.openinfosecfoundation.org/issues/7231

@jasonish jasonish removed the needs ticket Needs (link to) redmine ticket label Aug 29, 2024
@jufajardini jufajardini added the decision-required Waiting on deliberation from the team label Aug 30, 2024
@catenacyber
Copy link
Contributor

My big question is how could this work as a plugin ?
Leaving a few remarks in the code about this...

@@ -580,6 +580,10 @@ typedef struct Packet_
uint8_t *payload;
uint16_t payload_len;

#ifdef HAVE_NDPI
uint16_t ip_len;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can avoid to store this, and recompute it based on the total packet length and offset of ip header...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we'll want to get rid of additional #ifdef here as well for the move to a plugin.

@@ -503,6 +503,12 @@ typedef struct Flow_
uint64_t todstbytecnt;
uint64_t tosrcbytecnt;

#ifdef HAVE_NDPI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this somehow go into the storage section below ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps by using FlowStorageRegister and friends? Example usage in app-layer-expectation.c.

@@ -387,6 +387,41 @@ void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars
{
SCLogDebug("packet %"PRIu64" -- flow %p", p->pcap_cnt, f);

#ifdef HAVE_NDPI
if (tv->ndpi_struct && f->ndpi_flow && (!f->detection_completed) && (p->ip_len > 0)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we would need a hook here in FlowHandlePacketUpdate for every packet...

JsonBuilder *JsonBuildFileInfoRecord(
const Packet *p, const File *ff, void *tx, const uint64_t tx_id, const bool stored,
uint8_t dir, HttpXFFCfg *xff_cfg, OutputJsonCtx *eve_ctx
#ifdef HAVE_NDPI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could accept this for every case (even if it unused in most cases)

@@ -27,5 +27,8 @@
void JsonFlowLogRegister(void);
void EveAddFlow(Flow *f, JsonBuilder *js);
void EveAddAppProto(Flow *f, JsonBuilder *js);
#ifdef HAVE_NDPI
void EveAddnDPIProto(Flow *f, JsonBuilder *js, ThreadVars *tv);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused ?

@@ -135,6 +135,10 @@ typedef struct ThreadVars_ {
struct FlowQueue_ *flow_queue;
bool break_loop;

#ifdef HAVE_NDPI
struct ndpi_detection_module_struct *ndpi_struct;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I do not know about this one... (how we could make it work as a plugin)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could just use thread_local?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we delay initialization until first use, which would be in the packet path then?

I don't think a callback on thread creation would work, as in the library work a thread may be provided by the user, in which case some sort of callback with some user storage in the ThreadVar might make more sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with user data on ThreadVars. When/how to construct/destruct needs some thought. Do plugins have "thread init" callbacks? Where it would be called once per thread at init?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with user data on ThreadVars. When/how to construct/destruct needs some thought. Do plugins have "thread init" callbacks? Where it would be called once per thread at init?

No they do not, but this is what I was thinking we might need.

@@ -120,4 +120,7 @@ OutputJsonThreadCtx *CreateEveThreadCtx(ThreadVars *t, OutputJsonCtx *ctx);
void FreeEveThreadCtx(OutputJsonThreadCtx *ctx);
void JSONFormatAndAddMACAddr(JsonBuilder *js, const char *key, const uint8_t *val, bool is_array);

#ifdef HAVE_NDPI
void ndpiJsonBuilder(Flow *f, JsonBuilder *js, ThreadVars *tv);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we would need to hook into logging...

@lucaderi
Copy link

lucaderi commented Sep 4, 2024

My big question is how could this work as a plugin ? Leaving a few remarks in the code about this...

We are open to both a plugin and native support. The latter is the best IMHO as it enables all users to exploit it, but if a plugin is just a packaging detail fine for me.

Just let us know what we can do to expedite your decision as we would like to push additional features after this PR is likely merged.

Copy link
Member

@jasonish jasonish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some discussion on our side, we'd like to help where we can to make this a plugin a.s.a.p. This will require some work on our side as we don't have all the support required yet, but this PR does help identify where we need to provide the hooks.

On your end could you:

  • see about using thread local storage
  • remove the additional fields from the header and see about using the storage apis
  • register and ndpi feature so rules can conditinally use this

On our side we'll closely review this for the hooks that are needed and prepare a PR from our side.

I think this would be a plugin we'll bundle with Suricata though, so the user experience won't be much different than it is with this PR.

@lucaderi
Copy link

Hi @jasonish do you have some updates to share? We're ready to move forward with the plugin development as soon as you're ready. Thanks

Copy link
Contributor

@jufajardini jufajardini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had some minor comments that for some reason were pending since forever 😓

Comment on lines +82 to +85
#ifdef HAVE_NDPI

static void ndpiJsonBuilderTLSQUIC(Flow *f, JsonBuilder *js, ThreadVars *tv)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move these ndpi-related changes to their own file?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: naming convention: s/n/N ?

ndpi_set_protocol_detection_bitmask2(tv->ndpi_struct, &protos);
ndpi_finalize_initialization(tv->ndpi_struct);

/* printf("%s - ndpi_init_detection_module()\n", __FUNCTION__); */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is keeping these necessary? If yes, couldn't they be changed to SCLogDebug statements?

- Self-signed Certificate
- Susp DGA Domain name
- Malware host contacted
- and many other...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Should we add any a reference here for what was consulted to define those and where people could check them, or isn't this necessary?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +79 to +81
SCLogDebug("ndpi protocol match on protocol = %u.%u (match %u)",
f->detected_l7_protocol.app_protocol, f->detected_l7_protocol.master_protocol,
data->l7_protocol);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compile error here:

detect-ndpi-protocol.c: In function ‘DetectnDPIProtocolPacketMatch’:
detect-ndpi-protocol.c:80:40: error: ‘ndpi_protocol’ {aka ‘const struct ndpi_proto’} has no member named ‘app_protocol’
   80 |                 f->detected_l7_protocol.app_protocol, f->detected_l7_protocol.master_protocol,
      |                                        ^

/**********************************Unittests***********************************/

#ifdef UNITTESTS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These unit tests below also fail to compile.

Copy link
Member

@jasonish jasonish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lucaderi @cardigliano Can we get a rebase that builds against current nDPI, or a specific version of nDPI?

@jasonish
Copy link
Member

Linker error.. When I build Suricata with ./configure --enable-ndpi --with-ndpi=/home/jason/src/nDPI, it fails to link:

/usr/bin/ld: /home/jason/src/nDPI/src/lib/libndpi.a(ndpi_main.o): in function `ndpi_handle_rule.isra.0':
ndpi_main.c:(.text+0xaef3): undefined reference to `nbpf_parse'
/usr/bin/ld: /home/jason/src/nDPI/src/lib/libndpi.a(ndpi_main.o): in function `ndpi_exit_detection_module':
ndpi_main.c:(.text+0x11d99): undefined reference to `nbpf_free'
/usr/bin/ld: /home/jason/src/nDPI/src/lib/libndpi.a(ndpi_main.o): in function `ndpi_detection_process_packet':
ndpi_main.c:(.text+0x14d58): undefined reference to `nbpf_match'

this appears to be linking against the .a static library. Probably because I use --disable-shared. It works against the shared library. Is there a known reason why?

@lucaderi
Copy link

I believe you have built nDPI with nBPF support and the nBPF library was not used during linking. I think you have /home/jason/PF_RING/userland/nbpf/libnbpf.a but that was not used during linking.
Just delete libnbpf.a and rebuild nDPi and it will work

@jasonish
Copy link
Member

@lucaderi @cardigliano Its still needs much review, but here's what I'm thinking for the support required for nDPI to be a plugin, including a stub plugin that shows off the call backs and user storage for threads and flows.

#11944

@jasonish
Copy link
Member

I believe you have built nDPI with nBPF support and the nBPF library was not used during linking. I think you have /home/jason/PF_RING/userland/nbpf/libnbpf.a but that was not used during linking. Just delete libnbpf.a and rebuild nDPi and it will work

Yeah, it picked up some older pfring install from /usr/local. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
decision-required Waiting on deliberation from the team
Development

Successfully merging this pull request may close these issues.

6 participants