8 def socks4AResolveRequest(hostname
):
14 reqheader
= struct
.pack("!BBHL", version
, command
, port
, addr
)
15 return "%s%s\x00%s\x00"%(reqheader
,username
,hostname
)
17 def socks4AParseResponse(response
):
19 if len(response
) < RESPONSE_LEN
:
21 assert len(response
) >= RESPONSE_LEN
22 version
,status
,port
= struct
.unpack("!BBH",response
[:4])
26 return "%d.%d.%d.%d"%tuple(map(ord, response
[4:]))
28 return "ERROR (status %d)"%status
32 def socks5ParseHello(response
):
33 if response
!= "\x05\x00":
34 raise ValueError("Bizarre socks5 response")
35 def socks5ResolveRequest(hostname
, atype
=0x03, command
=0xF0):
39 reqheader
= struct
.pack("!BBBB",version
, command
, rsv
, atype
)
41 reqheader
+= struct
.pack("!B", len(hostname
))
42 portstr
= struct
.pack("!H",port
)
43 return "%s%s%s"%(reqheader
,hostname
,portstr
)
45 def socks5ParseResponse(r
):
48 version
, reply
, rsv
, atype
= struct
.unpack("!BBBB",r
[:4])
53 assert atype
in (0x01,0x03,0x04)
55 expected_len
= 4 + ({1:4,4:16}[atype
]) + 2
56 if len(r
) < expected_len
:
58 elif len(r
) > expected_len
:
59 raise ValueError("Overlong socks5 reply!")
62 return "%d.%d.%d.%d"%tuple(map(ord,addr
))
64 # not really the right way to format IPv6
65 return "IPv6: %s"%(":".join([hex(ord(c
)) for c
in addr
]))
67 hlen
, = struct
.unpack("!B", r
[4])
68 expected_len
= 5 + hlen
+ 2
69 if len(r
) < expected_len
:
73 def socks5ResolvePTRRequest(hostname
):
74 return socks5ResolveRequest(socket
.inet_aton(hostname
),
75 atype
=1, command
= 0xF1)
78 def parseHostAndPort(h
):
79 host
, port
= "localhost", 9050
86 print "Bad hostname %r"%h
96 def resolve(hostname
, sockshost
, socksport
, socksver
=4, reverse
=0):
97 assert socksver
in (4,5)
99 fmt
= socks4AResolveRequest
100 parse
= socks4AParseResponse
102 fmt
= socks5ResolveRequest
103 parse
= socks5ParseResponse
105 fmt
= socks5ResolvePTRRequest
106 parse
= socks5ParseResponse
108 s
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
109 s
.connect((sockshost
,socksport
))
111 s
.send(socks5Hello())
112 socks5ParseHello(s
.recv(2))
113 s
.send(fmt(hostname
))
115 result
= parse(answer
)
116 while result
is None:
121 result
= parse(answer
)
122 print "Got answer",result
125 print "Got extra data too: %r"%m
128 if __name__
== '__main__':
129 if len(sys
.argv
) not in (2,3,4):
130 print "Syntax: resolve.py [-4|-5] hostname [sockshost:socksport]"
134 while sys
.argv
[1][0] == '-':
135 if sys
.argv
[1] in ("-4", "-5"):
136 socksver
= int(sys
.argv
[1][1])
138 elif sys
.argv
[1] == '-x':
141 elif sys
.argv
[1] == '--':
144 if len(sys
.argv
) >= 4:
145 print "Syntax: resolve.py [-x] [-4|-5] hostname [sockshost:socksport]"
147 if len(sys
.argv
) == 3:
148 sh
,sp
= parseHostAndPort(sys
.argv
[2])
150 sh
,sp
= parseHostAndPort("")
152 if reverse
and socksver
== 4:
154 resolve(sys
.argv
[1], sh
, sp
, socksver
, reverse
)