web-dev-qa-db-fra.com

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

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 ( https://stackoverflow.com/questions/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). Aucun 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 entrant TCP trafic 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 interrompus après chaque demande/connexion par un client sans préavis ni journal. Keepalive n'a pas changé cette situation. TCP Les packages 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/ , https: // stackoverflow .com/questions/9024227/duplicate-input-unix-stream-to-multiple-tcp-clients-using-socat ) et des outils similaires ont échoué, car la fonction TEE fournie écrit dans FS uniquement.
  • 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 source différente pour 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')

Les commentaires pour utiliser ce script:
Ce script transfère un certain nombre de ports locaux configurés vers un autre serveur local et un serveur 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:
Divisez chaque ligne de configuration avec des espaces
0: port local à écouter
1: port local vers lequel transférer
2: adresse IP distante du serveur de destination
3: port distant du serveur de destination
et retourner les paramètres

33
Sise

C'est impossible. TCP est un protocole d'état. 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 les rejouer. Mais cela ne donnera pas les conditions de concurrence ou de trafic exactes d'un serveur en direct.

11
Kazimieras Aliulis

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. Relisez le trafic de la production aux environnements de transfert et de développement." ?

20
Arthur Lutz

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)
7
Tombart

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.

Récupérer les paquets au niveau de la couche TCP terminaison et les relayer en tant que nouveau TCP est raisonnable. L'outil duplicateur vous lié à 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 Cela semble correspondre à la facture 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 simples, je m'attends à ce que vous rencontriez des problèmes avec cette méthodologie de test liée au 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 Edge.

4
Evan Anderson

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 processus douloureux de transfert de trafic vers un autre serveur.

1
snowbirdSkiBum

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 les données du marché TCP, ingérer chaque paquet mais aussi envoyer un clone de chaque paquet à un autre serveur de simulation)

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

https://github.com/mkevac/goduplicator

0
perfecto25

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.

Donc ... 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.

0
James

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)
  • POST Utilisation du fractionnement des demandes. Il n'y a pas de concept de "maître" et d '"ombre" - le premier backend 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.

0
losnir