7 def socks4AResolveRequest(hostname
):
13 reqheader
= struct
.pack("!BBHL", version
, command
, port
, addr
)
14 return "%s%s\x00%s\x00"%(reqheader
,username
,hostname
)
16 def socks4AParseResponse(response
):
18 if len(response
) < RESPONSE_LEN
:
20 assert len(response
) >= RESPONSE_LEN
21 version
,status
,port
= struct
.unpack("!BBH",response
[:4])
25 return "%d.%d.%d.%d"%tuple(map(ord, response
[4:]))
27 return "ERROR (status %d)"%status
31 def socks5ParseHello(response
):
32 if response
!= "\x05\x00":
33 raise ValueError("Bizarre socks5 response")
34 def socks5ResolveRequest(hostname
, atype
=0x03, command
=0xF0):
38 reqheader
= struct
.pack("!BBBB",version
, command
, rsv
, atype
)
40 reqheader
+= struct
.pack("!B", len(hostname
))
41 portstr
= struct
.pack("!H",port
)
42 return "%s%s%s"%(reqheader
,hostname
,portstr
)
44 def socks5ParseResponse(r
):
47 version
, reply
, rsv
, atype
= struct
.unpack("!BBBB",r
[:4])
52 assert atype
in (0x01,0x03,0x04)
54 expected_len
= 4 + ({1:4,4:16}[atype
]) + 2
55 if len(r
) < expected_len
:
57 elif len(r
) > expected_len
:
58 raise ValueError("Overlong socks5 reply!")
61 return "%d.%d.%d.%d"%tuple(map(ord,addr
))
63 # not really the right way to format IPv6
64 return "IPv6: %s"%(":".join([hex(ord(c
)) for c
in addr
]))
66 hlen
, = struct
.unpack("!B", r
[4])
67 expected_len
= 5 + hlen
+ 2
68 if len(r
) < expected_len
:
72 def socks5ResolvePTRRequest(hostname
):
73 return socks5ResolveRequest(socket
.inet_aton(hostname
),
74 atype
=1, command
= 0xF1)
77 def parseHostAndPort(h
):
78 host
, port
= "localhost", 9050
85 print "Bad hostname %r"%h
95 def resolve(hostname
, sockshost
, socksport
, socksver
=4, reverse
=0):
96 assert socksver
in (4,5)
98 fmt
= socks4AResolveRequest
99 parse
= socks4AParseResponse
101 fmt
= socks5ResolveRequest
102 parse
= socks5ParseResponse
104 fmt
= socks5ResolvePTRRequest
105 parse
= socks5ParseResponse
107 s
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
108 s
.connect((sockshost
,socksport
))
110 s
.send(socks5Hello())
111 socks5ParseHello(s
.recv(2))
112 s
.send(fmt(hostname
))
114 result
= parse(answer
)
115 while result
is None:
120 result
= parse(answer
)
121 print "Got answer",result
124 print "Got extra data too: %r"%m
127 if __name__
== '__main__':
128 if len(sys
.argv
) not in (2,3,4):
129 print "Syntax: resolve.py [-4|-5] hostname [sockshost:socksport]"
133 while sys
.argv
[1][0] == '-':
134 if sys
.argv
[1] in ("-4", "-5"):
135 socksver
= int(sys
.argv
[1][1])
137 elif sys
.argv
[1] == '-x':
140 elif sys
.argv
[1] == '--':
143 if len(sys
.argv
) >= 4:
144 print "Syntax: resolve.py [-x] [-4|-5] hostname [sockshost:socksport]"
146 if len(sys
.argv
) == 3:
147 sh
,sp
= parseHostAndPort(sys
.argv
[2])
149 sh
,sp
= parseHostAndPort("")
151 if reverse
and socksver
== 4:
153 resolve(sys
.argv
[1], sh
, sp
, socksver
, reverse
)