¿Capturar paquetes de red en Android?
sockets networking (1)
Estoy trabajando en un proyecto en el que necesito capturar los paquetes entrantes / salientes y almacenarlos en un archivo pcap.
Android ha proporcionado VpnService
para este propósito, que se agregó en el Nivel 14 de API. Aunque parece que hay muchas preguntas con respecto a esto en SO, sorprendentemente, hay ejemplos menos eficaces de ello. Intenté usar ToyVpn, que se agrega en las muestras, pero no pude hacerlo funcionar. Entonces me encontré con este ejemplo.
El ejemplo resume la captura en los siguientes pasos.
- Cree una interfaz TUN (aún no estoy seguro de qué es TUN, pero navegar en Internet dice que es una emulación de la capa de red en el dispositivo).
- Obtenga el Descriptor de archivo para los paquetes entrantes y los paquetes salientes a través del TUN.
- Reenvía estos paquetes al servidor real. (¿No está seguro de qué servidor está aquí? Cada paquete saliente tiene un requestUrl , por lo que servidor aquí significa delegar la solicitud al servidor requestUrl . O servidor significa que crea su propio servidor en algún lugar en AWS y redirige todo el tráfico que a su vez redirigir el tráfico al destino real).
- Obtenga la respuesta del servidor.
- Con la ayuda de TUN, vuelva a pasar esta respuesta al componente deseado de la aplicación.
Creé un TUN usando el siguiente código. Di la dirección que se dio en el tutorial mencionado anteriormente. No estoy seguro, si hay los valores correctos. Y cómo decidir esta dirección.
Builder builder = new Builder();
ParcelFileDescriptor mInterface = builder.setSession("MyVPNService")
.addAddress("192.168.0.1", 24)
.addDnsServer("8.8.8.8")
.addRoute("0.0.0.0", 0).establish();
Luego obtuve el descriptor del archivo y abrí el túnel.
FileInputStream in = new FileInputStream(
mInterface.getFileDescriptor());
DatagramChannel tunnel = DatagramChannel.open();
// I have created a EC2 instance on AWS, and gave the ip Address and port of that server. Not sure if this is the correct method.
tunnel.connect(new InetSocketAddress("54.254.187.207", 5000));
//d. Protect this socket, so package send by it will not be feedback to the vpn service.
protect(tunnel.socket());
Luego aplicó un bucle while para leer los paquetes.
while (true) {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while(true){
String line = reader.readLine();
if(line ==null){
break;
}else{
System.out.println("line is "+line);
}
// I am guessing that here after reading the packets, I need to forward them to the actual server.
}}
que me daba la siguiente salida
02-21 19:12:26.074 16435-16778/awesomedroidapps.com.debugger I/System.out: line is E����@�''@��@������<��5��,��������������������graphfacebookcom������E����@�(@��
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is E����@0@��@����d�:�N����P�V�x�%0/�W�����
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is ��EP���
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is �%0.�%0/E����L�@��@�����Ɂ��5��8�[�����������������apploadingestcrittercismcom������E����@�:@��@�����d6�� �>�Wz� y�A�x�[����
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is ��T@�
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is y�1�y�7E����A�@��@��������5��-��-�����������������decidemixpanelcom������E������;@��@�F���d6�� �>�Wz�y�A�x������
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is ��]@���F����BA �+��q�ϔ���Jb2_''�D�y�̯��[:�1)���PΠ�ѡ���h71�L�3�=~������(�����������������S�~''U������9d_���"�I�E����@0@��@�
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is ���d�:�N����P�V�x�%0/�W������
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is ��^P���
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is �%0.�%0/E����=�@��@���������5��)l����������������t appsflyercom������E����=�@��@������6��5��)�.����������������t appsflyercom������E����@0@��@����d�:�N����P�V�x�%0/�W������
02-21 18:43:53.648 16435-16639/awesomedroidapps.com.debugger I/System.out: line is ���P���
De los registros está claro que puedo capturar los paquetes salientes en el TUN. Los registros anteriores en algún lugar imprimen hosts como facebook.com
lo que me hace creer que estoy en el camino correcto.
Pero, ¿qué debo hacer después de esto? ¿Cómo reenviar datos al servidor? Creo que hay menos ejemplos de trabajo. Pero, ¿alguien me puede dar un procedimiento paso a paso sobre cómo lograr esto?
Actualización : Después de seguir investigando, llegué a saber que necesito crear un servidor y reenviar los paquetes interceptados al servidor. Creé un servidor en mi computadora y pude reenviar con éxito los paquetes interceptados a mi servidor. Pero no estoy seguro de cómo obtener la IP y el puerto de destino reales del paquete recibido para poder enviarlos al destino deseado.
PD : También JnetPcap biblioteca JnetPcap , pero parece que para capturar los paquetes en vivo, el teléfono debe estar rooteado, lo que no es un requisito de mi aplicación.
Bastante seguro de que lo mejor es configurar un servidor proxy y luego usar algo como wireshark para monitorear el tráfico que va y viene. No soy un experto en esto, pero en los viejos tiempos antes de cambiar los enrutadores eran muy baratos, era muy fácil porque todos los paquetes se transmitían a todas las computadoras en la misma subred. Tal vez si pudiera conseguir un concentrador / enrutador que tenga la capacidad de desactivar el cambio, podría usar este método en lugar de un proxy.
En estos días, la mayoría de las comunicaciones se realiza mediante http y para eso tiene excelentes herramientas como Charles (mac) y Fiddler (windows) que hacen exactamente lo que quiere, excepto http. Es posible que al menos puedan darle ideas sobre cómo hacer lo mismo con Wireshark