Re: [PATCH] netfilter: nf_nat_sip: fix RTP/RTCP source port translations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Dec 11, 2018 at 6:41 AM Alin Năstac <alin.nastac@xxxxxxxxx> wrote:
>
> Hi Pablo.
>
> On Tue, Dec 11, 2018 at 1:14 AM Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> wrote:
> >
> > Hi Alin,
> >
> > On Tue, Nov 27, 2018 at 10:09:20AM +0100, Alin Nastac wrote:
> > > Perform the same SNAT translation on RTP/RTCP conntracks regardless of
> > > who sends the first datagram.
> > >
> > > Prior to this change, RTP packets send by the peer who required source
> > > port translation were forwarded with unmodified source port when this
> > > peer started its voice/video stream first.
> >
> > Copying and pasting your more detailed description for reference (from
> > your previous email here. BTW, no problem about long descriptions,
> > specifically for helper patches).
>
> Communication skill is not my strong point... ;-P
>
> >
> > Alin Nastac said:
> > > The scenario fixed by this patch involves a regular SIP call, but
> > > one that requires port translation for the RTP conntrack. For
> > > instance, suppose you have 2 SIP agents in the LAN, both connected
> > > to the same SIP proxy:
> > >   - agent S1  starts first and its REGISTER phase will create a
> > >   permanent expected conntrack on dport 5060 for allowing SIP
> > >   packets to be forwarded to S1 regardless of their source IP
> > >   address or port
> > >   - on agent S2  registration, its permanent expected conntrack will
> > >   confict with the S1 signalling expected conntrack, so it will be
> > >   translated to port 1024
> > >
> > > When S1 initiates a call using RTP/RTCP port range 1024-1025, SIP
> > > helper will find that port 1024 is taken over by S2's signalling
> > > expected conntrack, so it translates it to port range 1026-1027. All
> > > goes well if the RTP conntrack is initiated by a packet originated
> > > from the SIP proxy, but when the first RTP packet is sent by S1
> > > (usually the peer that initiates the call is the one that sends the
> > > first RTP packet), it is sent towards SIP proxy with unmodified
> > > source port (1024 iso 1026).
> > -- end of quote --
> >
> > Please, see my comments below.
> >
> > > Signed-off-by: Alin Nastac <alin.nastac@xxxxxxxxx>
> > > ---
> > >  net/netfilter/nf_nat_sip.c | 35 +++++++++++++++++++++++++++++++----
> > >  1 file changed, 31 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c
> > > index 1f30860..a1e23cc 100644
> > > --- a/net/netfilter/nf_nat_sip.c
> > > +++ b/net/netfilter/nf_nat_sip.c
> > > @@ -18,6 +18,7 @@
> > >
> > >  #include <net/netfilter/nf_nat.h>
> > >  #include <net/netfilter/nf_nat_helper.h>
> > > +#include <net/netfilter/nf_conntrack_core.h>
> > >  #include <net/netfilter/nf_conntrack_helper.h>
> > >  #include <net/netfilter/nf_conntrack_expect.h>
> > >  #include <net/netfilter/nf_conntrack_seqadj.h>
> > > @@ -316,6 +317,9 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
> > >  static void nf_nat_sip_expected(struct nf_conn *ct,
> > >                               struct nf_conntrack_expect *exp)
> > >  {
> > > +     struct nf_conn_help *help = nfct_help(ct->master);
> > > +     struct nf_conntrack_expect *pair_exp;
> > > +     int range_set_for_snat = 0;
> > >       struct nf_nat_range2 range;
> > >
> > >       /* This must be a fresh one. */
> > > @@ -327,15 +331,38 @@ static void nf_nat_sip_expected(struct nf_conn *ct,
> > >       range.min_addr = range.max_addr = exp->saved_addr;
> > >       nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
> > >
> > > -     /* Change src to where master sends to, but only if the connection
> > > -      * actually came from the same source. */
> > > -     if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
> > > +     /* Do SRC manip according with the parameters found in the
> > > +      * paired expected conntrack. */
> > > +     spin_lock_bh(&nf_conntrack_expect_lock);
> > > +     hlist_for_each_entry(pair_exp, &help->expectations, lnode) {
> > > +             if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) &&
> > > +                 pair_exp->tuple.dst.protonum == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum &&
> > > +                 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &pair_exp->saved_addr) &&
> > > +                 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == pair_exp->saved_proto.all) {
> >
> > Let me rephrase the scenario with my own words, I'm assuming that:
> >
> > #1 S1 agent creates expectation via REGISTER: SIP proxy (SP) -> S1.
> >    using dport 5060 for the expectation.
> > #2 S2 agent creates expectation via REGISTER: SP -> S2 with dport 1024
> >    for the expectation.
> > #3 S1 creates expectation via INVITE to SP: SP -> S1 for RTP/RCTP traffic.
> >    As you said "all goes well if RTP conntrack is initiated by a
> >    packet originated from the SP", which makes sense since this
> >    traffic matches the expectation.
> > #4 However, if first RTP packet is coming from S1, it does not match
> >    any expectation, so it goes through the firewall with no mangling -
> >    as you described. But, in such case, given we do not match an
> >    expectation, nf_nat_sip_expected() is not called.
> >
> > So what am I missing to exercise your new code from nf_nat_sip_expected()?
>
> An INVITE creates an expectation for the RTP packets sent by the party
> that receives the INVITE, while the reply to the INVITE creates
> another expectation for the RTP packets sent by the call initiator.
> These expectations are designed to perform the necessary DNAT, so the
> expectations created by SIP packets sent from LAN to WAN are not doing
> actually any translation (source IP address is translated anyway by
> the MASQUERADE/SNAT rule). However, when RTP port of the LAN client
> requires translation (source port that is, e.g. from 1024 to 1026),
> the current version of nf_nat_sip_expected doesn't deliver it.
>
> There is no problem when the WAN party is the one that sends the first
> RTP packet because the LAN party's RTP packets will match the
> conntrack created by the WAN party's RTP packets and therefore the
> source port of the RTP packets sent from the LAN will be translated
> correctly.
>
> However, when LAN client sends the first RTP packet, there is no
> conntrack created already so there will be no source port translation.
> And this is where my patch intervenes... It looks for the expectation
> created by the INVITE's reply (where all the necessary info is stored)
> and perform the SNAT accordingly.

Correction: It looks for the expectation created by the INVITE (where
all the necessary info is stored) and perform the SNAT accordingly.

As I said earlier, the LAN RTP packets are hitting the expectation
created by the peer's reply to the INVITE.

>
> >
> > > +                     range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
> > > +                     range.min_proto.all = range.max_proto.all = pair_exp->tuple.dst.u.all;
> > > +                     range.min_addr = range.max_addr = pair_exp->tuple.dst.u3;
> > > +                     range_set_for_snat = 1;
> > > +                     break;
> > > +             }
> > > +     }
> > > +     spin_unlock_bh(&nf_conntrack_expect_lock);
> > > +
> > > +     /* When no paired expected conntrack has been found, change src to
> > > +      * where master sends to, but only if the connection actually came
> > > +      * from the same source. */
> > > +     if (!range_set_for_snat &&
> > > +         nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
> > >                            &ct->master->tuplehash[exp->dir].tuple.src.u3)) {
> > >               range.flags = NF_NAT_RANGE_MAP_IPS;
> > >               range.min_addr = range.max_addr
> > >                       = ct->master->tuplehash[!exp->dir].tuple.dst.u3;
> > > -             nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
> > > +             range_set_for_snat = 1;
> > >       }
> > > +
> > > +     /* Perform SRC manip. */
> > > +     if (range_set_for_snat)
> > > +             nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
> > >  }
> > >
> > >  static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
> > > --
> > > 2.7.4
> > >




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux