Skip to content

Commit

Permalink
Improvements to HTTP proxy negotiation
Browse files Browse the repository at this point in the history
  • Loading branch information
Anorov committed Dec 13, 2013
1 parent 5c9df12 commit d041e1b
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 32 deletions.
29 changes: 16 additions & 13 deletions socks.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,30 +405,33 @@ def _negotiate_HTTP(self, dest_addr, dest_port):
self.sendall(b"CONNECT " + addr.encode() + b":" + str(dest_port).encode() +
b" HTTP/1.1\r\n" + b"Host: " + dest_addr.encode() + b"\r\n\r\n")

resp = self.recv(4096)
while b"\r\n\r\n" not in resp and b"\n\n" not in resp:
d = self.recv(4096)
if not d:
self.close()
raise GeneralProxyError("Connection closed unexpectedly")
resp += d
# We just need the first line to check if the connection was successful
fobj = self.makefile()
status_line = fobj.readline()
fobj.close()

if not status_line:
self.close()
raise GeneralProxyError("Connection closed unexpectedly")

try:
proto, status_code, status_msg = status_line.split(" ", 2)
except ValueError:
raise GeneralProxyError("HTTP proxy server sent invalid response")

# We just need the first line to check if the connection was successful
status_line = resp.splitlines()[0].split(b" ", 2)

if not status_line[0].startswith(b"HTTP/"):
if not proto.startswith("HTTP/"):
self.close()
raise GeneralProxyError("Proxy server does not appear to be an HTTP proxy")

try:
status_code = int(status_line[1])
status_code = int(status_code)
except ValueError:
self.close()
raise HTTPError("HTTP proxy server did not return a valid HTTP status")

if status_code != 200:
self.close()
error = "{}: {}".format(status_code, status_line[2].decode())
error = "{}: {}".format(status_code, status_msg)
if status_code in (400, 403, 405):
# It's likely that the HTTP proxy server does not support the CONNECT tunneling method
error += ("\n[*] Note: The HTTP proxy server may not be supported by PySocks"
Expand Down
2 changes: 1 addition & 1 deletion test/httpproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def run_proxy(port=8080, start_ioloop=True):
app = tornado.web.Application([
(r'.*', ProxyHandler),
])
app.listen(port)
app.listen(port, address="127.0.0.1")
ioloop = tornado.ioloop.IOLoop.instance()
if start_ioloop:
ioloop.start()
Expand Down
2 changes: 1 addition & 1 deletion test/socks4server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from twisted.protocols.socks import SOCKSv4Factory

def run_proxy():
reactor.listenTCP(1080, SOCKSv4Factory("/dev/null"))
reactor.listenTCP(1080, SOCKSv4Factory("/dev/null"), interface="127.0.0.1")
try:
reactor.run()
except (KeyboardInterrupt, SystemExit):
Expand Down
32 changes: 16 additions & 16 deletions test/sockstest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
import urllib2

def raw_HTTP_request():
req = "GET /ip/ HTTP/1.1\r\n"
req += "Host: api.externalip.net\r\n"
req = "GET /ip HTTP/1.1\r\n"
req += "Host: ifconfig.me\r\n"
req += "User-Agent: Mozilla\r\n"
req += "Accept: text/html\r\n"
req += "\r\n"
Expand All @@ -22,23 +22,23 @@ def raw_HTTP_request():
def socket_HTTP_test():
s = socks.socksocket()
s.set_proxy(socks.HTTP, "127.0.0.1", 8081)
s.connect(("api.externalip.net", 80))
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def socket_SOCKS4_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS4, "127.0.0.1", 1080)
s.connect(("api.externalip.net", 80))
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def socket_SOCKS5_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081)
s.connect(("api.externalip.net", 80))
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")
Expand All @@ -47,70 +47,70 @@ def socket_SOCKS5_auth_test():
# TODO: add support for this test. Will need a better SOCKS5 server.
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081, username="a", password="b")
s.connect(("api.externalip.net", 80))
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def socket_HTTP_IP_test():
s = socks.socksocket()
s.set_proxy(socks.HTTP, "127.0.0.1", 8081)
s.connect(("95.211.60.37", 80))
s.connect(("133.242.129.236", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def socket_SOCKS4_IP_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS4, "127.0.0.1", 1080)
s.connect(("95.211.60.37", 80))
s.connect(("133.242.129.236", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def socket_SOCKS5_IP_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, "127.0.0.1", 1081)
s.connect(("95.211.60.37", 80))
s.connect(("133.242.129.236", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def socket_SOCKS4_test():
s = socks.socksocket()
s.set_proxy(socks.SOCKS4, "127.0.0.1", 1080)
s.connect(("api.externalip.net", 80))
s.connect(("ifconfig.me", 80))
s.sendall(raw_HTTP_request())
status = s.recv(2048).splitlines()[0]
assert status.startswith(b"HTTP/1.1 200")

def urllib2_HTTP_test():
socks.set_default_proxy(socks.HTTP, "127.0.0.1", 8081)
socks.wrap_module(urllib2)
status = urllib2.urlopen("http://api.externalip.net/ip/").getcode()
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
assert status == 200

def urllib2_SOCKS5_test():
socks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 1081)
socks.wrap_module(urllib2)
status = urllib2.urlopen("http://api.externalip.net/ip/").getcode()
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
assert status == 200

def urllib2_handler_HTTP_test():
opener = urllib2.build_opener(sockshandler.SocksiPyHandler(socks.HTTP, "127.0.0.1", 8081))
status = opener.open("http://api.externalip.net/ip/").getcode()
status = opener.open("http://ifconfig.me/ip").getcode()
assert status == 200

def urllib2_handler_SOCKS5_test():
opener = urllib2.build_opener(sockshandler.SocksiPyHandler(socks.SOCKS5, "127.0.0.1", 1081))
status = opener.open("http://api.externalip.net/ip/").getcode()
status = opener.open("http://ifconfig.me/ip").getcode()
assert status == 200

def global_override_HTTP_test():
socks.set_default_proxy(socks.HTTP, "127.0.0.1", 8081)
good = socket.socket
socket.socket = socks.socksocket
status = urllib2.urlopen("http://api.externalip.net/ip/").getcode()
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
socket.socket = good
assert status == 200

Expand All @@ -119,7 +119,7 @@ def global_override_SOCKS5_test():
socks.set_default_proxy(*default_proxy)
good = socket.socket
socket.socket = socks.socksocket
status = urllib2.urlopen("http://api.externalip.net/ip/").getcode()
status = urllib2.urlopen("http://ifconfig.me/ip").getcode()
socket.socket = good
assert status == 200
assert socks.get_default_proxy()[1].decode() == default_proxy[1]
Expand Down
2 changes: 1 addition & 1 deletion test/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ echo "Python 3.x tests"
python3 sockstest.py

pkill python > /dev/null 2>&1
pkill mocks > /dev/null 2>&1
./mocks shutdown >/dev/null 2>&1 &
echo "Finished tests"

0 comments on commit d041e1b

Please sign in to comment.