IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

probléme socket RAW


Sujet :

Réseau C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 15
    Points : 6
    Points
    6
    Par défaut probléme socket RAW
    Bonjour à tous,

    j'ai un problème avec mon appli qui utilise un SOCK_RAW pour modifier des packets UDP reçu et les renvoyer vers un autres hote, voila le process:
    soit machines A B et C et D, l'application en question est sur C
    1)D envoie des packets UDP destiné a A et tout passe par C, ainsi l'appli reçois le message.
    2)une fonction CALLBACK est appellé pour chaque packet reçu, elle extrait le payload du packet (entête IP, UDP+data) et le passe a une 3éme fonction build_pkt()
    3) cette 3éme fonction prend le paylad change l'adresse IP de destination ainsi que le port et l'envoie à travers un socket RAW avec sendto()

    voila le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
     
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <linux/types.h>
    #include "linux/netfilter.h"
    #include <time.h>
    #include "libnetfilter_queue/libnetfilter_queue.h"
    #include <linux/ip.h>
    #include <linux/tcp.h>
    #include <linux/udp.h>
     
    #define SPORT 57630
    #define DPORTB 49739
     
    #define DPORTA 49872
    #define PAYL_LEN 10
     
    typedef struct {
    		int Mode;
     
    		int Nbr;
    		long int Temps;
    		int a,b,c;
        	} MaShm;
    	MaShm *shm;
    	char  *s;
     
     
    int sockfd;
     
     
    static void init_socket()
    {
     
     
    int one = 1;
    const int *val = &one;
    /*
    ***création du socket qui est une interface
    ***qui nous permettra d'envoyer des paquets de données à travers le réseau,
    ***SOCK_RAW est le type de socket, le type RAW a la particularité de nous laisser
    ***acceder au données contenues dans les entêtes
    */
     
        printf("Création du socket\n");
    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
    if(sockfd <0) {
    	printf("erreur durant la création du socket");
     }
     
    /*
    ***cette fonction est nécéssaire p
    our empecher le kernel de prendre l'initiative
    ***de completer les entête automatiquement
    */
     
      if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
          printf ("Warning: Cannot set HDRINCL!\n");
          return;
     }
     
    }
     
     
    static void build_copy_pkt (unsigned char *data)
    {
     
     
    int numbytes;
    unsigned char *cpy_data = data;
    struct sockaddr_in dconn;
    char source_addr[16], dest_addr[16];
     
     
    /*
    ***déclaration des entêtes IP et udp, ce qui nous permettra d'acceder et d'éditer les informations
    ***dans les entêtes
     
    */
    struct iphdr *ip_hdr;
    struct udphdr *udp_hdr;
    ip_hdr=(struct iphdr *)cpy_data;
    if(ip_hdr->protocol == IPPROTO_UDP) {
     
    udp_hdr = (struct udphdr *)(cpy_data + sizeof (struct iphdr));
     
    }
     
     
     
    /*
    ***la longueur totale de l'entête ip est calculé en ajoutant la taille de
    ***l'entête UDP + la taille des données (10).
    */
    inet_ntop(AF_INET, &(ip_hdr->saddr), source_addr, sizeof(source_addr));
    if(shm->Mode == 0) {
    inet_pton(AF_INET, "192.6.1.236", &ip_hdr->daddr);
      } else if(shm->Mode == 1) {
     
        inet_pton(AF_INET, "192.6.1.237", &ip_hdr->daddr);
               }
     
    inet_ntop(AF_INET, &(ip_hdr->daddr), dest_addr, sizeof(dest_addr));
    ip_hdr->tot_len= sizeof(struct iphdr)+ sizeof(struct udphdr) +PAYL_LEN;
     
    /* affichage des information qui nous interresse */
    printf("protocole : %d\n", ip_hdr->protocol);
     
    printf("ttl : %d\n", ip_hdr->ttl);
    printf("source adr : %s\n", source_addr);
    printf("dest adr : %s\n", dest_addr);
    printf("tot len : %d\n", ip_hdr->tot_len);
     
    /*
    ***on définie le port de destination, celui qu'utilise le serveur pour communiquer
    ***la partie Transport est constituée de l'entête UPD d'une longueur de 8bytes + la taille des données...
    8+10 = 18
    */
     
    if(shm->Mode==1) {
    udp_hdr->dest = htons(DPORTB);
    printf("dport : %d\n", ntohs(udp_hdr->dest));
    dconn.sin_port  = htons(DPORTB);
    } else {
    udp_hdr->dest = htons(DPORTA);
    printf("dport : %d\n", ntohs(udp_hdr->dest));
    dconn.sin_port  = htons(DPORTA);
    }
    udp_hdr->source = htons(SPORT);
    printf("sport : %d\n", ntohs(udp_hdr->source));
    udp_hdr->len = htons(8 + PAYL_LEN);
    /*
    ***on paramettre le socket pour envoyer les packet a destination ip_hdr->dest sur le port voulu
    */
     
    dconn.sin_family = AF_INET;
    dconn.sin_addr.s_addr = ip_hdr->daddr;
     
     
    numbytes= sendto(sockfd, cpy_data,ip_hdr->tot_len, 0,(struct sockaddr *)&dconn, sizeof(struct sockaddr));
    if(numbytes <0) {
                printf("erreur durant l'envoi \n");
                return;
            }
            printf("pkt sent : %d\n", numbytes);
     
     
     
     
    }
     
     
    /*
    ***la fonction cb pour callback est une fonction appelé à chaque fois qu'un paquet est reçu
    ***sur la queue.
    */
    static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
    	      struct nfq_data *nfa, void *data)
    {
    	int id=0;
        int ret;
    	unsigned char *pl;
    	struct nfqnl_msg_packet_hdr *ph;
     
     
    	printf("entering callback\n");
        /*
        ***nfq_get_payload() récupére le packet en lui même c'est à dire avec toutes ses entête
        ***Liaison ,réseau et transport + DATA
        */
    	ret = nfq_get_payload(nfa, &pl);
    	int taille = sizeof(pl)-1;
    	int i;
    	for(i=28; i<=ret; i++) {
     
    	printf(" 0x%1X ", pl[i] );
     
    	}
    	if(ret>=0) {
    	   build_copy_pkt(pl);
    	}
            ph = nfq_get_msg_packet_hdr(nfa);
            if (ph) {
    		id = ntohl(ph->packet_id);
    		printf("pckt_id : %d\n", id);
     
    	}
     
    	return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
     
     
     
    }
     
     
     
    int main(int argc, char **argv)
    {
    	struct nfq_handle *h;
    	struct nfq_q_handle *qh;
    	struct nfnl_handle *nh;
    	int fd;
    	int rv;
    	char buf[4096] __attribute__ ((aligned));
    	int shmid;
        	key_t key;
     
        	init_socket();
     
        key = 5678;
     
        if ((shmid = shmget(key, sizeof(MaShm), 0666)) < 0) {
            perror("shmget");
            exit(1);
        }
     
     
        if ((shm = (MaShm*)shmat(shmid, NULL, 0)) == (MaShm *) -1) {
            perror("shmat");
            exit(1);
        }
     
     
    	printf("opening library handle\n");
    	h = nfq_open();
    	if (!h) {
    		fprintf(stderr, "error during nfq_open()\n");
    		exit(1);
    	}
     
    	printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
    	if (nfq_unbind_pf(h, AF_INET) < 0) {
    		fprintf(stderr, "error during nfq_unbind_pf()\n");
    		exit(1);
    	}
     
    	printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
    	if (nfq_bind_pf(h, AF_INET) < 0) {
    		fprintf(stderr, "error during nfq_bind_pf()\n");
    		exit(1);
    	}
     
    	printf("binding this socket to queue '4'\n");
    	qh = nfq_create_queue(h,  4, &cb, NULL);
    	if (!qh) {
    		fprintf(stderr, "error during nfq_create_queue()\n");
    		exit(1);
    	}
     
    	printf("setting copy_packet mode\n");
    	if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
    		fprintf(stderr, "can't set packet_copy mode\n");
    		exit(1);
    	}
     
    	fd = nfq_fd(h);
     
     
    		while((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
     
    			printf("début du paquet\n");
    			nfq_handle_packet(h, buf, rv);
     
     
     
    			printf("fin du paquet\n\n");
     
    		}
     
     
     
    	printf("unbinding from queue 0\n");
    	nfq_destroy_queue(qh);
     
    #ifdef INSANE
    	/* normally, applications SHOULD NOT issue this command, since
    	 * it detaches other programs/sockets from AF_INET, too ! */
    	printf("unbinding from AF_INET\n");
    	nfq_unbind_pf(h, AF_INET);
    #endif
     
    	printf("closing library handle\n");
    	nfq_close(h);
     
    	exit(0);
    }

    le message est bien transporté jusqu'a A mais le PROBLEME est que B ne reçois pas le message envoyé sur le socket... j'ai fait les verif avec wireshark les packets sont identique (hors mis l'adresse ip de dest et le port)
    j'ai besoin d'aide svp , merci de vos réponses.

  2. #2
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Salut,

    J'ai regarde tres rapidement et je vois ces problemes potentiels (dans build_copy_pkt):
    1. Tu ne changes pas l'@ MAC, donc ton packet va forcement aller au mauvais endroit vu que ton packet n'est pas route. Il faut que tu changes l'adresse MAC, soit statiquement, soit en faisant une requete ARP.
    2. tu ne recalcules pas les checksums des packets modifies (autant au niveau IP qu'UDP). Tu modifies les donnees, donc les checksums doivent etre recalcules si tu ne veux pas que la carte reseau src/dst ignore le packet. Pareil au niveau applicatif. Ca doit etre possible d'offloader les checksums UDP a la carte reseau ou au kernel, mais je suis pas sur (C'est possible avec TCP en tout cas)

    T'as fonction d'envoi a l'air correcte.

    Plus generallement, pourquoi tu n'utilises pas le mutlicast ici?

    Bon courage.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    merci beaucoup d'avoir repondu l'adresse mac de destination n'est pas accessible a ce niveau la mais est correctement ajouté lors de l'envois du packet (avec une requête ARP),
    j'ai naté l'adresse mac source (au cas ou) avec ebtables.
    -c'est vrai! je n'y ai pas pensé! vu que le checksum est le résultat d'une opération sur les données des entêtes! c'est peut etre ça, je vais essayer.
    j'ai pensé au multicast mais le patron trouvais cette solution plus sympa, faute de résultat je vais cependant mettre en oeuvre le multicast.

    Merci encore je vous tien au courrant

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    alors j'ai jeté un coup d'oeuil sur wireshark et le checksum semble bon (j'ignore comme il c'est modifié mais il est différent dans le paquet allant a A (originial) et celui allanta B (copie)
    j'ai essayé d'envoyé le message copié vers A et elle le reçois correctement (2 fois ducoup) c'est a dire que la copie marche vers A et pas vers B... je n'y comprend plus rien j'en ai marre...
    escqu'il ne pourrai pas sagir d'un probléme d'initialisation de dialogue entre les deux machines?
    Wireshark pourrai t'il me feinter pour le checksum?

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 599
    Points
    23 599
    Par défaut
    Je n'ai que survolé ton post mais si tu as des problèmes de checksums en manipulant l'IP, peut-être trouveras-tu des indices dans cette discussion

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2013
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    Très bien je pense que le checksum me joue des tours je vais essayer mettre une fonction dans mon code qui le calcule, cependant je n'arrive pas à comprendre pourquoi wireshark dit que le checksum est valide pour l'IP (même si je n'ai rien changé) et [validation disabled] pour l'entete UDP, c'est normal?

    Bon... ben ça a l'air de marcher... je n'accorderai plus une confiance aveugle à wireshark... je vous remercie beaucoup vous êtes géniaux tout les deux!! <3

  7. #7
    Membre éclairé
    Profil pro
    Ingénieur sécurité
    Inscrit en
    Février 2007
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2007
    Messages : 574
    Points : 751
    Points
    751
    Par défaut
    Citation Envoyé par Para_doxx Voir le message
    [validation disabled] pour l'entete UDP, c'est normal?
    Si tu as pris la capture sur la meme machine qui genere les packets sortants, c'est normal. De nos jours les checksums (L4) sont fait par la carte reseau directement. Le kernel n'y met qu'une suite de zero, et le checksum est calcule en hardware.
    Mais la capture faite par la libpcap se fait avant l'ajout des checksums. Avant, Wireshark jettait plein d'erreurs de checksums sur les packets sortants. Maintenant, ils ont desactives la verification des checksums de L4 dans wireshark pour les packets sortants, originaire de la meme machine.

    Citation Envoyé par Para_doxx Voir le message
    Bon... ben ça a l'air de marcher... je n'accorderai plus une confiance aveugle à wireshark...
    Tu peux quand meme . Wireshark est un outil incroyable, mais comme tout les outils, il a certaines subtilites.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de Raw Sockets
    Par simrapman dans le forum Réseau/Web
    Réponses: 1
    Dernier message: 07/09/2009, 14h31
  2. [Socket RAW] Problème entête UDP
    Par Flo0r dans le forum Réseau
    Réponses: 4
    Dernier message: 30/12/2008, 16h41
  3. Problème socket raw ? bizarre :~
    Par MonsieurAk dans le forum Windows
    Réponses: 2
    Dernier message: 12/07/2005, 15h12
  4. [Réseau] Problème socket
    Par neenee dans le forum Entrée/Sortie
    Réponses: 14
    Dernier message: 18/01/2005, 16h26
  5. App Socket Raw avec VC++6
    Par Martin Soucy dans le forum Développement
    Réponses: 3
    Dernier message: 04/12/2002, 06h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo