SocksiPy – Conexión TCP/IP vía proxy SOCKS



Versión: 2.x, 3.x.

Ante la necesidad de establecer una conexión con un servidor a través de un proxy llegué al encuentro de SocksiPy, un módulo escrito íntegramente en Python que permite crear conexiones TCP/IP (incluyendo HTTP) utilizando el protocolo SOCKS en sus versiones 4 y 5.

Descarga e instalación

Originalmente el módulo corre únicamente en Python 2, pero puedes descargar mi adaptación para la gama 3.x desde este enlace. Las descargas originales se encuentran en la página del proyecto en SourceForge. Una vez descargado, basta con copiar el archivo socks.py en la carpeta lib/site-packages dentro del directorio de instalación del intérprete.

La utilización es sencilla y similar al módulo estándar socket. La clase principal de SocksiPy hereda de socket.socket, por lo que como novedad nos encontraremos únicamente con una función para indicar los datos del servidor proxy y algunas clases para manejar potenciales errores.

Aplicación

Comenzamos entonces con la importación del módulo y creación de un socket.

import socks
s = socks.socksocket()

La clase socksocket recibe los mismos argumentos que socket.socket. Cabe aclarar, sin embargo, que el protocolo SOCKS funciona únicamente con los argumentos socket.AF_INET, socket.SOCK_STREAM, 0 que son utilizados por defecto.

A continuación indicamos la dirección del servidor proxy y el tipo de protocolo (SOCKS4/5 o bien HTTP).

# Tipo de protocolo, dirección de IP y puerto.
s.setproxy(socks.PROXY_TYPE_SOCKS4, "127.0.0.1", 1080)

Los valores disponibles para el primer parámetro son PROXY_TYPE_SOCKS4, PROXY_TYPE_SOCKS5 y PROXY_TYPE_HTTP. Hay varios sitios que proveen servidores proxy de forma gratuita.

Adicionalmente, la función permite indicar opcionalmente si la consulta de DNS debe ser realizada de forma remota (cuarto parámetro, True por defecto); y usuario y contraseña (quinto y sexto, respectivamente, None por defecto) para conexiones vía el protocolo SOCKS5.

Si la llamada a setproxy es omitida, s funciona como un socket convencional.

Para establecer la información del servidor proxy previo a la creación del socket se nos provee la función setdefaultproxy que recibe los mismos parámetros que la anterior. Resulta útil al momento de reemplazar la implementación estándar del módulo socket para que el servidor proxy sea también utilizado en otros módulos ajenos a nuestro código. Véase el ejemplo tomado del archivo README.

socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "socks.example.com")
socket.socket = socks.socksocket
urllib.urlopen("http://www.sourceforge.net/")

De esta forma, el módulo urllib accede a la dirección indicada a través del proxy.

Ya fuera de lo particular del módulo, procedemos a conectar, enviar y recibir datos, y terminar la conexión de la forma general.

s.connect(host)
s.send("Hola mundo!")
print(s.recv(1024))
s.close()

host debe ser una tupla que indique la dirección de IP y puerto del servidor TCP. Para realizar pruebas puedes utilizar nuestro Servidor TCP Multi-Hilo.

Usuarios de Python 3.x deben enviar los datos como una secuencia de bytes:

s.send(b"Hola mundo!")

Manejo de errores

El módulo exporta las siguientes excepciones: Socks4Error, Socks5Error y HTTPError para errores propios de los protocolos SOCKS4/5 y HTTP, respectivamente. En el caso de una autenticación fallida en el protocolo SOCKS5 se obtendrá Socks5AuthError. Para errores generales, independientes del protocolo, GeneralProxyError.

Por último, todas estas clases heredan de ProxyError; por ende, podemos capturar todos los errores relacionados con el módulo utilizando:

try:
    # Conexión, envío de datos, etc.
except socks.ProxyError:
    # Manejo de errores.

(No debe pasarse por alto la posibilidad de obtener socket.error para errores del módulo estándar.)



3 comentarios.

Deja un comentario