4 votes

Comment inverser le proxy des paquets TCP bruts ?

Je suis en train de concevoir un système dans lequel des dispositifs distants envoient en toute sécurité des mises à jour d'état à un serveur central d'enregistrement pour agrégation. Sur le serveur, j'utilise la solution Redis + Logstash + Elasticsearch. Les données envoyées au serveur sont sensibles et doivent être cryptées. Je m'efforce de trouver un moyen efficace et sûr de "LPUSH" les journaux à la liste Redis.

Les appareils sont actuellement capables d'envoyer la commande Redis suivante directement au port 6379.

"*3\r\n$5\r\nLPUSH\r\n$3\r\nkey\r\n$5\r\nvalue\r\n"

La clé correcte et l'entrée de la liste sont créées dans Redis sur le serveur.

L'étape suivante consiste à placer redis derrière un pare-feu et à crypter les paquets. Ma tentative actuelle consistait à utiliser Apache comme reverse proxy. Un appareil établit une connexion SSL bidirectionnelle avec Apache, puis renvoie les informations décryptées vers le port 6379 en utilisant l'interface de bouclage. La connexion SSL bidirectionnelle est établie sans problème et un message est transmis à Redis. Malheureusement, ce n'est pas le message que le périphérique a envoyé. tcpdump me dit ce qui suit...

tcpdump -nnXvv -i lo host localhost and port 6379

127.0.0.1.48916 > 127.0.0.1.6379: Flags [P.], cksum 0xfeab (incorrect -> 0x9415),
seq 1:132, ack 1, win 1025, options [nop,nop,TS val 299310518 ecr 299310518], 
length 131
0x0000:  4500 00b7 12b7 4000 4006 2988 7f00 0001  E.....@.@.).....
0x0010:  7f00 0001 bf14 18eb ce9c 0f04 e920 abec  ................
0x0020:  8018 0401 feab 0000 xxxx xxxx xxxx xxxx  ................
0x0030:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  ....*3./.HTTP/1.
0x0040:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  1..Host:.localho
0x0050:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  st:6379..X-Forwa
0x0060:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  rded-For:.xx.xxx
0x0070:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  .xxx.xxx..X-Forw
0x0080:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  arded-Server:.xx
0x0090:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  .xxx.xxx.xx..Con
0x00a0:  xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx  nection:.Keep-Al
0x00b0:  xxxx xxxx xxxx xx                        ive....

Comme on peut le voir dans la traduction ASCII, Apache tronque le message au premier CRLF après *3 et ajoute des informations d'en-tête HTTP pour le transfert, comme il est censé le faire. Bien sûr, Redis répond avec une erreur car le message n'est plus formaté en utilisant le Redis Serialization Protocol (RESP).

1) Existe-t-il un moyen de configurer Apache pour qu'il transfère aveuglément les paquets TCP bruts ?

2) Sinon, existe-t-il une solution standard à code source ouvert pour résoudre ce problème ?

Merci pour votre temps !

1 votes

Qu'essayez-vous de faire que le simple transfert de port NAT ne peut pas accomplir ?

0 votes

@MichaelHampton cryptage.

1 votes

Je choisirais un tunnel SSH et non un proxy.

1voto

Twitch Points 101

Si tout fonctionne, à l'exception des ajouts d'Apache aux en-têtes, vous pouvez les désactiver via mod_headers : http://httpd.apache.org/docs/2.2/mod/mod_headers.html

0 votes

Merci ! mod_headers semblait prometteur. Cependant, pour s'assurer que la commande Redis n'est pas modifiée, tous les en-têtes devraient être complètement supprimés. Après quelques recherches, il semble que le module Serveur en-tête ne peut pas être retiré .

0 votes

Je m'avance un peu, mais peut-être que POST en PHP et ensuite dépouiller tout ce dont vous n'avez pas besoin.

0 votes

Oui, nous avons lancé cette idée ici aussi. Il est regrettable d'avoir besoin d'une colle comme celle-là, mais je suppose que c'est justifié étant donné qu'Apache n'est probablement pas l'outil pour ce travail de toute façon. Merci pour votre temps.

1voto

Nathan Crock Points 333

Bien que mon intuition me dise qu'Apache+PHP n'est pas une solution optimale, c'était une solution rapide et jusqu'à présent satisfaisante. Apache envoie le message HTTP au script PHP script où le message est extrait et transmis à redis en utilisant l'interface loopback. Pour la 'postérité', j'ai collé une version squelette du script ici.

<?php
    $file = fopen("/some/logging.txt","a");
    $entityBody = file_get_contents('php://input');
    $redisSocket = fsockopen("localhost", 6379, $errno, $errstr, 30);
    if (!$redisSocket) {
        fwrite($file, "Error: $errstr ($errno)\n");
    } else {
        fwrite($redisSocket, "$entityBody");
        $redisResponse = fgets($redisSocket);
        if (!$redisResponse) {
            fwrite($file, "No response from Redis");
        } else {
            fwrite($file, "Redis Response: $redisResponse");
        }
    }
?>

J'essaie d'éviter de "coller" les choses avec des scripts dans la mesure du possible, mais jusqu'à présent, cela a fourni les avantages supplémentaires de me permettre de vérifier l'intégrité des données d'entrée et de créer des journaux et des réponses personnalisés.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X