使用Python测试HTTPS代理

7
我管理许多具有自己SSL连接的HTTPS代理。我正在使用Python构建诊断工具,尝试通过每个代理连接到页面,并在无法通过其中一个代理连接时向我发送电子邮件。
我计划使用urllib通过每个代理连接并返回一个内容为“success”的页面来实现此目标,代码如下:
def fetch(url):
    connection = urllib.urlopen(
    url,
    proxies={'http':"https://"+server+':443'}
    )
    return connection.read()


print fetch(testURL)

这会完美地获取我想要的页面,但问题是即使代理服务器信息不正确或代理服务器不活动,它仍会获取我想要的页面。因此,要么它从不使用代理服务器,要么在失败时尝试连接而没有代理。

我该如何解决这个问题?

编辑:似乎没有人知道如何做到这一点。我将开始阅读其他语言库,看看它们是否可以更好地处理它。有人知道在另一种语言(如Go)中是否更容易吗?

编辑:我刚才在下面的评论中写了这个,但我认为可能存在误解。 “代理服务器有自己的ssl连接。因此,如果我去谷歌.com,我首先与foo.com进行密钥交换,然后再与目标地址bar.com或目标地址baz.com进行交换。目标地址不必是https,代理是https”

4个回答

4
大多数人将https代理理解为能够理解CONNECT请求的代理。我的例子创建了直接的SSL连接。
try:
    import http.client as httplib # for python 3.2+
except ImportError:
    import httplib # for python 2.7


con = httplib.HTTPSConnection('proxy', 443) # create proxy connection
# download http://example.com/ through proxy
con.putrequest('GET', 'http://example.com/', skip_host=True)
con.putheader('Host', 'example.com')
con.endheaders()
res = con.getresponse()
print(res.read())

如果您的代理是反向代理,则更改。
con.putrequest('GET', 'http://example.com/', skip_host=True)

con.putrequest('GET', '/', skip_host=True)`

1

从代码的阅读来看,urllib似乎不支持此功能,而urllib2是否支持尚不清楚。但是,只需使用curl(或curllib)就可以了,这通常是HTTP客户端API的首选(更复杂,这就是为什么出现了urllib等工具的原因)。

查看命令行工具curl,它似乎很有前途:

   -x, --proxy <[protocol://][user:password@]proxyhost[:port]>
          Use the specified HTTP proxy. If the port number is not specified, it is assumed at port 1080.

          This  option  overrides  existing environment variables that set the proxy to use. If there's an environment variable setting a proxy, you can set
          proxy to "" to override it.

          All operations that are performed over an HTTP proxy will transparently be converted to HTTP. It means that certain protocol  specific  operations
          might not be available. This is not the case if you can tunnel through the proxy, as one with the -p, --proxytunnel option.

          User  and  password that might be provided in the proxy string are URL decoded by curl. This allows you to pass in special characters such as @ by
          using %40 or pass in a colon with %3a.

          The proxy host can be specified the exact same way as the proxy environment variables, including the protocol prefix (http://)  and  the  embedded
          user + password.

          From  7.21.7,  the  proxy  string  may  be  specified with a protocol:// prefix to specify alternative proxy protocols. Use socks4://, socks4a://,
          socks5:// or socks5h:// to request the specific SOCKS version to be used. No protocol specified, http:// and all others will be  treated  as  HTTP
          proxies.

          If this option is used several times, the last one will be used.

1

我已经尝试过了,但没有起到帮助的作用。在这种情况下使用requests的优点是什么? - Josh Horowitz
好的,我在我的环境中使用数据包捕获运行了这个程序,结果显示urllib没有向代理发送CONNECT请求,这是不正确的。然后我阅读了https://docs.python.org/2/howto/urllib2.html,其中指出:“目前urllib2不支持通过代理获取https位置。但是,可以通过扩展urllib2来启用此功能,如http://code.activestate.com/recipes/456195中所示。”我建议使用requests python模块,因为它似乎比尝试使用urllib更简单、更容易使用。 - Yuvika

0

使用超时怎么样?如果代理在30秒内无法连接,则应将其标记为未连接。

def fetch(url, server):
 proxy_handler = urllib2.ProxyHandler({'http':'https://'+server+':443'})
 opener = urllib2.build_opener(proxy_handler, urllib2.HTTPHandler(debuglevel=0))
 urllib2.install_opener(opener)

 try:
  response = opener.open( url, timeout = 30)
  return response.read()
 except:
  print "Can't connect with proxy %s" % (server)

print fetch(url,serverIp)

您可以更改debuglevel = 1以查看连接详细信息。

我将其用于全局代理,并且在我的互联网连接中,30秒是最长的超时时间,以了解是否已连接。在我的测试中,如果连接时间超过30秒,则始终失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接