Implementación NAT usando NETFILTER en Linux Kernel (Ver: 2.6.34.10)

NAT ( Network Address Translation )
En las redes de computadoras, traducción de direcciones de red ( NAT ) es el proceso de modificación de información de la dirección IP en los encabezados de paquetes IP <. / div>

Con la ayuda small;»> style=»font-size: pr ivate IP addre se puede traducir a la dirección IP pública small;»> esconde el espacio de direcciones IP privadas de espacio de direcciones IP públicas
En mi post anterior, que habría visto sobre los conceptos básicos de netfilter
En este post, me gustaría para explicar sobre la implementación NAT utilizando el código NETFILTER.

Si bien la implementación de NAT en NETFILTER, DNAT debe realizar en gancho pre-Routing mientras que SNAT (Fuente NAT) llevará a cabo en Hook post-Routing (Recuerde que esta es una regla del pulgar básica)
Con el fin de enviar el paquete de Pre-Routing Hook to Post-Routing Hook, el gancho delantero debe estar habilitado como siguien w s.
echo 1> / proc / sys / net/ipv4/ip_forward

Nota: DNAT y SNAT no se puede realizar en el pre .-Routing Hook (Esto no funcionará)

Configuración de prueba
/>
Netfilter Kernel código fuente: muniTestNetfilter.c # include
# include # include # include # include # include # include

/ * Encabezados opcionales no es necesario, si usted no ‘t quiere Eliminar * / # include

# include # include # include

/ * Estos son necesarios para la funcionalidad NETFILTER * / # include

# include # include # include

# define DRIVER_AUTHOR_NAME
# define DRIVER_DESCRIPTION «NETFILTER»

# define DEST_PORT_NUM 2905

/ * NETFILTER * /
estructura estática nf_hook_ops test_hookPreRouting;
estructura estática nf_hook_ops test_HookPostRouting;
/ *
* preRoutingHookEntryFunc -> Función Pre Routing
* /
static unsigned int preRoutingHookEntryFunc (
                       unsigned int unHookNum,
                       struct sk_buff * skb,
                       const struct net_device * INDEVICE,
                       const struct net_device * OUTDEVICE,
                       int (* okfn) (struct sk_buff *))

{/ * Copie el Socket Buffer * / struct
sk_buff * sockBuff = skb ;

/ * Intialise la UDP Encabezado * / struct
udphdr * uh = NULL;

/ * Extraer el encabezado IP * / struct
iphdr * iph = ip_hdr (SKB),

/ * Si la Cabecera IP es cero o SockBuff es Zero acaba de aceptar * /
if (NULL == sockBuff | | NULL == iph)
retorno NF_ACCEPT;

/ * Señale la UDP Encabezado * /
uh = (struct udphdr *) (sockBuff-> data + (IPH- > DIH * 4));

/ * Filter sólo UDP de paquetes * /
if ((IPH-> protocolo == IPPROTO_UDP) &&
                       (Ntohs (uh-> dest) == DEST_PORT_NUM))

{/ * Recuperar UDP Encabezado * /
printk (KERN_INFO «Recived paquete antes de [Pre-Hook] con IPDest:% x: PortNum:% d»
; «IPSrc% x: PortNum:% d n»,
ntohl (IPH-> daddr), ntohs (uh-> dest),
ntohl (IPH-> saddr), ntohs (uh-> fuente));
;
/ * Realizar la DNAT en Pre-enrutamiento * /
/ * Cambiar la dirección IP Dest y mencione apropiada electrónico * /
iph-> daddr = htonl (0x0a0c075f);

printk (KERN_INFO » Recived paquete después [Pre-Hook] con IPDest:% x: PortNum:% d «
; «IPSrc% x: PortNum:% d n»,
ntohl ( iph-> daddr), ntohs (uh-> dest),
ntohl ( iph-> saddr), ntohs (uh-> fuente));

} / * Todos los paquetes Justo NF_ACCEPT
* Si se trata de paquetes de país, entonces se irá a LOCAL_IN
* Aplicación a los demás por no locales Los paquetes que irá
* GANCHO POST y salida
* /
retorno NF_ACCEPT;
}
/ *
* postRoutingHookEntryFunc -> Función Publica Routing

* * GANCHO POSTE será llamado para los paquetes locales sin fines de
* HOOK PRE_HOOK-POST través
* ADELANTE demás LOCAL_OUT – HOOK POST para los paquetes generados local del sistema (PING)

* * /
estática unsigned int postRoutingHookEntryFunc (
unsigned int unHookNum, />
estructura const net_device * INDEVICE, />
int (* okfn) (struct sk_buff *))

{/ * Copie el Socket Buffer * /
struct sk_buff * sockBuff = skb;

/ * Intialise la UDP Encabezado * / struct
udphdr * uh = NULL;

/ * Extraer el encabezado IP * / struct iphdr
* iph = ip_hdr (SKB),

/ * Si el hdr IP es Cero o Cero SockBuff es simplemente aceptar * /
if (NULL == sockBuff | | NULL == iph)
retorno NF_ACCEPT;

/ * Señale la UDP Encabezado * /
uh = (struct udphdr *) (sockBuff-> data + (IPH-> DIH * 4));

/ * Filter sólo UDP de paquetes * /
if ((IPH-> protocolo == IPPROTO_UDP) &&
                     (Ntohs (uh-> dest) == DEST_PORT_NUM))

{/ * Recuperar UDP Encabezado * /
printk (KERN_INFO «Recived Paquete En ANTES [HOOK Post] IPDest:% x: PortNum:% d»
«IPSrc% x: PortNum:% d n»,
; ntohl (IPH-> daddr), ntohs (uh-> dest),
; ntohl (IPH-> saddr), ntohs (uh-> fuente));

/ * Realizar el SNAT en POST-enrutamiento * /
/ * Cambiar la dirección SourceIP y mencione dirección apropiada * /

/ * Módulo de salida * /
module_exit (muni_test_netfilter_exit);

/ * Algunas MÓDULO /> PARÁMETROS * /
MODULE_AUTHOR (DRIVER_AUTHOR_NAME);
module_description (DRIVER_DESCRIPTION);
MODULE_VERSION («2.6.34.10»);

Kernel Haz archivo
obj-m + = natTest.o
natTest-OBJS: = muniTestNetfilter.o
todos:
make-C / lib / modules / $ (shell uname-r) / build M = $ módulos (PWD)
limpia:
make-C / lib / modules / $ (shell uname-r) / build M = $ (PWD) limpia

código de espacio de usuario (Se utiliza para enviar y recibir tráfico UDP)
============

# include
# include
# include

# define BUFFSIZE 5096

int sendlen, receivelen;
int i, contar, sentCnt = 0;
unsigned char buffer [BUFFSIZE];
/ * Socket cliente * / struct
sockaddr_in receivesocket;
/ * socket de servidor * / struct
sockaddr_in sendsocket;

/ * Calcetín FD /> * / int
unsigned int ch;
noOfTimes internos sin firmar;

/ * Enviar UDP de datos * / int
sendUDPData ();

/ * Recibir llamen de vuelta Función * /
void * recvNetfilterData (void *);

int main (int argc, char * argv []) {int
ret = 0;

/ * Crear el socket UDP * /
if ((sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) <0) {
perror («socket»);
return -1;}

/ * mi dirección o parámetros (Estos son necesarios para la unión del Puerto y
Dirección IP)
Enlazar a mi propio puerto y dirección * /
memset (& receivesocket, 0, sizeof (receivesocket));
receivesocket.sin_family = AF_INET ;
receivesocket.sin_addr.s_addr = htonl (INADDR_ANY);
receivesocket.sin_port = htons (2905);

; receivelen = sizeof (receivesocket);

/ * Vincular el mi Socket * /
if (bind (sockfd, (struct sockaddr *) y receivesocket , receivelen) <0) {
perror («bind»);
; return -1;}

/ * Dirección de servidor o parámetros, Envío de direcciones del sistema y el puerto Num * /
memset (& sendsocket, 0, sizeof (sendsocket));
sendsocket.sin_family = AF_INET;
/ * dar dirección IP correcta * /
sendsocket.sin_addr.s_addr = inet_addr («10.12.7.75»);
sendsocket.sin_port = htons (2905);

/ * Crear Tema Seperate * /
/ * Iniciar el Tema de recepción * /
pthread_t ThreadID;
si (pthread_create (& ThreadID, NULL, recvNetfilterData, NULL))

{printf («Error al crear proceso receptor n» );
return 0;}

/ * Hacer Loop -> Enviar UDP de datos * /
hacer

{printf («Escriba su elección :. t n «); printf />
; printf («2 exit n.»);
scanf («% d», & ch);
printf (» n»);

interruptor (ch)
{case />

                   printf («Introduzca la longitud de la carga útil n»);
                   scanf («% d», & sendlen);
                   printf («Introduzca las veces que desea enviar los datos n»);
                   scanf («% d», & noOfTimes);
                   / * Enviar UDP de datos * /
                   sendUDPData ();
                   romper; />

                  printf («Invalid Choice n»);
                  break;}

} while (ch! = 2);
return 0;}

/ *
* sendUDPData
* / int
sendUDPData ()

{ ; int cuenta = 0;
memset (buffer, 31, sendlen);

; for (cuenta = 0; cuenta if (sendto (sockfd, tampón, sendlen, 0,
                        (Struct sockaddr *) y sendsocket, sizeof (sendsocket))! = Sendlen)

{ ; perror («sendto»);
return -1;}

> else {
sentCnt + +;
;}}

return 0;}

/ *
* Vaciado de datos
* /
vacío dumpdata (unsigned char * de datos, unsigned int len)
{
; unsigned int uIndx;
if (data) {

for (uIndx = 0; uIndx }
if (uIndx% 4 == 0)
{
; printf («»);}

printf («% 02x», los datos [uIndx]);}

} printf />

}

/ *
* recvNetfilterData ()
* /
void * recvNetfilterData (void * args) {

unsigned char buf [5096];
int receivedLen = 0;

while (1)
{
memset (buf, 0, BUFFSIZE);
/ * recibe las datos de otros sistemas * /
if ((receivedLen = recvfrom (sockfd, buf, BUFFSIZE, 0, NULL, NULL)) <0) { perror («recvfrom»);
; return 0;}

else if (receivedLen == 0)
{printf />
{
/ * Imprimir El datos * /
printf («llam Byte de longitud% d n», receivedLen);
dumpdata (buf, receivedLen);
}}

}






Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *