2017-07-14 66 views
0

我正尝试使用python创建套接字连接。在Python中验证对端

这里是我的Python代码...

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
socket.settimeout(config['timeout']) 
self.socket.connect((config['host'], config['port'])) 

self.ssl = ssl.wrap_socket(
    self.socket, 
    certfile=config['certificate'], 
    keyfile=config['key'] 
) 

远程服务器的证书似乎是自签名或信任存储缺少它没有工作。我是新来的python,并不知道如何禁用python中的verify_peer,所以连接可以工作。

我有工作在PHP代码...

$context = stream_context_create([ 
    'ssl' => [ 
     'verify_peer' => false, 
     'local_cert' => $config['certificate'], 
     'local_pk' => $config['key'] 
    ] 
]); 

$socket = stream_socket_client(
    'ssl://secure.test.com:700', 
    $errno, $errstr, $config['timeout'], 
    STREAM_CLIENT_CONNECT, $context 
); 

设置'verify_peer' => false有助于建立连接。我如何在Python中做类似的事情?

OpenSSL的调试

openssl s_client -connect secure.test.com:700 

verify error:num=20:unable to get local issuer certificate 
verify return:1 

verify error:num=21:unable to verify the first certificate 
verify return:1 

请帮助和建议。谢谢

+0

*“设置'verify_peer => FALSE'有助于确立连接。我如何在python中做类似的事情?“ - 非常糟糕的主意;请参阅[世界上最危险的代码:在非浏览器软件中验证SSL证书](http://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html)。 – jww

+0

*“它不起作用,因为远程服务器的证书似乎是自签名的或从信任存储库中丢失...” - - 这是什么?用例影响答案。请发布您用于连接服务器的URL,并发布'openssl s_client -connect -tls1 -servername | openssl x509 -text -noout'。点击*编辑*(不要将其作为评论发布),将其添加到您的问题中。否则,我们无法复制它,并且没有足够的信息来帮助排除故障。 – jww

+0

@jww感谢您的帮助。我已经编辑了更多细节的问题。我得到这个错误:'验证错误:num = 20:无法获得本地颁发者证书'已经尝试通过Linux命令重新获取当前证书'openssl s_client -connect secure.test.com:700:' – seoppc

回答

0

禁用证书验证可以简单地通过添加cert_reqs = ssl.CERT_NONE完成。但是,只要禁用证书验证是一个非常糟糕的主意,因为您知道对man-in-the-middle attacks开放。

因此您应该检查证书是否是预期的证书。对于自签名证书(和其他人也行),您可以检查例如接收到的证书下面的代码预期的证书指纹一致,如:

import socket 
import ssl 
import hashlib 

dst = ('www.paypal.com',443) 
fp_expected = '0722d46c216327bab8075f5db57ebed64d80e6699204c249c3f6ea9cc281c15b' 

# connect to the target with TCP 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect(dst) 

# upgrade the socket to SSL without checking the certificate 
s = ssl.wrap_socket(s,cert_reqs = ssl.CERT_NONE) 

# get certificate, compute fingerprint and check against expected value 
cert_bin = s.getpeercert(True) 
fp = hashlib.sha256() 
fp.update(cert_bin) 
assert(fp.hexdigest() == fp_expected) 
+0

感谢您的解释。我被这个错误困住了。当我运行'openssl s_client -connect secure.test.com:700 -key client'时,验证错误:num = 20:无法获得本地颁发者证书并且验证错误:num = 21:无法验证第一个证书。 key -cert client.crt',所以我想禁用证书检查。 – seoppc

+0

@seoppc:上面的代码可以用来验证服务器证书是否是自签名或某种程度上中断的预期。但是它应该有适当的证书+链,那么你可能从一开始就做错了:例如,它可能是服务器要求你使用SNI扩展来获得一个简单的wrap_socket不能实现的正确的证书和链。请注意,我无法使用s_client进行测试,因为secure.test.com:700无法从我的位置访问,即TCP连接已失败。 –