Comment dupliquer le trafic TCP vers un ou plusieurs serveurs distants à des fins d'analyse comparative?

30

Infrastructure: serveurs dans Datacenter, OS - Debian Squeeze, Webserver - Apache 2.2.16


Situation:

Le serveur en direct est utilisé quotidiennement par nos clients, ce qui rend impossible le test des ajustements et des améliorations. Par conséquent, nous aimerions dupliquer le trafic HTTP entrant sur le serveur en direct vers un ou plusieurs serveurs distants en temps réel. Le trafic doit être transmis au serveur Web local (dans ce cas, Apache) ET aux serveurs distants. Ainsi, nous pouvons ajuster les configurations et utiliser un code différent / mis à jour sur le ou les serveurs distants pour l'analyse comparative et la comparaison avec le serveur en direct actuel. Actuellement, le serveur Web écoute environ. 60 ports supplémentaires en plus de 80 et 443, en raison de la structure du client.


Question: Comment mettre en œuvre cette duplication sur un ou plusieurs serveurs distants?

Nous avons déjà essayé:

  • duplicateur agnoster - cela nécessiterait une session ouverte par port, ce qui n'est pas applicable. ( https://github.com/agnoster/duplicator )
  • kklis proxy - ne transfère que le trafic vers le serveur distant, mais ne le transmet pas au serveur Web lcoal. ( https://github.com/kklis/proxy )
  • iptables - DNAT ne transfère que le trafic, mais ne le transmet pas au serveur Web local
  • iptables - TEE ne se duplique que sur les serveurs du réseau local -> les serveurs ne sont pas situés sur le même réseau en raison de la structure du centre de données
  • les alternatives suggérées fournies pour la question "trafic tcp en double avec un proxy" sur stackoverflow ( /programming/7247668/duplicate-tcp-traffic-with-a-proxy ) ont échoué. Comme mentionné, TEE ne fonctionne pas avec des serveurs distants en dehors du réseau local. teeproxy n'est plus disponible ( https://github.com/chrislusf/tee-proxy ) et nous n'avons pu le trouver ailleurs.
  • Nous avons ajouté une deuxième adresse IP (qui se trouve dans le même réseau) et l'avons attribuée à eth0: 0 (l'adresse IP principale est attribuée à eth0). Pas de succès avec la combinaison de cette nouvelle interface IP ou virtuelle eth0: 0 avec la fonction ou les routes iptables TEE.
  • Les alternatives suggérées fournies pour la question « Dupliquer le trafic TCP entrant sur Debian Squeeze » ( Dupliquer le trafic TCP entrant sur Debian Squeeze ) ont échoué. Les sessions cat | nc (cat / tmp / prodpipe | nc 127.0.0.1 12345 et cat / tmp / testpipe | nc 127.0.0.1 23456) sont interrompues après chaque demande / connexion par un client sans préavis ni journal. Keepalive n'a pas changé cette situation. Les packages TCP n'ont pas été transportés vers le système distant.
  • Essais supplémentaires avec différentes options de socat (HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , /programming/9024227/duplicate-input- unix-stream-to-multiple-tcp-clients-using-socat ) et des outils similaires ont échoué, car la fonction TEE fournie n'écrira que sur FS.
  • Bien sûr, googler et rechercher ce «problème» ou la configuration a également échoué.

Nous manquons d'options ici.

Existe-t-il une méthode pour désactiver l'application du "serveur dans le réseau local" de la fonction TEE lors de l'utilisation d'IPTABLES?

Notre objectif peut-il être atteint par une utilisation différente des IPTABLES ou des itinéraires?

Connaissez-vous un outil différent à cet effet qui a été testé et fonctionne pour ces circonstances spécifiques?

Existe-t-il une autre source de tee-proxy (qui répondrait parfaitement à nos besoins, AFAIK)?


Merci d'avance pour vos réponses.

----------

modifier: 05.02.2014

voici le script python, qui fonctionnerait comme nous en avons besoin:

import socket  
import SimpleHTTPServer  
import SocketServer  
import sys, thread, time  

def main(config, errorlog):
    sys.stderr = file(errorlog, 'a')

    for settings in parse(config):
        thread.start_new_thread(server, settings)

    while True:
        time.sleep(60)

def parse(configline):
    settings = list()
    for line in file(configline):
        parts = line.split()
        settings.append((int(parts[0]), int(parts[1]), parts[2], int(parts[3])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        dock_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        dock_socket.bind(('', settings[0]))

        dock_socket.listen(5)

        while True:
            client_socket = dock_socket.accept()[0]

            client_data = client_socket.recv(1024)
            sys.stderr.write("[OK] Data received:\n %s \n" % client_data)

            print "Forward data to local port: %s" % (settings[1])
            local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            local_socket.connect(('', settings[1]))
            local_socket.sendall(client_data)

            print "Get response from local socket"
            client_response = local_socket.recv(1024)
            local_socket.close()

            print "Send response to client"
            client_socket.sendall(client_response)
            print "Close client socket"
            client_socket.close()

            print "Forward data to remote server: %s:%s" % (settings[2],settings[3])
            remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote_socket.connect((settings[2], settings[3]))
            remote_socket.sendall(client_data)       

            print "Close remote sockets"
            remote_socket.close()
    except:
        print "[ERROR]: ",
        print sys.exc_info()
        raise

if __name__ == '__main__':
    main('multiforwarder.config', 'error.log')

Commentaires pour utiliser ce script:
Ce script transfère un certain nombre de ports locaux configurés vers un autre serveur de socket local et distant.

Configuration:
Ajoutez au fichier de configuration des lignes port-forward.config avec le contenu comme suit:

Les messages d'erreur sont stockés dans le fichier 'error.log'.

Le script divise les paramètres du fichier de configuration:
Fractionnez chaque ligne de configuration avec des espaces
0: port local à écouter
1: port local à transmettre à
2: adresse IP distante du serveur de destination
3: port distant du serveur de destination
et retour des paramètres

Sise
la source
Est-ce que tout le trafic est HTTP?
longneck
oui, tout le trafic est HTTP.
Sise
1
btw. teeproxy est disponible ici: github.com/chrislusf/teeproxy
Tombart
1
Autre possibilité: github.com/ebowman/splitter Scala / Netty-based.
Rich K.

Réponses:

11

C'est impossible. TCP est un protocole complet. L'ordinateur utilisateur final est impliqué dans chaque étape de la connexion et il ne répondra jamais à deux serveurs distincts essayant de communiquer avec lui. Tout ce que vous pouvez faire est de collecter toutes les requêtes http sur le serveur Web ou un proxy et de les rejouer. Mais cela ne donnera pas les conditions de concurrence ou de trafic exactes d'un serveur en direct.

Kazimieras Aliulis
la source
Dupliquer le TCP est impossible - je suis d'accord avec ça. La duplication du trafic de la couche 7 ne l'est pas. Vous pouvez capturer les demandes du client et les lire sur les autres serveurs. Une simple requête par lecture de session TCP devrait être assez facile. Les connexions persistantes vont nécessiter une réflexion dans la mesure où vous chronométrez les demandes supplémentaires du client.
Evan Anderson
@Kazimieras Aliulis: il n'est pas nécessaire de communiquer avec deux serveurs distincts. le client communique avec le serveur principal = le serveur actif. le serveur en direct traite les demandes des clients et répond au client. en plus de traiter et de répondre au client, le serveur principal duplique les requêtes vers le deuxième serveur = serveur de test. les réponses du deuxième serveur au serveur principal seront ignorées / ignorées sur le serveur principal et ne seront pas transmises au client.
Sise
@Evan Anderson: la duplication au niveau HTTP était également notre première idée, mais par exemple, le proxy Apache ou des outils ou modules similaires ne permettent pas de traiter simultanément les demandes localement et de les dupliquer sur un hôte distant. si vous avez une autre idée, n'hésitez pas à me conseiller! :) nous préférons la duplication à l'enregistrement et à la relecture pour obtenir des résultats de comparaison instantanés.
Sise
1
@Sise: vous pouvez essayer d'écrire votre propre proxy http, qui transmet le trafic à deux serveurs. Cela devrait être assez facile à faire avec le cadre python Twisted twistedmatrix.com .
Kazimieras Aliulis
@Kazimieras Aliulis: c'est définitivement une alternative! Je n'en ai jamais entendu parler. mais le vérifier montre qu'il conviendrait parfaitement à notre objectif. Nous n'avions pas envisagé python auparavant, mais actuellement nous examinons le framework Twisted et les possibilités avec python général également. Je ferai rapport si nous réussissons!
Sise
20

D'après ce que vous décrivez, GOR semble correspondre à vos besoins. https://github.com/buger/gor/ "Relecture du trafic HTTP en temps réel. Relire le trafic de la production à la mise en scène et aux environnements de développement." ?

Arthur Lutz
la source
2
C'est exactement ce que je cherchais, merci beaucoup, tu m'as sauvé en écrivant exactement ceci, dans Go! :-)
chmac
nginx a un module miroir. nginx.org/en/docs/http/ngx_http_mirror_module.html
Jimmy MG Lim
7

Teeproxy pourrait être utilisé pour répliquer le trafic. L'utilisation est vraiment simple:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a serveur de production
  • b serveur de test

Lorsque vous mettez un HAproxy (avec roundrobin) devant votre serveur Web, vous pouvez facilement rediriger 50% de votre trafic vers le site de test:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)
Tombart
la source
4

TCP, étant un protocole avec état, n'est pas susceptible de simplement exploser des copies des paquets sur un autre hôte, comme le souligne @KazimierasAliulis.

Ramasser les paquets au niveau de la terminaison TCP et les relayer en tant que nouveau flux TCP est raisonnable. L' outil de duplication auquel vous vous êtes connecté ressemble à votre meilleur pari. Il fonctionne comme un proxy TCP, permettant à la machine d'état TCP de fonctionner correctement. Les réponses de vos machines de test seront simplement ignorées. Cela ressemble à cela correspond au projet de loi pour ce que vous voulez exactement.

Je ne comprends pas pourquoi vous avez annulé l'outil de duplication comme inacceptable. Vous devrez exécuter plusieurs instances de l'outil car il n'écoute que sur un seul port, mais, vraisemblablement, vous souhaitez relayer chacun de ces différents ports d'écoute vers différents ports du système principal. Sinon, vous pouvez utiliser iptables DNAT pour diriger tous les ports d'écoute vers une seule copie d'écoute de l'outil de duplication.

À moins que les applications que vous testez ne soient très simples, je m'attends à ce que vous rencontriez des problèmes avec cette méthodologie de test concernant le timing et l'état des applications internes. Ce que vous voulez faire semble d'une simplicité trompeuse - je pense que vous allez trouver beaucoup de cas marginaux.

Evan Anderson
la source
oui, vous avez tout à fait raison, l'outil de duplication agnoster répondrait à nos besoins, à l'exception de la situation multi-ports. De plus, la suppression des réponses de la machine de test est entièrement effectuée. Pour atteindre notre objectif de simuler la situation réelle / en direct aussi précisément que possible, nous ne pouvons pas regrouper tous les ports du serveur en direct sur un seul port sur la machine de test. Différents ports sont utilisés pour diviser les appareils clients en différents clients. De ce fait, nous devons ouvrir 60 à 70 sessions de cet outil de duplication. Ce n'est pas très pratique comme vous pouvez l'imaginer.
Sise
@Sise - Les ordinateurs sont bons pour faire des choses fastidieuses. Je pense que vous pourriez écrire un script pour analyser vos configurations Apache et cracher les lignes de commande nécessaires pour exécuter 60 à 70 instances de l'outil de duplication. Je ne peux pas imaginer que l'outil de duplication soit très gourmand en ressources, mais, même s'il l'était, vous pourriez exécuter ces 60 à 70 instances sur une autre machine et faire une supercherie réseau pour obtenir le trafic là-bas. Pour moi, au moins, cela semble tout à fait pratique et une façon assez simple de gérer cela.
Evan Anderson
1

J'essaie de faire quelque chose de similaire, cependant, si vous essayez simplement de simuler la charge sur un serveur, je regarderais quelque chose comme un cadre de test de charge. J'ai utilisé locust.io dans le passé et cela a très bien fonctionné pour simuler une charge sur un serveur. Cela devrait vous permettre de simuler un grand nombre de clients et vous permettre de jouer avec la configuration du serveur sans avoir à passer par le douloureux processus de transfert de trafic vers un autre serveur.

snowbirdSkiBum
la source
0

En ce qui concerne "nous souhaitons dupliquer le trafic HTTP entrant sur le serveur en direct vers un ou plusieurs serveurs distants en temps réel", il existe une façon non mentionnée ci-dessus, qui consiste à configurer un port miroir sur le commutateur auquel il est connecté.

Dans le cas des commutateurs Cisco Catalyst, cela s'appelle SPAN (plus d'informations ici ). Dans un environnement Cisco, vous pouvez même avoir le port en miroir sur un autre commutateur.

Mais le but de ceci est pour l'analyse du trafic, donc ce sera unidirectionnel - mot-clé dans le texte cité dans le premier paragraphe ci-dessus: entrant . Je ne pense pas que le port autorisera le trafic de retour, et si c'était le cas, comment traiteriez-vous le trafic de retour en double? Cela fera probablement des ravages avec votre réseau.

Alors ... je voulais juste ajouter une possibilité à votre liste, mais avec la mise en garde que ce sera en effet pour le trafic à sens unique. Peut-être que vous pouvez placer un concentrateur sur ce port miroir et faire remettre des réponses de serveur en double par un simulateur client local qui capterait les sessions initiées et y répondrait, mais alors vous dupliqueriez le trafic entrant vers votre serveur en double ... probablement pas ce que vous vouloir.

James
la source
nous y avons pensé, j'ai lu sur l'alternative d'utiliser SPAN. Mais, comme les serveurs sont situés dans un centre de données d'un fournisseur tiers, nous avons des possibilités limitées en ce qui concerne les changements matériels. J'ai déjà demandé de connecter directement 2 serveurs sur un deuxième nic. Cette action combinée à un réseau local uniquement pour ces 2 serveurs me permettrait d'utiliser IPTABLES avec TEE. Mais pour opter pour cette alternative, nous aurions besoin de changer les adresses IP externes des serveurs, ce qui est un NoGo car les appareils clients sont configurés pour se connecter à l'adresse IP définie.
Sise
0

J'ai également écrit un proxy inverse / équilibreur de charge dans un but similaire avec Node.js (c'est juste pour le plaisir, pas prêt pour la production pour le moment).

https://github.com/losnir/ampel

Il est très opiniâtre et soutient actuellement:

  • GET Utilisation de la sélection à tour de rôle (1: 1)
  • POSTUtilisation du fractionnement des demandes. Il n'y a pas de concept de «maître» et d '«ombre» - le premier serveur principal qui répond est celui qui servira la demande du client, puis toutes les autres réponses seront rejetées.

Si quelqu'un le trouve utile, je peux l'améliorer pour être plus flexible.

losnir
la source
Node.js est un choix de langue très étrange pour une application comme celle-ci qui va nécessiter des performances très élevées. Je ne suis pas sûr que ce sera jamais prêt pour la production.
Michael Hampton
Tu as tout à fait raison. Ce n'était pas censé être très performant - juste facile à écrire (pour moi). Je pense que cela dépend de la charge requise. J'ai réussi à atteindre un peu plus de 1000 tr / min sur une machine bas de gamme (2 cœurs).
losnir
0

mon entreprise avait une exigence similaire, cloner un paquet et l'envoyer à un autre hôte (nous exécutons des simulateurs de données de marché et avions besoin d'une solution temporaire qui écouterait un flux TCP de données de marché, ingérerait chaque paquet mais enverrait également un clone de chaque paquet à un autre simulateur serveur)

ce binaire fonctionne très bien, c'est une version de TCP Duplicator mais écrit en golang au lieu de jscript, donc son chemin plus rapide, et fonctionne comme annoncé,

https://github.com/mkevac/goduplicator

perfecto25
la source
-1

il y a un outil créé par un gars d'une entreprise chinoise, et c'est peut-être ce dont vous avez besoin: https://github.com/session-replay-tools/tcpcopy

Musikoder
la source
2
Salut et bienvenue sur serverfault. Pouvez-vous fournir une réponse plus détaillée? Que fait exactement le programme? Est-ce écrit en C ...?
bgtvfr