diff --git a/src/conf.py b/src/conf.py index 5cb51b2ba..307b7e6a6 100644 --- a/src/conf.py +++ b/src/conf.py @@ -254,6 +254,18 @@ class Servers(registry.SpaceSeparatedListOfStrings): L = registry.SpaceSeparatedListOfStrings.__call__(self) L.append(s) +class SocksProxy(registry.String): + """Value must be a valid hostname:port string.""" + def setValue(self, v): + # TODO: improve checks + if ':' not in v: + self.error() + try: + int(v.rsplit(':')) + except ValueError: + self.error() + super(SocksProxy, self).setValue(v) + class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf): sorted = True List = ircutils.IrcSet @@ -301,6 +313,9 @@ def registerNetwork(name, password='', ssl=False, sasl_username='', registerGlobalValue(sasl, 'password', registry.String(sasl_password, _("""Determines what SASL password will be used on %s.""") \ % name, private=True)) + registerGlobalValue(network, 'socksproxy', registry.String('', + _("""If not empty, determines the hostname of the socks proxy that + will be used to connect to this network."""))) return network # Let's fill our networks. diff --git a/src/drivers/Socket.py b/src/drivers/Socket.py index 0c2e28b74..96c1513d1 100644 --- a/src/drivers/Socket.py +++ b/src/drivers/Socket.py @@ -183,7 +183,16 @@ class SocketDriver(drivers.IrcDriver, drivers.ServersMixin): server = self._getNextServer() drivers.log.connect(self.currentServer) try: - self.conn = utils.net.getSocket(server[0]) + socks_proxy = getattr(conf.supybot.networks, self.irc.network) \ + .socksproxy() + try: + if socks_proxy: + import socks + except ImportError: + log.error('Cannot use socks proxy (SocksiPy not installed), ' + 'using direct connection instead.') + socks_proxy = '' + self.conn = utils.net.getSocket(server[0], socks_proxy) vhost = conf.supybot.protocols.irc.vhost() self.conn.bind((vhost, 0)) except socket.error, e: diff --git a/src/utils/net.py b/src/utils/net.py index 289a2fe28..3b09c7e8a 100644 --- a/src/utils/net.py +++ b/src/utils/net.py @@ -80,12 +80,18 @@ class EmailRe: return count >= 1 emailRe = EmailRe() -def getSocket(host): +def getSocket(host, socks_proxy=None): """Returns a socket of the correct AF_INET type (v4 or v6) in order to communicate with host. """ addrinfo = socket.getaddrinfo(host, None) host = addrinfo[0][4][0] + if socks_proxy: + import socks + s = socks.socksocket() + hostname, port = socks_proxy.rsplit(':', 1) + s.setproxy(socks.PROXY_TYPE_SOCKS5, hostname, int(port)) + return s if isIPV4(host): return socket.socket(socket.AF_INET, socket.SOCK_STREAM) elif isIPV6(host):