4

I'm now preparing an automation testing lab for our mobile department consisting of mainly android devices.

For first phase i need HTTP device sniffing, i can't do it on the device as they are not all rooted and it's not all devices are 4.0 and above so they can use VPN based solutions.

I'm considering a proxy that will be defined in the device wifi "advanced settings" and SHOULD create .txt files with the request response headers + body (since it has no special format and is plain text is should work just fine for me).

HTTPS i'll address at a later time if needed.

My question is which proxy server will be the fastest to setup and script for such an action ? I guess there will be no more than 10-15 devices that can make a request at one time, load wont be much of an issue in my setup, but making sure each device has his own data printed into files is.

I know squid exists and tinyproxy i know apache got a proxy_mod that might do the trick , not sure if it'll suite my need. The server machine is linux so no fiddler will come for my aid.

codeScriber
  • 157
  • 4

1 Answers1

5

I can think of two options:

  • linux HTTP Proxy with wireshark
  • Network capture

It sounds like you'd prefer to use the linux HTTP Proxy method, but I'm including the Network capture info as well.

HTTP Proxy Capture

Use python-proxy, with the source code modification that I added at the bottom of the page. By default, python-proxy only listens on localhost. A small change in their script makes it listen on all ports:

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

After you save the file in linux, you can execute as an unpriv user with python PythonProxy.py Now configure your android clients to proxy through the IP of the linux server on tcp/8080.

python-proxy doesn't support HTTPS. There are other python proxy projects like mitmproxy which do support https, but I haven't had as much success with them (then again, I typically deploy everything in a virtualenv, which doesn't play well with a few python projects).

Another option for proxy-ing SSL traffic on linux, is CharlesProxy, but I have never used it. It's a commercial product though...

Network Capture

Many managed switches (i.e. Cisco / Juniper / HP / etc) will mirror one ethernet port's traffic to another ethernet port with very simple configuration on the switch.

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

                                                ^^^^^^ Sniff here

This method does not support decrypting an https capture.


### 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')
Mike Pennington
  • 8,266
  • 9
  • 41
  • 86
  • i don't have specialized hardware for the time being, just my linux server, so that's off, started trying squid, but as i said i'm not so fond of the idea since 1. it will not be suitable in the future for https and it's a monster of a proxy, too many options which i don't need but don't know i don't need :-) – codeScriber Dec 09 '13 at 08:26
  • @codeScriber, in that case just use python-proxy. I updated my answer with information on that. – Mike Pennington Dec 10 '13 at 09:53
  • actually working with mitmproxy, also i found out that Paros (java) proxy does the job. – codeScriber Dec 16 '13 at 09:41