Servidor de socket Python: rechazar la conexión de la dirección

Tengo un servidor de socket Python que escucha en un puerto y acepta todas las conexiones entrantes usando:

(conn, address) = socket.accept() 

Sin embargo, deseo aceptar conexiones solo desde cierta dirección ip.

Actualmente, cierro la conexión si la dirección no está registrada, para lograr esto.

Pero, ¿hay una mejor manera de hacerlo, rechazando directamente las conexiones de direcciones no registradas, en lugar de aceptar conexiones y luego cerrarlas?

No es posible indicar la conexión rechazada a los clientes desde algunas direcciones IP y establecer la conexión con los clientes desde otras direcciones IP. Esto no es una limitación de Python, sino una limitación de la capa de socket BSD de nivel inferior. No puedes hacerlo incluso desde C.

El comportamiento más cercano en general que puede hacer en Python es cerrar la conexión rápidamente después de que se haya aceptado:

 sock, addr = server_socket.accept() if addr[0] != '12.34.56.78': sock.close() return ... 

Luego, el cliente vería que se aceptaba la conexión y, poco después, el cliente vería EOF al leer desde ella, y no podría escribir en ella.

Sin embargo, es posible limitar mediante la interfaz (es decir, la tarjeta de red) en el momento del enlace , utilizando uno de los siguientes:

 server_socket.bind(('', 65432)) # Bind on any interface. server_socket.bind(('127.0.0.1', 65432)) # Bind on loopback (localhost clients only). server_socket.bind(('34.56.78.91', 65432)) 

Entonces, en la versión 127.0.0.1 , telnet 127.0.0.1 65432 (como cliente) funcionaría, pero telnet myhostname 65432 daría como resultado la conexión rechazada (y la llamada server_socket.accept() no obtendrá esta conexión).

Si lees los documentos , puedes encontrar BaseServer.verify_request(request, client_address) que te dice esto:

Debe devolver un valor booleano; si el valor es Verdadero, la solicitud será procesada, y si es Falso, la solicitud será denegada. Esta función se puede anular para implementar controles de acceso para un servidor. La implementación predeterminada siempre devuelve True.

Microsoft parece admitir esta funcionalidad a través de la opción de socket SO_CONDITIONAL_ACCEPT

Esto parece requerir el uso de WSAAccept para aceptar conexiones

Esta constante no aparece en el módulo de socket pythons en mi máquina con Windows 8. No creo que haya una opción para usar WSAAccept a través del módulo de socket integrado de python.

Si entiendo correctamente, esto permitirá que su servidor responda a los paquetes SYN inmediatamente con los paquetes RST cuando esté configurado para hacerlo en lugar de terminar el intercambio de manos e intercambiar los paquetes FIN. Tenga en cuenta que el uso de este indicador elimina la responsabilidad de manejar las conexiones del sistema operativo y lo coloca en la aplicación, por lo que hay un montón de espacio para que se produzcan errores y errores de rendimiento. Si el objective era un aumento del rendimiento, puede que no valga la pena seguirlo.

Es posible hacerlo en el nivel C en windows. El módulo ctypes de Pythons permite la interconexión con el código C, por lo que es técnicamente posible hacerlo a través de una interfaz Python. Pero es probable que requiera una cantidad de esfuerzo no trivial. Si está seguro de que necesita esta función, puede ser menos esfuerzo encontrar una biblioteca de zócalos en C que lo admita, así podría crear un contenedor de ctypes para eso.