4 votes

renifler les données du trafic mobile

Je suis en train de préparer un laboratoire de tests d'automatisation pour notre département mobile composé principalement d'appareils Android.

Pour la première phase, j'ai besoin de renifler le dispositif HTTP, je ne peux pas le faire sur le dispositif car ils ne sont pas tous enracinés et tous les dispositifs ne sont pas 4.0 et plus afin qu'ils puissent utiliser des solutions basées sur le VPN.

J'envisage un proxy qui sera défini dans les "paramètres avancés" de l'appareil wifi et qui DEVRAIT créer des fichiers .txt avec les en-têtes de la demande et le corps de la réponse (puisqu'il n'y a pas de format spécial et que c'est du texte brut, cela devrait fonctionner parfaitement pour moi).

J'aborderai la question du HTTPS plus tard, si nécessaire.

Ma question est la suivante : quel serveur proxy sera le plus rapide à configurer et quel script pour une telle action ? Je suppose qu'il n'y aura pas plus de 10-15 appareils qui peuvent faire une demande en même temps, la charge ne sera pas un gros problème dans ma configuration, mais s'assurer que chaque appareil a ses propres données imprimées dans des fichiers l'est.

Je sais que squid existe et tinyproxy, je sais que Apache a un proxy_mod qui pourrait faire l'affaire, mais je ne suis pas sûr qu'il réponde à mes besoins. La machine du serveur est un linux donc aucun bidouilleur ne viendra à mon aide.

5voto

Mike Pennington Points 8236

Je peux penser à deux options :

  • Proxy HTTP linux avec wireshark
  • Capture du réseau

Il semble que vous préfériez utiliser la méthode du proxy HTTP de Linux, mais j'inclus également les informations de capture réseau.

Capture de proxy HTTP

Utilice Python-proxy avec la modification du code source que j'ai ajoutée en bas de la page. Par défaut, Python-proxy n'écoute que sur localhost. Une petite modification dans son script le fait écouter sur tous les ports :

if __name__ == '__main__':
    start_server(host='0.0.0.0')

Après avoir enregistré le fichier dans linux, vous pouvez l'exécuter en tant qu'utilisateur non privé avec python PythonProxy.py Maintenant, configurez vos clients Android pour passer par l'IP du serveur linux sur tcp/8080.

Python-proxy ne prend pas en charge HTTPS. Il existe d'autres projets de proxy Python comme mitmproxy qui prennent en charge https, mais je n'ai pas eu autant de succès avec eux (là encore, je déploie généralement tout dans un environnement de type virtualenv qui n'est pas compatible avec certains projets Python).

Une autre option pour le proxying du trafic SSL sur linux est CharlesProxy mais je ne l'ai jamais utilisé. C'est un produit commercial pourtant...

Capture de réseau

De nombreux commutateurs gérés (par exemple Cisco / Juniper / HP / etc.) reflètent le trafic d'un port Ethernet vers un autre port Ethernet avec une configuration très simple sur le commutateur.

           |               |
           | <--  wifi --> |
+-------+  |               |  +---------+ Eth     +-----------------+
| phone |--+               +--| Wifi AP |---------| Ethernet Switch |
+-------+                     +---------+         +-----------------+

                                                ^^^^^^ Sniff here

Cette méthode ne permet pas de décrypter une capture https.


### PythonProxy.py

# <PythonProxy.py>
#
#Copyright (c) <2009> <Fábio Domingues - fnds3000 in gmail.com>
#
#Permission is hereby granted, free of charge, to any person
#obtaining a copy of this software and associated documentation
#files (the "Software"), to deal in the Software without
#restriction, including without limitation the rights to use,
#copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the
#Software is furnished to do so, subject to the following
#conditions:
#
#The above copyright notice and this permission notice shall be
#included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
#OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#OTHER DEALINGS IN THE SOFTWARE.

"""\
Copyright (c) <2009> <Fábio Domingues - fnds3000 in gmail.com> <MIT Licence>

                  **************************************
                 *** Python Proxy - A Fast HTTP proxy ***
                  **************************************

Neste momento este proxy é um Elie Proxy.

Suporta os métodos HTTP:
 - OPTIONS;
 - GET;
 - HEAD;
 - POST;
 - PUT;
 - DELETE;
 - TRACE;
 - CONENCT.

Suporta:
 - Conexões dos cliente em IPv4 ou IPv6;
 - Conexões ao alvo em IPv4 e IPv6;
 - Conexões todo o tipo de transmissão de dados TCP (CONNECT tunneling),
     p.e. ligações SSL, como é o caso do HTTPS.

A fazer:
 - Verificar se o input vindo do cliente está correcto;
   - Enviar os devidos HTTP erros se não, ou simplesmente quebrar a ligação;
 - Criar um gestor de erros;
 - Criar ficheiro log de erros;
 - Colocar excepções nos sítios onde é previsível a ocorrência de erros,
     p.e.sockets e ficheiros;
 - Rever tudo e melhorar a estrutura do programar e colocar nomes adequados nas
     variáveis e métodos;
 - Comentar o programa decentemente;
 - Doc Strings.

Funcionalidades futuras:
 - Adiconar a funcionalidade de proxy anónimo e transparente;
 - Suportar FTP?.

(!) Atenção o que se segue só tem efeito em conexões não CONNECT, para estas o
 proxy é sempre Elite.

Qual a diferença entre um proxy Elite, Anónimo e Transparente?
 - Um proxy elite é totalmente anónimo, o servidor que o recebe não consegue ter
     conhecimento da existência do proxy e não recebe o endereço IP do cliente;
 - Quando é usado um proxy anónimo o servidor sabe que o cliente está a usar um
     proxy mas não sabe o endereço IP do cliente;
     É enviado o cabeçalho HTTP "Proxy-agent".
 - Um proxy transparente fornece ao servidor o IP do cliente e um informação que
     se está a usar um proxy.
     São enviados os cabeçalhos HTTP "Proxy-agent" e "HTTP_X_FORWARDED_FOR".

"""

import socket, thread, select

__version__ = '0.1.0 Draft 1'
BUFLEN = 8192
VERSION = 'Python Proxy/'+__version__
HTTPVER = 'HTTP/1.1'

class ConnectionHandler:
    def __init__(self, connection, address, timeout):
        self.client = connection
        self.client_buffer = ''
        self.timeout = timeout
        self.method, self.path, self.protocol = self.get_base_header()
        if self.method=='CONNECT':
            self.method_CONNECT()
        elif self.method in ('OPTIONS', 'GET', 'HEAD', 'POST', 'PUT',
                             'DELETE', 'TRACE'):
            self.method_others()
        self.client.close()
        self.target.close()

    def get_base_header(self):
        while 1:
            self.client_buffer += self.client.recv(BUFLEN)
            end = self.client_buffer.find('\n')
            if end!=-1:
                break
        print '%s'%self.client_buffer[:end]#debug
        data = (self.client_buffer[:end+1]).split()
        self.client_buffer = self.client_buffer[end+1:]
        return data

    def method_CONNECT(self):
        self._connect_target(self.path)
        self.client.send(HTTPVER+' 200 Connection established\n'+
                         'Proxy-agent: %s\n\n'%VERSION)
        self.client_buffer = ''
        self._read_write()        

    def method_others(self):
        self.path = self.path[7:]
        i = self.path.find('/')
        host = self.path[:i]        
        path = self.path[i:]
        self._connect_target(host)
        self.target.send('%s %s %s\n'%(self.method, path, self.protocol)+
                         self.client_buffer)
        self.client_buffer = ''
        self._read_write()

    def _connect_target(self, host):
        i = host.find(':')
        if i!=-1:
            port = int(host[i+1:])
            host = host[:i]
        else:
            port = 80
        (soc_family, _, _, _, address) = socket.getaddrinfo(host, port)[0]
        self.target = socket.socket(soc_family)
        self.target.connect(address)

    def _read_write(self):
        time_out_max = self.timeout/3
        socs = [self.client, self.target]
        count = 0
        while 1:
            count += 1
            (recv, _, error) = select.select(socs, [], socs, 3)
            if error:
                break
            if recv:
                for in_ in recv:
                    data = in_.recv(BUFLEN)
                    if in_ is self.client:
                        out = self.target
                    else:
                        out = self.client
                    if data:
                        out.send(data)
                        count = 0
            if count == time_out_max:
                break

def start_server(host='localhost', port=8080, IPv6=False, timeout=60,
                  handler=ConnectionHandler):
    if IPv6==True:
        soc_type=socket.AF_INET6
    else:
        soc_type=socket.AF_INET
    soc = socket.socket(soc_type)
    soc.bind((host, port))
    print "Serving on %s:%d."%(host, port)#debug
    soc.listen(0)
    while 1:
        thread.start_new_thread(handler, soc.accept()+(timeout,))

if __name__ == '__main__':
    start_server(host='0.0.0.0')

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