Título: Como envia datos a un sitio web HTTPS via socket? | Servidor Proxy python3 Publicado por: Drakaris en 20 Julio 2020, 19:21 pm Buenas, estoy haciendo un servidor proxy con Python3. La idea es la siguiente:
1 . Primero, capturo el puerto especificado en el primer argumento: Código: if len(sys.argv) == 2: 2. Después con el puerto especificado, creo una conexion socket servidor bind(), y obtengo los datos recibidos, con ello, ejecuto un hilo, donde paso los datos de la conexion y datos a la funcion get_data. Código: print("[*] Listening Port "+str(PORT_LISTEN)+"....") 3. En la funcion get_data, obtengo la url, donde cogeré dominio donde estoy visitando Código: #get url 4. Una vez sé en que dominio estoy haciendo la petición, si el dominio contiene ":" cogeré el puerto especificado. Por defecto el puerto es 80, si no se detecto ":" en el dominio. Código: port = 80 5. Finalmente ejecuto la funcion send_data con sus argumentos, para que me haga una conexion socket cliente al servidor y envie los datos, con un bucle. Código: send_data(website, int(port), conn, data, addr, True) Esto funciona correctamente en sitios web HTTP, pero como cabe esperar, el HTTPS no, por los certificados ssl. Así que modifiqué el apartado 5. Y con una condicional, si el puerto es 443, ejecutará lo siguiente: Código: if port == 443: En send_data añadí un argumento booleano llamada SSL, que antes de hacer nada, si este es True, sería https, lo que no sé muy bien, es que hacer aquí. Me he mirado el funcionamiento de los sitios HTTPS en youtube. uNrh0zoItGI En el minuto 2:16, explica con más profundidad como trabaja este protocolo. He pensado, si hay alguna forma de obtener el certificado que me da el servidor para obtener la llave publica.... pero no se muy bien. Miré este enlace: https://soursop-dev.blogspot.com/2020/05/creacion-de-un-servidor-web-proxy-en.html Donde te explica como hacer una conexion ssl con el modulo ssl. Así que modifique la funcion send_data: Código: def send_data(site, port, conn, data, addr, SSL): Creé los certificados autofirmados: Código: $ cd ssl Como bien me imaginaba esto no funciona, ya que tendría que coger el certificado que me da el dominio al hacer la peticion. No acabo de entender muy bien en las variables de crt y key, que llaves tengo que poner... Código: server_cert = "./ssl/sechome.csr" CODE COMPLETE: Código: #!/usr/bin/python3 Título: Re: Como envia datos a un sitio web HTTPS via socket? | Servidor Proxy python3 Publicado por: el-brujo en 20 Julio 2020, 22:45 pm No tienes que crear ningún certificado para conectarte a una página web que usa https, ni crt, ni key, ni csr, ni nada. Eso es para el servidor web si fuera tuyo, pues para configurar el certificado SSL.
Para navegar o en tu caso, para enviar una petición con datos sólo tienes que usar la librería SSL y ya: Código: import ssl https://docs.python.org/3/library/ssl.html Título: Re: Como envia datos a un sitio web HTTPS via socket? | Servidor Proxy python3 Publicado por: @XSStringManolo en 21 Julio 2020, 09:23 am Si quieres interceptar tráfico te recomiendo usar mitmproxy.
Yo uso el cli, pero tienen lib para python. Aquí te dejo una implementación: https://gist.github.com/carpedm20/27f5157c3ff8f2a63a37 Título: Re: Como envia datos a un sitio web HTTPS via socket? | Servidor Proxy python3 Publicado por: Drakaris en 22 Julio 2020, 11:50 am Buenas! He modificado el código y al detectar que el puerto es 443 he creado la funcion send_data_tls() donde le envio los mismos argumentos.
Código: if port == 443: funcion send_data_tls Código: def send_data_tls(site, port, data, conn): Cuando lo ejecuto me imprime lo siguiente en la pantalla: imagenes:https://drive.google.com/drive/folders/1S4GZBjBUziGXvo_wNpVon8EkyoEs1tue?usp=sharing Como se puede ver en las imagenes, la salida me imprime bién los datos a enviar: Citar b'CONNECT platzi.com:443 HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: platzi.com:443\r\n\r\n' Pero cuando recibo la respuesta, recibo un erro 400 Bad Request: Citar b'HTTP/1.1 400 Bad Request\r\nServer: cloudflare\r\nDate: Wed, 22 Jul 2020 09:30:08 GMT\r\nContent-Type: text/html\r\nContent-Length: 155\r\nConnection: close\r\nCF-RAY: -\r\n\r\n<html>\r\n<head><title>400 Bad Request</title></head>\r\n<body>\r\n<center><h1>400 Bad Request</h1></center>\r\n<hr><center>cloudflare</center>\r\n</body>\r\n</html>\r\n' Además me sale el siguiente error: Citar ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:2162) El error 400 indica que la petición que fue enviada no a podido ser procesada por algún tipo de error. Que puede estar causando este error? En realidad no acabo de entender porque, yo me conecto a un sitio web por el puerto 443, y envio los datos envidos con data() a otro servidor, en este caso a Cloudflare. Es aquí que yo no entiendo que datos tengo que enviar o que debo de hacer. ¿Este es el paso donde se hace el handshake antes de conectarse al sitio web? Título: Re: Como envia datos a un sitio web HTTPS via socket? | Servidor Proxy python3 Publicado por: Drakaris en 25 Julio 2020, 18:19 pm Buenas!! Cuando he hecho la parte del proxy HTTP entendí su funcionamiento y todo, pero ahora en la parte de HTTPS. no acabo de entender muy bien.... Modifiqué el código, para ver mejor lo que esta pasando...
Código: #CODE Hice varias pruebas y ninguna me surgió nada interesante... donde pueda partir de alla. Cree la clase Send_data_tls con la funcion send_data (creo una clase por que me imagino que tengo que hacer algo antes de enviar los datos a la web HTTPS). En la funcion get_data en la condicional cargo la clase en la variable SSL y ejecuto la funcion send_data(). Cuando lo ejecuto, me encuentro con algo MUY lógico... [IMAGE] => https://drive.google.com/file/d/1rdieWydRAgjcHvhZ7qdK6hrk583-V2Hl/view?usp=sharing Lo que pasa, y cuya cosa ya me dí cuenta es que, al conectarme a la web por 443 Citar data sent: b'CONNECT platzi.com:443 HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: platzi.com:443\r\n\r\n' Este se conecta antes con el servidor Cloudflare (creo que la CA para autenticar el certificado), y este por alguna razon me recibe el 400 Bad Request. El problema en que no entiendo que esta pasando y que debo hacer.... El cloudflare me esta rechazando. Puedo hacer lo que quiero hacer con unicamente el modulo ssl? Segun @el-brujo me dijo que con ese modulo me bastava. Hay algun post o sitio donde expliquen como funciona este modulo? Para navegar o en tu caso, para enviar una petición con datos sólo tienes que usar la librería SSL y ya: Código: import ssl https://docs.python.org/3/library/ssl.html Gracias |