Linux Virtual Server i NetFilter, SNAT against Masquerading never lost

November 29, 2007 – 2:17 am

Escriure un post al blog sobre algunes de les compatibilitats menys estudiades i indocumentades entre Linux Virtual Server (LVS) i NetFilter - aka iptables - pot semblar una mica tendenciós. Seré generalista al donar informació global i detallista amb el que realment cal. Existeix un Overview molt tècnic del que comento aqui, descobert en un intent de traduir el codi de LVS

Ja fa temps que vaig escriure algun article sobre LVS i fins i tot en vaig presentar alguna cosa a la facultat. Arrel d'uns canvis que estem portant a terme a la feina m'he vist amb l'obligació moral d'estudiar un cas força especial de compatibilitat entre LVS i NetFilter.

Les dues conclusions que n'he tret són : primer que estava equivocat en com creia que LVS s'integrava a NetFilter i segon que fer coexistir LVS i NetFilter dins el codi i arquitectura de la pila TCP/IP del kernel de Linux no és una feina trivial


SNAT against Masquerading

Recordem que LVS té un mètode per fer forwarding de paquets anomenat masquerading, mitjançant aquest mètode els paquets que s'envien a la xarxa interna de servidors que formen LVS reben com ip origen la ip del client i la ip destí la del propi servidor web.

Per tant en modo masquereading, LVS espera que els teus servidors que formen el cluster LVS tinguin com a gateway la mateixa màquina on esta corrent LVS, per poder aplicar l'operació inversa del maquerading.

NetFilter permet entre multitud de coses aplicar regles a la taula NAT a l'estat POSTROUTING per modificar l'origen dels paquets que surten per una ethernet derminada.

Com podem veure aquestes dues opcions que permeten modificar les ips origen del paquet, coexistint en una mateixa maquina amb regles de re escritura de la ip orgien diferent sobre una mateixa ethernet podría portrar problemes, SNAT acabaria aixafant el Masquerading de LVS.

Doncs resulta que la gent de LVS ja va pensar amb aquesta problemàtica i va aplicar alguns mecanismes al codi del kernel per evitar-ho.

Com s'integra el Masquerade de LVS al Kernel

LVS utilitza dos hooks de NetFilter als estats Forward i Post Routing respectivament per evitar la problemàtica comentada.

Com podem veure a ip_vs_core.c es declaren els dos hooks comentats. El primer anomenat ip_vs_out_ops s'inicialitza amb una prioritat de 100 i sobre l'estat FORWARD


/* After packet filtering, change source only for VS/NAT */
static struct nf_hook_ops ip_vs_out_ops = {
.hook = ip_vs_out,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = 100,
};

Mitjançant aquest hook - després del seu posterior registre - Netfilter cridarà a la operació ip_vs_out per a cada paquet que entri a l'estat NF_IP_FORWARD, amb un prioritat de 100.

Recordem l'estat NP_IP_FORWARD indica que s'està cercant una ruta per aquell paquet determinat i s'està decidint sobre quin medi físic s'injectarà el paquet ( diguis per exemple elecció de ethernet i ruta per defecte)

Si fem una ullada a la funció ip_vs_out podem trobar un conjunt d'operacions interessants que seran importants per entendre com finalment el SNAT no sobreescriure el masquerade aplicat per LVS


static unsigned int
ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
.....
/* mangle the packet */
if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp))
goto drop;
skb = *pskb;
skb->nh.iph->saddr = cp->vaddr;
ip_send_check(skb->nh.iph);
IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
ip_vs_out_stats(cp, skb);
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
ip_vs_conn_put(cp);
skb->nfcache |= NFC_IPVS_PROPERTY;
LeaveFunction(11);
return NF_ACCEPT;
....
}

La part important d'aquesta funció la trobem al final, tal i com ja diu per ella mateixa amb el comentari mangle the packe. El que fa a continuació del comentari és modificar l'adreça o ip origen del paquet. Aplicant d'aquesta forma el masquerade.

Seguidament actualitza temes referents al accounting mitjançant les funcions *_stats i finalment, i això és important, marcar el paquet amb el flag NFC_IPVS_PROPERTY

Si fem ara una ullada al segon hook, el que estava sobre l'estat POST ROTING, on podrem observar com la prioritat que es dona és justament NF_IP_PRI_NAT_SRC-1, provocant que la prioritat sigui superior a la regla de SNAT

/* Before the netfilter connection tracking, exit from POST_ROUTING */
static struct nf_hook_ops ip_vs_post_routing_ops = {
.hook = ip_vs_post_routing,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC-1,
};

La funció ip_vs_post_routing que es executada per Netfilter per a cada paquet que travessa l'estat POST ROUTING es realment fàcil d'entendre i acaba de tancar el cercle


static unsigned int ip_vs_post_routing(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
if (!((*pskb)->nfcache & NFC_IPVS_PROPERTY))
return NF_ACCEPT;
/* The packet was sent from IPVS, exit this chain */
(*okfn)(*pskb);
return NF_STOLEN;
}

Aquesta funció basicament fa un bit test a sk_buf per saber si existeix NFC_IPVS_PROPERTY, fer això és el mateix que preguntar-se si aquest paquet ha passat per el masquerade de LVS. En cas de respondre afirmatiu la funció retorna un NF_STOLEN, provocant que el paquet ja no travessi cap més funció de Netfilter, entre elles la de SNAT, i sigui injectat directament a la ethernet

  1. One Response to “Linux Virtual Server i NetFilter, SNAT against Masquerading never lost”

  2. Qui va fer l’editor del Word Press hauria de replantejar-se la seva feina, estic per abandonar i passar a metodes més tradicionals, algú coneix alguna bona manera d’editar posts dedicats a programació !!

    By pfreixes on Nov 29, 2007

Post a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word