[fli4l] statisches Forward vs. dynamischer NAT-Eintrag

Christoph Schulz fli4l at kristov.de
Do Aug 18 07:15:07 CEST 2016


Hallo!

Am Thu, 18 Aug 2016 01:32:58 +0200 schrieb Erwin Lottermann:

> So weit ich das beobachten konnte, verwendet ein Client bei SIP
> normalerweise keinen zufälligen Quellport sondern ebenfalls 5060.

OK, das wusste ich nicht.

> Bei SIP ist es keine ganz untypische Situation, dass die NAT-Einträge
> wegen UDP-Timeout gelöscht werden, weil lange (z.B. 1 Stunde) keine
> Daten über die Verbindung gehen. Um trotzdem erreichbar zu sein, wird
> vielfach empfohlen, ein statisches Forwarding für den externen Port 5060
> udp für die fritzbox im LAN einzurichten.
> 
> Jetzt startet jemand einen zweiten SIP-Client A' im LAN und es gibt
> gerade keinen NAT-Eintrag für die SIP-Verbindung der Fritzbox A, weil
> das Timeout abgelaufen ist. Oder die Fritzbox ist gar nicht
> eingeschaltet. Oder der zweite SIP-Client verbindet sich gar nicht zu
> B:5060 wie die Fritzbox, sondern zu C:5060.
> 
> Wir haben dann im Router ein statisch eingerichtetes Forwarding für den
> externen Port 5060 Richtung Fritzbox:5060 und wir haben einen dynamisch
> entstandenen NAT-Eintrag C:5060->A':5060
> 
> Jetzt sendet C:5060 an F:5060 Daten
> 
> Welche Regel greift jetzt zuerst?

Die conntrack-Regel. Siehe die Priorisierung im Linux-Kernel:

kristov at peacock /usr/src/linux $ grep NF_IP_PRI_ include/uapi/linux/
netfilter_ipv4.h
        NF_IP_PRI_FIRST = INT_MIN,
        NF_IP_PRI_CONNTRACK_DEFRAG = -400,
        NF_IP_PRI_RAW = -300,
        NF_IP_PRI_SELINUX_FIRST = -225,
        NF_IP_PRI_CONNTRACK = -200,
        NF_IP_PRI_MANGLE = -150,
        NF_IP_PRI_NAT_DST = -100,
        NF_IP_PRI_FILTER = 0,
        NF_IP_PRI_SECURITY = 50,
        NF_IP_PRI_NAT_SRC = 100,
        NF_IP_PRI_SELINUX_LAST = 225,
        NF_IP_PRI_CONNTRACK_HELPER = 300,
        NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
        NF_IP_PRI_LAST = INT_MAX,

NF_IP_PRI_CONNTRACK = -200 < -100 = NF_IP_PRI_NAT_DST, also erst 
CONNTRACK, dann Destination NAT.

Außerdem wird die nat-Tabelle nur für *neue* Verbindungen (genauer: Flows) 
zu Rate gezogen, d.h. der Conntrack-Status muss "NEW" sein. Das ist in 
der Funktion nf_nat_ipv4_fn() in net/ipv4/netfilter/nf_nat_l3proto_ipv4.c 
implementiert:

        switch (ctinfo) {
[...]
        case IP_CT_NEW:
                if (!nf_nat_initialized(ct, maniptype)) {
                        unsigned int ret;

                        ret = do_chain(priv, skb, state, ct);
                              ^^^^^^^^
                              (hier wird die NAT-Tabelle abgearbeitet)
[...]
        default:
                /* ESTABLISHED */
                NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
                             ctinfo == IP_CT_ESTABLISHED_REPLY);
                if (nf_nat_oif_changed(state->hook, ctinfo, nat, state-
>out))
                        goto oif_changed;
        }

Ein Bild sagt häufig mehr als tausend Worte. Eines der typischen 
Diagramme zum Linux-Paketfilter kann man z.B. unter https://
upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg 
finden. Hier sieht man gut, dass die conntrack-Behandlung in der 
PREROUTING-Ketter zwar nach der raw-, aber noch vor der mangle- oder nat-
Tabelle passiert. In der oben verlinkten Grafik steht sogar explizit drin:

  "nat" table only consulted for "NEW" connections


Viele Grüße,
-- 
Christoph Schulz
[fli4l-Team]


Mehr Informationen über die Mailingliste Fli4L