send
Grupo de Telegram
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

[Python] Underch4t v1.0 (Parte 3)

  • 2 Respuestas
  • 1538 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado WhiZ

  • *
  • Underc0der
  • Mensajes: 395
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
« en: Enero 02, 2016, 01:33:12 pm »

UnderCh4t



Bienvenidos a la tercera entrega de UnderCh4t, un sencillo chat en python que nos ayudará a comprender algunos de conceptos de gran importancia para todo programador.

Si es la primera vez que escuchás hablar de este tutorial, te recomiendo que pases primero por estos posts:
    - You are not allowed to view links. Register or Login
    - You are not allowed to view links. Register or Login

Bien. Si hacemos un poco de memoria, en las entregas pasadas hemos estado enfocándonos en nuestro servidor. Más concretamente, hemos aprendido a crear un socket y a establecer una interfaz de conexión. Con todo esto, ya estamos en condiciones de poner a trabajar a nuestro servidor. Veamos cómo... ;)



PONIENDO AL SERVIDOR EN ESCUCHA


Debido a que esta vez las cosas van a ser un poco más complicadas, lo que voy a hacer es lo siguiente: primero, vamos a repasar las cosas que ya vimos en las entregas anteriores; en segundo lugar, vamos a poner el servidor en escucha y a atender las conexiones entrantes -es decir, los clientes que se conecten al servidor-.

Ya sabemos cómo crear el servidor y establecer la interfaz de conexión:
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos el socket
  5. mi_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # establecemos interfaz de conexión
  8. ip = "127.0.0.1"
  9. puerto = 8000
  10. mi_socket.bind((ip, puerto))

Bueno, muy fácil hasta aquí. Lo que viene ahora es poner el servidor en escucha. Sin embargo, antes me gustaría charlar algunas cosas. Sé que todavía no tocamos el tema de los clientes pero voy a ir adelantando algunas cosas (nada que los vaya a complicar, no se preocupen). Tal como hacemos con el servidor, al momento de crear un cliente debemos definir un socket. ¿Cómo lo hacemos? Tan simple como esto:

Código: Python
  1. import socket
  2.  
  3. mi_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Mmm... Esto me resulta bastante familiar, ¿no les parece? Sí. Esta misma línea la usamos para crear el socket en nuestro servidor. Interesante, ¿no?

Esto significa que cada vez que creamos un socket, éste sirve tanto para crear un servidor como un cliente, y debemos, por tanto, indicar qué rol tendrá el mismo en la conexión. En el caso del servidor (al cliente lo veremos en otro momento), lo hacemos con el método listen.

Tal y como vemos en la You are not allowed to view links. Register or Login, la sintaxis es la siguente:

Código: Python
  1. socket.listen(backlog)

El método listen, en pocas palabras, pone al socket en modo pasivo y establece el número de conexiones TCP entrantes que el sistema puede encolar.

Analicemos bien esto:

    - Poner al socket en modo pasivo: decimos que un socket se encuentra en modo pasivo cuando está listo para ser usado como un servidor y, por el contrario, en modo activo cuando será utilizado como cliente.

    - Encolar conexiones entrantes: cuando el servidor se pone en marcha sólo tiene que esperar a que los clientes se conecten a él. Cuando esto sucede, se atiende al cliente de forma individual y dedicada. Esto significa que si el servidor está conectado con un cliente, los demás deberán esperar a que ésta conexión finalice para ser atendidos. Podemos comparar esto con la caja de un supermercado: el cajero atiende a un cliente a la vez. Los demás deberán ponerse en fila y esperar su turno.

    - Establecer número máximo de conexiones en la cola: con el método listen podemos indicar cuál es el número máximo de clientes que vamos a permitir en nuestra cola (es el llamado backlog). Si volvemos al ejemplo del supermercado, el cajero puede indicar el número máximo de clientes que tendrá la cola. Si el máximo fuera de cinco personas, la sexta será notificada de tal situación y le negarán el acceso a la cola (sí, tendrá que irse a otra caja o volver a probar en otro momento).

Si llevamos esto al código, nos queda algo así:
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos el socket
  5. mi_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # establecemos interfaz de conexión
  8. ip = "127.0.0.1"
  9. puerto = 8000
  10. mi_socket.bind((ip, puerto))
  11.  
  12. # ponemos al socket en modo pasivo y establecemos el número
  13. # máximo de conexiones entrantes que el sistema puede encolar.
  14. backlog = 5
  15. mi_socket.listen(backlog)

Bien, ahora que ya hemos puesto al socket en modo pasivo (está escuchando: listen) y que hemos establecido el límite de conexiones a encolar (backlog), ya estamos en condiciones de recibir a nuestros clientes.



ACEPTANDO CONEXIONES ENTRANTES


Cuando decimos recibir a nuestros clientes, estamos hablando de aceptarlos. Justamente, para realizar esta tarea, existe el método accept. Para utilizar este método, sólo tenemos que escribir lo siguiente:

Código: Python
  1. conn, address = socket.accept()

Tal y como vemos en la You are not allowed to view links. Register or Login, para utilizar este método, es necesario haber creado una interfaz de conexión previamente. Una vez ejecutado, el método devuelve (return) una tupla de dos elementos:
    - conn: un nuevo objeto socket utilizado para enviar y recibir información de la conexión.
    - address: dirección vinculada al socket que se encuentra en el otro extremo de la conexión (es decir, la dirección del cliente). Como dijimos en la entrega anterior, una dirección de red se compone, en el caso de las familias AF_INET (IPv4), de una tupla con dos valores: IP y puerto.

Si volvemos al código anterior y evaluamos los valores retornados, tendríamos algo así:

Código: Python
  1. >>> print conn
  2. <socket._socketobject object at 0x0000000001FBF660>
  3. >>> print address
  4. ('127.0.0.1', 2580)

Como vemos, conn es un objeto socket y address una tupla con dos valores: el primero es la IP -en este caso, una Loop IP-, el segundo valor corresponde al puerto. Recuerden que estos dos valores (IP y puerto) corresponden al cliente que acabamos de recibir (aceptar). El objeto socket es el que nos permitirá comunicarnos con ese cliente.

Esto significa que si quiero enviarle información al cliente, tendré que hacerlo por medio de conn, y lo haremos a la IP 127.0.0.1 y al puerto 2580. Esto lo veremos con más detalle en las próximas entregas pero les comento esto ahora para que se vayan haciendo una idea ;)

Muy bien, en el día de hoy hemos aprendido a poner nuestro servidor en escucha (listen), indicando el número máximo de conexiones entrantes a encolar (backlog), y a aceptar cada una de estas conexiones entrantes (accept). Para poner en práctica todo esto, pueden crear un archivo llamado servidor.py (ahora les paso el contenido) y conectarse a él por medio de telnet o netcat (más adelante veremos cómo crear nuestro propio cliente).

[b[servidor.py[/b]
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos servidor
  5. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # creamos interfaz de conexión
  8. server.bind(("0.0.0.0", 8080))
  9.  
  10. # ponemos al servidor en escucha
  11. # (backlog: 5)
  12. server.listen(5)
  13.  
  14. # recibimos conexiones entrantes
  15. conn, address = server.accept()
  16.  
  17. # imprimimos los datos devueltos por
  18. # el método accept
  19. print conn
  20. print address
  21.  
  22. # cerramos la conexión con el cliente
  23. conn.close()
  24.  
  25. # cerramos el servidor
  26. server.close()

Para finalizar, déjenme comentarles dos cosas. En primer lugar, hay un método nuevo que no habíamos visto todavía: close. Como sabemos, tanto server como conn son objetos socket. Esto significa que ambos presentan los mismos métodos. Este nuevo método, sirve para cerrar un socket. En este caso, primero cerramos el socket conn y luego el que creamos para el servidor.

En segundo lugar, por si no se dieron cuenta, en el código que acabamos de hacer tenemos un gran problema: sólo podemos recibir un cliente. Luego de crear la conexión, cerramos ambos sockets y se termina todo. Evidentemente, esto no nos sirve si queremos tener un chat funcional. En las próximas entregas veremos cómo prolongar la conexión con un cliente (bucles) y cómo interactuar con varios clientes a la vez (threads).

Nos vemos en la próxima entrega con más de UnderCh4t ;)

Saludos!
WhiZ
« Última modificación: Enero 02, 2016, 01:38:32 pm por WhiZ »


Conectado po6xsecpo

  • *
  • Underc0der
  • Mensajes: 46
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
    • Email
  • Skype: po6xsecpo@gmail.com
« Respuesta #1 en: Enero 02, 2016, 06:08:03 pm »
Duda: Al usar socket.accept() permito un cliente,posterior a recibirlo veo su IP:Puerto. Qué sucede si quiero prefiltrar IP's  previo a darle accept() para no tener que abrir/cerrar la petición del cliente? (por cualquier razón, quizá un baneo temporal)

Gracias por el código. A la espera del threading :D

Desconectado WhiZ

  • *
  • Underc0der
  • Mensajes: 395
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
« Respuesta #2 en: Enero 02, 2016, 11:12:29 pm »
You are not allowed to view links. Register or Login
Duda: Al usar socket.accept() permito un cliente,posterior a recibirlo veo su IP:Puerto. Qué sucede si quiero prefiltrar IP's  previo a darle accept() para no tener que abrir/cerrar la petición del cliente? (por cualquier razón, quizá un baneo temporal)

Hola @You are not allowed to view links. Register or Login. Lamentablemente, eso no es posible, ni en python ni en ningún otro lenguaje. Lo único que podés hacer es algo así:
Código: Python
  1. import socket
  2.  
  3. blacklist = []
  4.  
  5. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6. server.bind(("0.0.0.0", 2236))
  7.  
  8. server.listen(5)
  9. conn, address = server.accept()
  10.  
  11. if address[0] in blacklist:
  12.     conn.close()

Saludos!
WhiZ
« Última modificación: Enero 03, 2016, 07:42:41 pm por WhiZ »


 

¿Te gustó el post? COMPARTILO!



[Código] Yardas a metros - Metros a yardas [Python]

Iniciado por LucaSthefano

Respuestas: 0
Vistas: 1143
Último mensaje Mayo 29, 2011, 01:27:34 am
por LucaSthefano
[Código] Entero / No Entero [Ejercicio - Python]

Iniciado por LucaSthefano

Respuestas: 0
Vistas: 1100
Último mensaje Mayo 29, 2011, 01:24:09 am
por LucaSthefano
Python phpmyadmin "BruteForce"

Iniciado por linkgl

Respuestas: 2
Vistas: 2185
Último mensaje Agosto 19, 2011, 12:14:37 pm
por linkgl
Python Trojan - By "bLiNdFiR3"

Iniciado por d33k40

Respuestas: 1
Vistas: 1752
Último mensaje Abril 03, 2010, 11:01:59 pm
por Dharok
Python keylogger - by "bLiNdFiR3"

Iniciado por d33k40

Respuestas: 0
Vistas: 1727
Último mensaje Abril 07, 2010, 03:30:22 am
por d33k40