Les packages de pré-traitement envoient à / de l'interface

Est-il possible d'intercepter des données de packages juste avant qu'il n'atteigne une interface, et juste après sa réception? Par exemple, le pré-traiter et le renvoyer sur son path?

Je voulais créer une solution personnalisée comme ce super programme appelé vtun . Il crée un périphérique virtuel qui agit comme une interface. Cela lui permet de faire toutes sortes de choses comme la compression du trafic, le encryption, le façonnage, etc.

Je me demandais si cela peut être fait plus facilement maintenant (vtun est assez vieux …). Mon OS cible est Ubuntu 14.04.

Oui, le framework Netfilter du kernel Linux est assez flexible pour rendre cela possible.

Je ne sais pas quelles sont vos attentes en disant «solution personnalisée» et «si cela peut être fait plus facilement maintenant» . Je suppose que vous êtes prêt à écrire du code afin de faire un traitement de packages de bas niveau.

L'idée générale est la suivante:

  1. Créez des règles iptables qui transmettront le trafic de la table désirée ( filter , nat , mangle ) à l'espace user, à travers la cible QUEUE .
  2. Vous pourrez accéder aux packages que vous avez envoyés à la file en utilisant la bibliothèque libnetfilter_queue ou nfqueue-bindings (si vous travaillez avec Perl ou Python).
  3. Traitez les packages comme bon vous semble et renvoyez-les sur leur path.

Gardez à l'esprit que vous travaillerez avec des packages IP bruts, des segments TCP ou des datagrammes UDP (en fonction du type de trafic que vous voulez traiter) et qu'il vous appartiendra de réassembler correctement le trafic, de maintenir la sum de contrôle au niveau du package et tout ce que la stack TCP / IP de votre operating system prend en charge par magie dans les coulisses.

Si vous envisagez de travailler en Python, je vous suggère d'utiliser dpkt ou scapy pour travailler avec des packages ou des segments TCP. Cela rendra les choses beaucoup plus faciles.

Voici un exemple de code utilisant les suggestions de @dkaragasidis. Il lit datatables de packages et les transmet. Vous pouvez modifier le package dans la fonction de gestionnaire.

Comstackr avec: -lnetfilter_queue -lnfnetlink

Ajouter une règle avec (exemple): sudo iptables -A OUTPUT -p udp --dport 4444 -j NFQUEUE --queue-num 0

Supprimer la règle avec (exemple): sudo iptables -D OUTPUT -p udp --dport 4444 -j NFQUEUE --queue-num 0

Testez avec: nc -lu 4444 et nc -u YOUR_IP 4444

 #include <netinet/in.h> #include <linux/netfilter.h> #include <libnetfilter_queue/libnetfilter_queue.h> #include <stdio.h> int handler(struct nfq_q_handle *myQueue, struct nfgenmsg *msg, struct nfq_data *pkt, void *cbData) { int id = 0; struct nfqnl_msg_packet_hdr *header; if( header = nfq_get_msg_packet_hdr(pkt) ) id = ntohl(header->packet_id); unsigned char *pktData; int len = nfq_get_payload(pkt, &pktData); printf("data[ %d ]:\n", len); int i; for (i = 0; i < len; i++) printf("%2d 0x%02x %3d %c\n", i, pktData[i], pktData[i], pktData[i]); printf("\n"); return nfq_set_verdict(myQueue, id, NF_ACCEPT, len, pktData); } int main(int argc, char **argv) { struct nfq_handle *nfqHandle; struct nfq_q_handle *myQueue; struct nfnl_handle *netlinkHandle; int fd, res; char buf[4096]; // queue connection if (!(nfqHandle = nfq_open())) { perror("Error in nfq_open()"); return(-1); } // bind this handler if (nfq_bind_pf(nfqHandle, AF_INET) < 0) { perror("Error in nfq_bind_pf()"); return(1); } // define a handler if (!(myQueue = nfq_create_queue(nfqHandle, 0, &handler, NULL))) { perror("Error in nfq_create_queue()"); return(1); } // turn on packet copy mode if (nfq_set_mode(myQueue, NFQNL_COPY_PACKET, 0xffff) < 0) { perror("Could not set packet copy mode"); return(1); } netlinkHandle = nfq_nfnlh(nfqHandle); fd = nfnl_fd(netlinkHandle); while ((res = recv(fd, buf, sizeof(buf), 0)) && res >= 0) nfq_handle_packet(nfqHandle, buf, res); nfq_destroy_queue(myQueue); nfq_close(nfqHandle); return 0; }