Wire: Herramientas de captura de red para desarrolladores de API

Lane LiaBraaten, equipo de API de datos de Google
Junio de 2007

Introducción

El desarrollo de aplicaciones que interactúan con los servicios web plantea un conjunto único de problemas. Una fuente frecuente de frustración es no saber exactamente qué mensaje se envió al servidor ni qué respuesta se recibió. Algunos de los errores más difíciles de localizar son causados por una desconexión entre lo que creemos que estamos enviando al servidor y lo que realmente sucede.

En este artículo, se presentan varias herramientas que pueden ayudar a que los datos sobre el cable sean más visibles y útiles. Estas herramientas, conocidas comúnmente como "husmeadores de paquetes", capturan todos los paquetes de red que se mueven en la interfaz de red. Examinar el contenido de estos paquetes y el orden en el que se enviaron y recibieron puede ser una técnica útil de depuración.

Ejemplo: recuperación de un feed público

Estoy armando un equipo de ciclismo para un viaje de caridad y creé un calendario para eventos como sesiones informativas, campañas de recaudación de fondos para equipos y viajes de capacitación. Se estableció este calendario como público para que los miembros del equipo y otros pasajeros puedan ver el calendario y participar en los eventos. También quiero enviar un boletín informativo con los próximos eventos, de modo que, en lugar de copiar la información del sitio web de Calendario de Google, puedo usar la API de datos de Calendario de Google para consultar este calendario y recuperar eventos.

La documentación de la API del Calendario de Google tiene información sobre cómo utilizar la API de datos RESTful de Google para interactuar con mi calendario de forma programática. (Nota del editor: a partir de la versión 3, la API del Calendario de Google ya no usa el formato de datos de Google). Lo primero que debes hacer es hacer clic en el botón de la página de configuración del calendario para obtener la URL del feed de eventos del calendario.

http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic

Si uso la documentación de Calendario de Google como referencia, puedo recuperar y mostrar eventos de calendario como este, en los que PUBLIC_FEED_URL contiene la URL del feed de eventos.

CalendarService myService = new CalendarService("exampleCo-fiddlerExample-1");
final String PUBLIC_FEED_URL = "http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic";
URL feedUrl = new URL(PUBLIC_FEED_URL);
CalendarEventFeed resultFeed = myService.getFeed(feedUrl, CalendarEventFeed.class);

System.out.println("All events on your calendar:");
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEventEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
System.out.println();

Esto muestra una lista básica de los eventos de mi calendario:

All events on your calendar:
    MS150 Training ride
    Meeting with Nicole
    MS150 Information session

El fragmento de código anterior muestra los títulos de los eventos del calendario, pero ¿qué ocurre con el resto de los datos que recibimos del servidor? La biblioteca cliente de Java no facilita la salida de un feed o una entrada como XML. Incluso si lo hiciera, el XML no era completo. ¿Qué sucede con los encabezados HTTP que acompañan a la solicitud? ¿La consulta se envió por proxy o se redireccionó? Con operaciones más complejas, estas preguntas se vuelven cada vez más importantes, especialmente cuando algo sale mal y recibimos errores. El software de detección de paquetes puede responder estas preguntas al revelar el tráfico de la red.

tcpdump

tcpdump es una herramienta de línea de comandos que funciona en plataformas similares a Unix, pero también hay un puerto de Windows llamado WinDump. Al igual que la mayoría de los detectores de paquetes, tcpdump pone su tarjeta de red en modo promiscuo, lo que requiere privilegios de superusuario. Si desea usar tcpdump, especifique la interfaz de red para escuchar y el tráfico de red se enviará a stdout:

sudo tcpdump -i eth0

Si ejecutas este comando, se verá bombardeado por todo tipo de tráfico de red, algunos de los cuales no reconocerás. Simplemente podría reenviar la salida a un archivo y grep aunque más adelante, pero eso podría generar algunos archivos muy grandes. La mayoría de los software de captura de paquetes tienen algunos mecanismos de filtrado incorporados para que solo captures lo que necesitas.

tcpdump admite el filtrado según varias características del tráfico de red. Por ejemplo, puede indicarle a tcpdump que solo capture el tráfico desde o hacia el servidor en el puerto 80 (mensajes HTTP) al insertar el nombre de host de su servidor en la siguiente expresión:

dst or src host <hostname> and port 80

Para cada paquete que coincida con la expresión de filtro, tcpdump mostrará una marca de tiempo, la fuente y el destino del paquete, y varias marcas de TCP. Esta información puede ser valiosa, ya que muestra el orden en que se enviaron y recibieron los paquetes.

A menudo, también es útil ver el contenido de los paquetes. La marca "-A" le indica a tcpdump que imprima cada paquete en ASCII, lo que expone los encabezados HTTP y el cuerpo del mensaje. La marca "-s" se utiliza para especificar la cantidad de bytes que se mostrarán (donde "-s 0" significa que no se truncará el cuerpo del mensaje).

Con todo esto, podemos obtener el siguiente comando:

sudo tcpdump -A -s 0 -i eth0 dst or src host <hostname> and port 80

Si ejecutas este comando y ejecutas el ejemplo corto de .Java que se mencionó antes, verás toda la comunicación de red que se usa en esta operación. Entre el tráfico, verás la solicitud HTTP GET:

22:22:30.870771 IP dellalicious.mshome.net.4520 > po-in-f99.google.com.80: P 1:360(359) ack 1 win 65535
E.....@....\...eH..c...P.=.....zP......GET /calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic HTTP/1.1
User-Agent: exampleCo-fiddlerExample-1 GCalendar-Java/1.0.6 GData-Java/1.0.10(gzip)
Accept-Encoding: gzip
Cache-Control: no-cache
Pragma: no-cache
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

También verás el mensaje de respuesta de 200 OK que contiene el feed de datos de Google. Tenga en cuenta que el feed está dividido en cuatro paquetes:

22:22:31.148789 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 1:1431(1430) ack 360 win 6432
E...1 ..2.I.H..c...e.P.....z.=.:P..M...HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8
Cache-Control: max-age=0, must-revalidate, private
Last-Modified: Mon, 11 Jun 2007 15:11:40 GMT
Transfer-Encoding: chunked
Date: Sun, 24 Jun 2007 02:22:10 GMT
Server: GFE/1.3

13da
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gCal='http://sc
hemas.google.com/gCal/2005' xmlns:gd='http://schemas.google.com/g/2005'><id>http
://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.goo
gle.com/public/basic</id><updated>2007-06-11T15:11:40.000Z</updated><category sc
heme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2
005#event'></category><title type='text'>MS150 Training Schedule</title><subtitl
e type='text'>This calendar is public</subtitle><link rel='http://schemas.google
.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calend
ar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic'></
link><link rel='self' type='application/atom+xml' href='http://www.google.com/ca
lendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic
?max-results=25'></link><author><name>Lane LiaBraaten</name><email>api.lliabraa@
gmail.com</email></author><generator version='1.0' uri='http://www.google.com/ca
lendar'>Google Calendar</generator><openSearch:totalRe


22:22:31.151501 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 1431:2861(1430) ack 360 win 6432
E...1!..2.I.H..c...e.P.......=.:P.. 2...sults>3</openSearch:totalResults><openSe
arch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch
:itemsPerPage><gd:where valueString=''></gd:where><gCal:timezone value='America/
Los_Angeles'></gCal:timezone><entry><id>http://www.google.com/calendar/feeds/24v
j3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/dgt40022cui2k3j
740hnj46744</id><published>2007-06-11T15:11:05.000Z</published><updated>2007-06-
11T15:11:05.000Z</updated><category scheme='http://schemas.google.com/g/2005#kin
d' term='http://schemas.google.com/g/2005#event'></category><title type='text'>M
S150 Training ride</title><summary type='html'>When: Sat Jun 9, 2007 7am to 10am

&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Status:     confirmed</summary><conte
nt type='text'>When: Sat Jun 9, 2007 7am to 10am&amp;nbsp; PDT&lt;br&gt;   &lt;b
r&gt;Event Status:     confirmed</content><link rel='alternate' type='text/html'
 href='http://www.google.com/calendar/event?eid=ZGd0NDAwMjJjdWkyazNqNzQwaG5qNDY3
NDQgMjR2ajNtNXBsMTI1YmgyaWpiYm5laDk1M3NAZw' title='alternate'></link><link rel='
self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/24v
j3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/dgt40022cui2k3j
740hnj46744'></link><author><name>MS150 Training Schedule</name></author><gCal:s
endEventNotifications value='false'></gCal:sendEventNotifications></entry><entry

><id>http://www.google.com/cal

22:22:31.153097 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 2861:4291(1430) ack 360 win 6432
E...1#..2.I.H..c...e.P.......=.:P.. ....endar/feeds/24vj3m5pl125bh2ijbbneh953s%4
0group.calendar.google.com/public/basic/51d8kh4s3bplqnbf1lp6p0kjp8</id><publishe
d>2007-06-11T15:08:23.000Z</published><updated>2007-06-11T15:10:39.000Z</updated
><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.g
oogle.com/g/2005#event'></category><title type='text'>Meeting with Nicole</title

><summary type='html'>When: Mon Jun 4, 2007 10am to 11am&amp;nbsp; PDT&lt;br&gt;
  &lt;br&gt;Where: Conference Room B &lt;br&gt;Event Status:     confirmed</summ
ary><content type='text'>When: Mon Jun 4, 2007 10am to 11am&amp;nbsp; PDT&lt;br&
gt;  &lt;br&gt;Where: Conference Room B &lt;br&gt;Event Status:     confirmed

&lt;br&gt;Event Description: Discuss building cycling team for MS150</content><l
ink rel='alternate' type='text/html' href='http://www.google.com/calendar/event?
eid=NTFkOGtoNHMzYnBscW5iZjFscDZwMGtqcDggMjR2ajNtNXBsMTI1YmgyaWpiYm5laDk1M3NAZw'
title='alternate'></link><link rel='self' type='application/atom+xml' href='http
://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.goo
gle.com/public/basic/51d8kh4s3bplqnbf1lp6p0kjp8'></link><author><name>MS150 Trai
ning Schedule</name></author><gCal:sendEventNotifications value='false'></gCal:s
endEventNotifications></entry><entry><id>http://www.google.com/calendar/feeds/24
vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/va41amq3r08dhh
kpm3lc1abs2o</id><published>20


22:22:31.190244 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: P 4291:5346(1055) ack 360 win 6432
E..G1$..2.K.H..c...e.P.....<.=.:P.. ....07-06-11T15:10:08.000Z</published><updat
ed>2007-06-11T15:10:08.000Z</updated><category scheme='http://schemas.google.com
/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title ty
pe='text'>MS150 Information session</title><summary type='html'>When: Wed Jun 6,
 2007 4pm to Wed Jun 6, 2007 5pm&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Statu
s:     confirmed</summary><content type='text'>When: Wed Jun 6, 2007 4pm to Wed
Jun 6, 2007 5pm&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Status:     confirmed<

/content><link rel='alternate' type='text/html' href='http://www.google.com/cale
ndar/event?eid=dmE0MWFtcTNyMDhkaGhrcG0zbGMxYWJzMm8gMjR2ajNtNXBsMTI1YmgyaWpiYm5la
Dk1M3NAZw' title='alternate'></link><link rel='self' type='application/atom+xml'
 href='http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.c
alendar.google.com/public/basic/va41amq3r08dhhkpm3lc1abs2o'></link><author><name
>MS150 Training Schedule</name></author><gCal:sendEventNotifications value='fals
e'></gCal:sendEventNotifications></entry></feed>

Esta salida incluye todos los encabezados y el contenido HTTP, así como varias marcas de TCP encriptadas. Todos los datos están presentes aquí, pero es un tanto difícil de leer y comprender. Existen varias herramientas gráficas que facilitan la visualización de estos datos.

WireShark (anteriormente etérea)

Captura de pantalla de Wireshark
WireShark muestra el tráfico de red de varias maneras.

WireShark es una herramienta gráfica compilada con libpcap, la misma biblioteca en la que se basa tcpdump, y se encuentra disponible en Linux, Mac OS X y Windows. La GUI de WireShark habilita varias formas nuevas de interpretar los datos de captura de paquetes e interactuar con ellos. Por ejemplo, a medida que los paquetes se capturan desde la interfaz de red, se muestran en diferentes colores según el protocolo que usen. También puedes ordenar el tráfico por marca de tiempo, origen, destino y protocolo.

Si seleccionas una fila en la lista de paquetes, Wireshark mostrará IP, TCP y otra información específica del protocolo en los encabezados de los paquetes en un árbol legible. Los datos también se muestran en formato hexadecimal y ASCII en la parte inferior de la pantalla.

Si bien la naturaleza visual de WireShark hace que el tráfico de red sea más fácil de comprender, en la mayoría de los casos se recomienda que filtres el tráfico de red. WireShark tiene capacidades sólidas de filtrado, incluida la compatibilidad con cientos de protocolos.

SUGERENCIA: Para ver los protocolos disponibles y compilar filtros complejos, haz clic en el botón cerca de la parte superior de la ventana de WireShark.

Para volver a crear el filtro que se usó en el ejemplo anterior de tcpdump, puede insertar la siguiente expresión en el cuadro de filtro de WireShark:

ip.addr==<your IP address> && tcp.port==80

O aprovecha el conocimiento de WireShark sobre HTTP:

ip.addr==<your IP address> && http

De este modo, se filtrarán los resultados de la captura únicamente para los paquetes que participen en la interacción con el servidor de Calendario de Google. Puedes hacer clic en cada paquete para ver el contenido y unir la transacción.

SUGERENCIA: Puede hacer clic con el botón derecho en uno de los paquetes y elegir "Seguir TCP Stream" para mostrar las solicitudes y respuestas de manera secuencial en una sola ventana.

WireShark ofrece varias formas de guardar la información de la captura. Puedes guardar uno, algunos o todos los paquetes. Si está viendo una transmisión TCP, puede hacer clic en el botón "Guardar como" para guardar solo los paquetes relevantes. También puedes importar el resultado de una captura de tcpdump y verlo en WireShark.

Un problema: SSL y encriptación

La falta de herramientas de captura de paquetes es la incapacidad de ver los datos encriptados mediante una conexión SSL. En el ejemplo anterior se accede a un feed público, por lo que no se requiere SSL. Sin embargo, si el ejemplo accede a un feed privado, el cliente necesitará autenticarse con el servicio de autenticación de Google, que requiere una conexión SSL.

El siguiente fragmento es similar al ejemplo anterior, pero aquí la CalendarService solicita el metafeed del calendario del usuario, que es un feed privado que requiere autenticación. Para autenticarte, solo debes llamar al método setUserCredentials. Este método activa una solicitud HTTPS al servicio ClientLogin y toma el token de autenticación de la respuesta. El objeto CalendarService incluirá el token de autenticación en todas las solicitudes posteriores.

CalendarService myService = new CalendarService("exampleCo-fiddlerSslExample-1");
myService.setUserCredentials(username, userPassword);
final String METAFEED_URL = "http://www.google.com/calendar/feeds/default";
URL feedUrl = new URL(METAFEED_URL);
CalendarFeed resultFeed = myService.getFeed(feedUrl, CalendarFeed.class);

System.out.println("Your calendars:");
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
System.out.println();

Considere el tráfico de red necesario para autenticarse y acceder a un feed privado de la API de datos de Google:

  1. Enviar credenciales de usuario al servicio ClientLogin
    • Envía un POST HTTP a https://www.google.com/accounts/ClientLogin con los siguientes parámetros en el cuerpo del mensaje:
      • Correo electrónico: la dirección de correo electrónico del usuario.
      • Contraseña: La contraseña del usuario.
      • source: identifica tu aplicación cliente. Debe tener el formato companyName-applicationName-versionID. Los ejemplos usan el nombre ExampleCo-FiddlerSSLExample-1.
      • servicio: El nombre del servicio de Calendario de Google es "cl".
  2. Recibir el token de autorización
    • Si la solicitud de autenticación falla, recibirás un código de estado HTTP 403 Prohibido.
    • Si el proceso se realiza correctamente, la respuesta del servicio será un código de estado HTTP 200 OK, más tres códigos alfanuméricos largos en el cuerpo de la respuesta: SID, LSID y Auth. El valor Auth es el token de autorización.
  3. Solicitar metafeed de calendario privado
    • Envía una GET HTTP a http://www.google.com/calendar/feeds/default con el siguiente encabezado:
    • Authorization: GoogleLogin auth=<yourAuthToken>
      

Intenta ejecutar este fragmento y ver el tráfico de red en WireShark (utilizando "http || ssl" como filtro). Verás los paquetes SSL y TLS involucrados en la transacción, pero los paquetes de solicitud y respuesta de ClientLogin están encriptados en los paquetes "Datos de aplicación". No se preocupe. A continuación, analizaremos una herramienta que puede revelar esta información encriptada.

Fiddler

Fiddler es otra herramienta gráfica de detección de paquetes, pero su comportamiento es distinto al de las herramientas presentadas hasta el momento. Fiddler actúa como un proxy entre su aplicación y los servicios remotos con los que interactúa, por lo que se convierte efectivamente en un intermediario. Fiddler establece una conexión SSL tanto con su aplicación como con el servicio web remoto, desencriptando el tráfico desde un extremo, capturando el texto sin formato y volviendo a encriptar el tráfico antes de enviarlo. Lamentablemente, Fiddler solo está disponible en Windows y para todos los usuarios de Mac y Linux.

Nota: La compatibilidad con SSL requiere la versión 2 de Fiddler y la versión 2 .0 de.NET Framework.

La visualización del tráfico de red en Fiddler se realiza principalmente a través de la pestaña Inspector de sesiones. Las pestañas secundarias más útiles para depurar problemas con las API de datos de Google son:

  • Encabezados: Muestra los encabezados HTTP en un formato de árbol que se puede contraer.
  • Auth: Muestra los encabezados de Authentication.
  • Sin procesar: Muestra el contenido de los paquetes de red en texto ASCII.

SUGERENCIA: Haz clic en el ícono en la esquina inferior izquierda de la ventana de Fiddler para activar y desactivar la captura.

Fiddler usa .NET Framework para configurar conexiones de red a fin de usar Fiddler como proxy. Esto significa que todas las conexiones que realices con Internet Explorer o con el código .NET aparecerán en Fiddler de manera predeterminada. Sin embargo, el tráfico de la muestra de Java anterior no se mostrará debido a que Java tiene una forma diferente de configurar los proxies HTTP.

En Java, puedes configurar el proxy HTTP con las propiedades del sistema. Fiddler se ejecuta en el puerto 8888, por lo que para una instalación local puede hacer que el código de Java use Fiddler como un proxy para HTTP y HTTPS. Para ello, agregue estas líneas:

System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "8888");
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8888");

Si ejecutas la muestra con estas líneas, en realidad obtendrás un seguimiento de pila desagradable del paquete de seguridad de Java:

[java] Caused by:
  sun.security.validator.ValidatorException: PKIX path building failed:
  sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Captura de pantalla de Fiddler
Fiddler puede desencriptar y mostrar el tráfico SSL.

Este error se produce cuando no se puede verificar el certificado que muestra el servidor en una conexión SSL. En este caso, el certificado incorrecto proviene de Fiddler y actúa como intermediario. Fiddler genera certificados sobre la marcha y, debido a que no es un emisor de confianza, los certificados harán que Java falle en la configuración de la conexión SSL.

Nota: Cuando esté ejecutando Fiddler, todas las conexiones SSL que cree en Internet Explorer activarán una "Alerta de seguridad" que le preguntará si desea continuar a pesar del certificado sospechoso. Puedes hacer clic en "Ver certificado" para ver el certificado que generó Fiddler.

Entonces, ¿cómo puede evitar esta excepción de seguridad? Básicamente, debe volver a configurar el marco de trabajo de seguridad de Java para confiar en todos los certificados. Afortunadamente, no es necesario reinventar la rueda. Consulta la solución de Francis Labrie y agrega el método SSLUtilities.trustAllHttpsCertificates() al ejemplo anterior.

Una vez que hayas configurado Java para usar Fiddler como proxy, además de haber inhabilitado la verificación de certificados predeterminada, puedes ejecutar el ejemplo y ver todo el tráfico que se envía por cable en texto simple. ¡No me roben la contraseña!

Recuerda que esta transacción de autenticación es solo un pequeño ejemplo del tráfico SSL. Algunas aplicaciones web utilizan conexiones SSL exclusivamente, por lo que la depuración del tráfico HTTP está fuera de la pregunta sin una manera de desencriptar los datos.

Conclusión

tcpdump está disponible en Linux, Mac OS X y Windows, y es una excelente herramienta para saber lo que está buscando y solo necesita hacer una captura rápida. Sin embargo, existen algunas herramientas gráficas que presentan el tráfico de red en formatos que son más fáciles de comprender. tcpdump tiene muchas más opciones y capacidades de filtrado que las que se abarcaron aquí. Para obtener una descripción completa de la funcionalidad de tcpdump, escriba “man tcpdump” o visite la página del manual de tcpdump en línea.

WireShark también está disponible en Linux, Mac OS X y Windows. La compatibilidad integrada con cientos de protocolos hace que WireShark sea una herramienta útil para muchas aplicaciones, no solo la depuración HTTP. Esta introducción apenas cubre la superficie de las múltiples capacidades de WireShark. Para obtener más información, escribe "hombre tiburón" o visita el sitio web de WireShark.

Fiddler también tiene muchas características excelentes, pero lo que la distingue del resto es su capacidad para desencriptar el tráfico SSL. Para obtener más información, visita el sitio web de Fiddler2.

Estas aplicaciones de detección de paquetes son excelentes herramientas para usar en tu cinturón de herramientas, y los lectores observadores habrán notado que todas son gratuitas. La próxima vez que trabaje con las API de Google y vea algo sospechoso, extraiga uno de estos analizadores de redes y analice en detalle el contenido de cada canal. Si no encuentras el problema, puedes publicar una pregunta en nuestro grupo de discusión. Si incluyes los mensajes de red relevantes, ayudarás a otros usuarios a comprender y diagnosticar tu problema en particular.

Buena suerte y olores.

Recursos