1 """SocksiPy - Python SOCKS module.
4 Copyright 2006 Dan-Haim. All rights reserved.
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice, this
10 list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14 3. Neither the name of Dan Haim nor the names of his contributors may be used
15 to endorse or promote products derived from this software without specific
16 prior written permission.
18 THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED
19 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.
29 This module provides a standard socket-like interface for Python
30 for tunneling connections through SOCKS proxies.
42 _orgsocket = socket.socket
48 return repr(self.
valuevalue)
80 _generalerrors = (
"success",
87 _socks5errors = (
"succeeded",
88 "general SOCKS server failure",
89 "connection not allowed by ruleset",
90 "Network unreachable",
94 "Command not supported",
95 "Address type not supported",
98 _socks5autherrors = (
"succeeded",
99 "authentication is required",
100 "all offered authentication methods were rejected",
101 "unknown username or invalid password",
104 _socks4errors = (
"request granted",
105 "request rejected or failed",
106 "request rejected because SOCKS server cannot connect to identd on the client",
107 "request rejected because the client program and identd report different user-ids",
110 def setdefaultproxy(proxytype=None,addr=None,port=None,rdns=True,username=None,password=None):
111 """setdefaultproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
112 Sets a default proxy which all further socksocket objects will use,
113 unless explicitly changed.
116 _defaultproxy = (proxytype,addr,port,rdns,username,password)
119 """socksocket([family[, type[, proto]]]) -> socket object
121 Open a SOCKS enabled socket. The parameters are the same as
122 those of the standard socket init. In order for SOCKS to work,
123 you must specify family=AF_INET, type=SOCK_STREAM and proto=0.
126 def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None):
127 _orgsocket.__init__(self,family,type,proto,_sock)
128 if _defaultproxy !=
None:
131 self.
__proxy__proxy = (
None,
None,
None,
None,
None,
None)
136 """__recvall(bytes) -> data
137 Receive EXACTLY the number of bytes requested from the socket.
138 Blocks until the required number of bytes have been received.
141 while len(data) < bytes:
142 d = self.recv(bytes-len(data))
148 def setproxy(self,proxytype=None,addr=None,port=None,rdns=True,username=None,password=None):
149 """setproxy(proxytype, addr[, port[, rdns[, username[, password]]]])
150 Sets the proxy to be used.
151 proxytype - The type of the proxy to be used. Three types
152 are supported: PROXY_TYPE_SOCKS4 (including socks4a),
153 PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP
154 addr - The address of the server (IP or DNS).
155 port - The port of the server. Defaults to 1080 for SOCKS
156 servers and 8080 for HTTP proxy servers.
157 rdns - Should DNS queries be performed on the remote side
158 (rather than the local side). The default is True.
159 Note: This has no effect with SOCKS4 servers.
160 username - Username to authenticate with to the server.
161 The default is no authentication.
162 password - Password to authenticate with to the server.
163 Only relevant when username is also provided.
165 self.
__proxy__proxy = (proxytype,addr,port,rdns,username,password)
168 """__negotiatesocks5(self,destaddr,destport)
169 Negotiates a connection through a SOCKS5 server.
172 if (self.
__proxy__proxy[4]!=
None)
and (self.
__proxy__proxy[5]!=
None):
176 self.sendall(
"\x05\x02\x00\x02")
180 self.sendall(
"\x05\x01\x00")
184 if chosenauth[0] !=
"\x05":
188 if chosenauth[1] ==
"\x00":
191 elif chosenauth[1] ==
"\x02":
194 self.sendall(
"\x01" + chr(len(self.
__proxy__proxy[4])) + self.
__proxy__proxy[4] + chr(len(self.
__proxy__proxy[5])) + self.
__proxy__proxy[5])
196 if authstat[0] !=
"\x01":
200 if authstat[1] !=
"\x00":
208 if chosenauth[1] ==
"\xFF":
217 ipaddr = socket.inet_aton(destaddr)
218 req = req +
"\x01" + ipaddr
221 if self.
__proxy__proxy[3]==
True:
224 req = req +
"\x03" + chr(len(destaddr)) + destaddr
227 ipaddr = socket.inet_aton(socket.gethostbyname(destaddr))
228 req = req +
"\x01" + ipaddr
229 req = req + struct.pack(
">H",destport)
233 if resp[0] !=
"\x05":
236 elif resp[1] !=
"\x00":
240 raise Socks5Error((ord(resp[1]),_generalerrors[ord(resp[1])]))
244 elif resp[3] ==
"\x01":
246 elif resp[3] ==
"\x03":
247 resp = resp + self.recv(1)
248 boundaddr = self.
__recvall__recvall(ord(resp[4]))
252 boundport = struct.unpack(
">H",self.
__recvall__recvall(2))[0]
255 self.
__proxypeername__proxypeername = (socket.inet_ntoa(ipaddr),destport)
260 """getsockname() -> address info
261 Returns the bound IP address and port number at the proxy.
266 """getproxypeername() -> address info
267 Returns the IP and port number of the proxy.
269 return _orgsocket.getpeername(self)
272 """getpeername() -> address info
273 Returns the IP address and port number of the destination
274 machine (note: getproxypeername returns the proxy)
279 """__negotiatesocks4(self,destaddr,destport)
280 Negotiates a connection through a SOCKS4 server.
285 ipaddr = socket.inet_aton(destaddr)
288 if self.
__proxy__proxy[3]==
True:
289 ipaddr =
"\x00\x00\x00\x01"
292 ipaddr = socket.inet_aton(socket.gethostbyname(destaddr))
294 req =
"\x04\x01" + struct.pack(
">H",destport) + ipaddr
296 if self.
__proxy__proxy[4] !=
None:
297 req = req + self.
__proxy__proxy[4]
303 req = req + destaddr +
"\x00"
307 if resp[0] !=
"\x00":
311 if resp[1] !=
"\x5A":
314 if ord(resp[1])
in (91,92,93):
316 raise Socks4Error((ord(resp[1]),_socks4errors[ord(resp[1])-90]))
320 self.
__proxysockname__proxysockname = (socket.inet_ntoa(resp[4:]),struct.unpack(
">H",resp[2:4])[0])
322 self.
__proxypeername__proxypeername = (socket.inet_ntoa(ipaddr),destport)
327 """__negotiatehttp(self,destaddr,destport)
328 Negotiates a connection through an HTTP server.
331 if self.
__proxy__proxy[3] ==
False:
332 addr = socket.gethostbyname(destaddr)
335 self.sendall(
"CONNECT " + addr +
":" + str(destport) +
" HTTP/1.1\r\n" +
"Host: " + destaddr +
"\r\n\r\n")
338 while resp.find(
"\r\n\r\n")==-1:
339 resp = resp + self.recv(1)
342 statusline = resp.splitlines()[0].split(
" ",2)
343 if statusline[0]
not in (
"HTTP/1.0",
"HTTP/1.1"):
347 statuscode = int(statusline[1])
351 if statuscode != 200:
353 raise HTTPError((statuscode,statusline[2]))
358 """connect(self,despair)
359 Connects to the specified destination through a proxy.
360 destpar - A tuple of the IP/DNS address and the port number.
361 (identical to socket's connect).
362 To select the proxy server use setproxy().
365 if (type(destpair)
in (list,tuple)==
False)
or (len(destpair)<2)
or (type(destpair[0])!=str)
or (type(destpair[1])!=int):
367 if self.
__proxy__proxy[0] == PROXY_TYPE_SOCKS5:
368 if self.
__proxy__proxy[2] !=
None:
369 portnum = self.
__proxy__proxy[2]
372 _orgsocket.connect(self,(self.
__proxy__proxy[1],portnum))
374 elif self.
__proxy__proxy[0] == PROXY_TYPE_SOCKS4:
375 if self.
__proxy__proxy[2] !=
None:
376 portnum = self.
__proxy__proxy[2]
379 _orgsocket.connect(self,(self.
__proxy__proxy[1],portnum))
381 elif self.
__proxy__proxy[0] == PROXY_TYPE_HTTP:
382 if self.
__proxy__proxy[2] !=
None:
383 portnum = self.
__proxy__proxy[2]
386 _orgsocket.connect(self,(self.
__proxy__proxy[1],portnum))
388 elif self.
__proxy__proxy[0] ==
None:
389 _orgsocket.connect(self,(destpair[0],destpair[1]))
def __init__(self, value)
def __init__(self, value)
def __init__(self, value)
def __init__(self, value)
def __init__(self, value)
def __init__(self, value)
def getproxypeername(self)
def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None)
def __negotiatesocks5(self, destaddr, destport)
def __recvall(self, bytes)
def setproxy(self, proxytype=None, addr=None, port=None, rdns=True, username=None, password=None)
def getproxysockname(self)
def __negotiatesocks4(self, destaddr, destport)
def __negotiatehttp(self, destaddr, destport)
def connect(self, destpair)
def setdefaultproxy(proxytype=None, addr=None, port=None, rdns=True, username=None, password=None)