sip monitor: or where do i plug my sniffer in?

J
jrun
Wed, Feb 13, 2019 4:09 PM

hello,

i have been asked to rewrite an in house sip monitoring software that was
developed in-house years ago. it does some simple libcap filtering to capture
traffic to and from asterisk (ast) and does some primitive calculation on
interarrival jitter, only. briefly, it's useless.

ideally i would like to build something that would capture the packets in and
out of the ast, and do, possibly high resolution, analysis on rtp streams.

in more detail, on captured packets, if sip, save the transaction/dialogues to a
database, keeping track of send/recv under the same obj in the db then if
dialogues results rtp streams to be sent back and forth, find the pertaining
dialogue in the db, link the streams to the dialogues, and keep track of
rtp/rtcp analysis on the actual calls (following rfc3550's recommendations).

considering rewriting from scratch what's in place, and noticing that newer
versions of ast do this already, lead me to pjsip which has lots of the above
already done-for-you with a clean interface. i've been reading up on
PJSIP-Dev-Guide and looking at the code itself plus test and sample codes and it
seems to me there might be a way to plug into pjsip's stack to do what i have in
mind. as a matter of fact it's already, somewhat, done in ast itself à la
res_pjsip_history. extending that module to send it's data to some monitoring
server (i believe it only keeps its db in mem) is an option. however for older
installed bases that is no solution. and also it is baked into ast, the idea is
to have an out-of-band monitoring to eliminate any extra load on ast itself.

my thinking at the moment, keep in mind that i have a primitive understanding of
pjsip and sip protocol itself in general, leads into couple of problems and the
following questions which i would like to pick you brain about them, if i may.

1

  • is there a way to feed packets to pjlibs I/O queue without binding the library
    to an actual network interface on the machine? regardless of whether
    monitoring process is running on the same machine as ast or not this is a
    required, since either way there will be a sniffer (libpcap or what have you)
    is involved at some point because former will not be able to hug the same
    addr:port as ast and latter will require parsing packets that are not meant
    for the monitoring server (for example packets are mirrored at some point on
    their way to ast and sent to the monitoring server). that is unless you have
    another idea for this...

    one solution i have thought of is using IPC, say a unix socket, to to plug the
    pjlib into and then send sniffed packets over that socket.
    what do you think? any idea?

    in any case this seems to requires extending pjsip_transport, would that be a
    reasonable assumption? i don't see it being implemented anywhere; pointers are
    welcome though.

    speaking of pointers, are sip_transport_loop.c, transport_adapter_sample.c and
    pjlib-test/ioq_udp.c relavent here? i have looked at them but still there are
    too many knobs to use, the kid is lost in the candy store.

2

  • say there is a solution to problem #1 and i manage to feed packets to ioqueue,
    what's next? this is where i need to know where to plug my module in. i
    definitely would want to take advantage of sip_parse.c plus transaction and/or
    dialog hash table. i seems to me that i can use one of those tables to merge
    rtp and sip dialogues together so they can be later looked up (the way
    res_pjsip_history does for example). what i really would like to know is what
    parts are done-for-me? my guess is none. transport for instance will not be
    initiated, that i read in the dev guide, but once i have some sort of adaptor,
    does the parsing, the lookups in tsx/dlg tables and so on are done regardless
    before things are handed to my module? or do i need to come in at each layer
    and do it myself?

3

  • while #2 is more on the rx side of things 3 is about tx. there will be packets
    coming out of the actual pbx and those need to be linked with the relavent rx
    ones. this i have no idea how to go about but i suspect solutions to 1 and 2
    will shed some light on this. in the mean time if there is any idea jumping
    out of you please let me know.

4

  • this is misc category if you like. with my limited knowledge here i am certain
    that there are pitfalls down the line that i am oblivion to. comments that
    are rushing to your mind and are the result out of your insight into pjsip and
    sip in general are priceless and welcomed and hopefully will go here :)

jrun

hello, i have been asked to rewrite an in house sip monitoring software that was developed in-house years ago. it does some simple libcap filtering to capture traffic to and from asterisk (ast) and does some primitive calculation on interarrival jitter, only. briefly, it's useless. ideally i would like to build something that would capture the packets in and out of the ast, and do, possibly high resolution, analysis on rtp streams. in more detail, on captured packets, if sip, save the transaction/dialogues to a database, keeping track of send/recv under the same obj in the db then if dialogues results rtp streams to be sent back and forth, find the pertaining dialogue in the db, link the streams to the dialogues, and keep track of rtp/rtcp analysis on the actual calls (following rfc3550's recommendations). considering rewriting from scratch what's in place, and noticing that newer versions of ast do this already, lead me to pjsip which has lots of the above already done-for-you with a clean interface. i've been reading up on PJSIP-Dev-Guide and looking at the code itself plus test and sample codes and it seems to me there might be a way to plug into pjsip's stack to do what i have in mind. as a matter of fact it's already, somewhat, done in ast itself à la res_pjsip_history. extending that module to send it's data to some monitoring server (i believe it only keeps its db in mem) is an option. however for older installed bases that is no solution. and also it is baked into ast, the idea is to have an out-of-band monitoring to eliminate any extra load on ast itself. my thinking at the moment, keep in mind that i have a primitive understanding of pjsip and sip protocol itself in general, leads into couple of problems and the following questions which i would like to pick you brain about them, if i may. 1 - is there a way to feed packets to pjlibs I/O queue without binding the library to an actual network interface on the machine? regardless of whether monitoring process is running on the same machine as ast or not this is a required, since either way there will be a sniffer (libpcap or what have you) is involved at some point because former will not be able to hug the same addr:port as ast and latter will require parsing packets that are not meant for the monitoring server (for example packets are mirrored at some point on their way to ast and sent to the monitoring server). that is unless you have another idea for this... one solution i have thought of is using IPC, say a unix socket, to to plug the pjlib into and then send sniffed packets over that socket. what do you think? any idea? in any case this seems to requires extending pjsip_transport, would that be a reasonable assumption? i don't see it being implemented anywhere; pointers are welcome though. speaking of pointers, are sip_transport_loop.c, transport_adapter_sample.c and pjlib-test/ioq_udp.c relavent here? i have looked at them but still there are too many knobs to use, the kid is lost in the candy store. 2 - say there is a solution to problem #1 and i manage to feed packets to ioqueue, what's next? this is where i need to know where to plug my module in. i definitely would want to take advantage of sip_parse.c plus transaction and/or dialog hash table. i seems to me that i can use one of those tables to merge rtp and sip dialogues together so they can be later looked up (the way res_pjsip_history does for example). what i really would like to know is what parts are done-for-me? my guess is none. transport for instance will not be initiated, that i read in the dev guide, but once i have some sort of adaptor, does the parsing, the lookups in tsx/dlg tables and so on are done regardless before things are handed to my module? or do i need to come in at each layer and do it myself? 3 - while #2 is more on the rx side of things 3 is about tx. there will be packets coming out of the actual pbx and those need to be linked with the relavent rx ones. this i have no idea how to go about but i suspect solutions to 1 and 2 will shed some light on this. in the mean time if there is any idea jumping out of you please let me know. 4 - this is misc category if you like. with my limited knowledge here i am certain that there are pitfalls down the line that i am oblivion to. comments that are rushing to your mind and are the result out of your insight into pjsip and sip in general are priceless and welcomed and hopefully will go here :) - jrun
J
jrun
Thu, Feb 21, 2019 6:32 PM

pjsip/src/pjsip/sip_transport_udp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pjsip/src/pjsip/sip_transport_udp.c b/pjsip/src/pjsip/sip_transport_udp.c
index dbda474c..669e8256 100644
--- a/pjsip/src/pjsip/sip_transport_udp.c
+++ b/pjsip/src/pjsip/sip_transport_udp.c
@@ -622,7 +622,7 @@ static void udp_set_pub_name(struct udp_transport *tp,
pj_sockaddr_print(&tp->base.local_addr, local_addr, sizeof(local_addr), 3);
pj_addr_str_print(&tp->base.local_name.host,
tp->base.local_name.port,

  •         pub_addr, sizeof(pub_addr), 1),
    
  •         pub_addr, sizeof(pub_addr), 1);
    

    pj_ansi_snprintf( tp->base.info, INFO_LEN, "udp %s [published as %s]",
    local_addr, pub_addr);
    --
    -jrun

--- pjsip/src/pjsip/sip_transport_udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pjsip/src/pjsip/sip_transport_udp.c b/pjsip/src/pjsip/sip_transport_udp.c index dbda474c..669e8256 100644 --- a/pjsip/src/pjsip/sip_transport_udp.c +++ b/pjsip/src/pjsip/sip_transport_udp.c @@ -622,7 +622,7 @@ static void udp_set_pub_name(struct udp_transport *tp, pj_sockaddr_print(&tp->base.local_addr, local_addr, sizeof(local_addr), 3); pj_addr_str_print(&tp->base.local_name.host, tp->base.local_name.port, - pub_addr, sizeof(pub_addr), 1), + pub_addr, sizeof(pub_addr), 1); pj_ansi_snprintf( tp->base.info, INFO_LEN, "udp %s [published as %s]", local_addr, pub_addr); -- -jrun