Archive for March 10, 2009

Приручаем socks прокси

Бывает нужно наладить работу библиотеки через socks прокси, но сама библиотека не предоставляет такой возможности. Если внутри неё используется модуль socket, то проблему можно решить с помощью socksipy

Рассмотрим конкретный пример. Библиотека xmpppy. Она позволяет работать только c HTTP/HTTPS проксями. Попробуем это изменить. Исследовав исходный код, увидим, что подключение к сети осуществляется в методе xmpp.transports.TCPsocket.connect, где создаётся сокет. Этот метод и нужно манкипатчить.

Я сделал так:

import xmpp
import xmpp_hack

xmpp_hack.PROXY = '12.34.56.789'
xmpp_hack.PORT = '7890'
... далее работаем с библиотекой xmpp как обычно!...

Вся суть в xmpp_hack модуле:

import xmpp
import logging
import socket
# Импорируем библиотеку socksify
import socks

from xmpp import transports

PROXY = ''
PORT = 0

# Это метод, которым мы проманкипатчим xmpp либу
# Он в точности похож на оригинал за исключением пары строчек
def custom_connect(self,server=None):
    """ Try to connect. Returns non-empty string on success. """
    try:
        if not server: server=self._server

        # Комментируем стандартное создание сокета
        #self._sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        logging.debug('Using %s:%s SOCKS5 proxy' % (PROXY, PORT))
        # И создаём socks-обёртку, которая имитирует обычный сокет
        self._sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
        self._sock.setproxy(socks.PROXY_TYPE_SOCKS5, PROXY, PORT)

        # Далее продолжается код из оригинального метода
        self._sock.connect(server)
        self._send=self._sock.sendall
        self._recv=self._sock.recv
        self.DEBUG("Successfully connected to remote host %s"%`server`,'start')
        return 'ok'
    except socket.error, (errno, strerror): 
        self.DEBUG("Failed to connect to remote host %s: %s (%s)"%(`server`, strerror, errno),'error')
    except Exception, ex:
        raise
        #logging.error(ex)

# Собственно манкипатчинг!
transports.TCPsocket.connect = custom_connect

Удачного манкипатчинга :-)