简体   繁体   English

Python3 套接字编程与 SSL 错误?

[英]Python3 Socket Programming with SSL errors?

I'm just learning the basics of Python socket programming and secure networking.我只是在学习 Python 套接字编程和安全网络的基础知识。 I've connected two VM's on my network, and I want to see the difference between encrypted vs. non-encrypted messages in Wireshark.我已经在我的网络上连接了两个虚拟机,我想看看 Wireshark 中加密和非加密消息之间的区别。 So, I followed these tutorialshttps://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309 and https://docs.python.org/2/library/ssl.html#server-side-operation and https://docs.python.org/3.8/library/ssl.html#server-side-operation to set up some openSSL certificates for my server VM, and I copied the rootCA certificate to my client VM. So, I followed these tutorialshttps://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309 and https://docs.python.org/2/library/ssl.html#server-side-operation and https://docs. python.org/3.8/library/ssl.html#server-side-operation为我的服务器 VM 设置一些 openSSL 证书,然后我将 rootCA 证书复制到我的客户端 VM。

These are the commands I followed to create my self-signed certificates:这些是我创建自签名证书时遵循的命令:

openssl genrsa -des3 -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256

When it asked for a Common Name, I gave it the IP of my server, which is 172.25.1.5.当它询问通用名称时,我给了它我服务器的 IP,即 172.25.1.5。

However, when I try to run my server and client python scripts, I get these errors:但是,当我尝试运行服务器和客户端 python 脚本时,出现以下错误:

$ python3 server.py 
what is host? 172.25.1.5
server bound.
server listening
Accepted conn from: ('172.25.1.4', 59592)
Traceback (most recent call last):
  File "server.py", line 32, in <module>
    connstream = context.wrap_socket(conn,server_side=True)
  File "/usr/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/usr/lib/python3.6/ssl.py", line 817, in __init__
    self.do_handshake()
  File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:852)

On the client side, I see:在客户端,我看到:

$ python3 client.py 
Traceback (most recent call last):
  File "client.py", line 19, in <module>
    s.connect((host,port))
  File "/usr/lib/python3.6/ssl.py", line 1109, in connect
    self._real_connect(addr, False)
  File "/usr/lib/python3.6/ssl.py", line 1100, in _real_connect
    self.do_handshake()
  File "/usr/lib/python3.6/ssl.py", line 1077, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)

Here's my code for the server and client:这是我的服务器和客户端代码:

import os, socket, ssl

# host and port
host = "172.25.1.5" # my VM ip
port = 1234
print("what is host? " + host)

# create context for socket (with ssl security)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="server.crt",keyfile="server.key")

# create socket and bind the socket to a tuple of host,port
s = socket.socket()
s.bind((host,port))
print("server bound.")

# listen for connections. The normal max is 5. The slides have 1.
print("server listening")
s.listen(1)

# accept connection
conn,address = s.accept()
print("Accepted conn from: " + str(address))

# give connection context
connstream = context.wrap_socket(conn,server_side=True)
#connstream = conn
print("wrapped socket.")

# receive data loop
# breaks if no data received
while True:
    data = connstream.recv(1024).decode()
    if not data:
        break
    print("received from client: " + str(data))
    # echo back
    connstream.send(data.encode())
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
conn.close()

And here's my client script on a different VM:这是我在不同 VM 上的客户端脚本:

import os, socket, ssl

# get context
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_verify_locations("rootCA.crt")
# define host and port
host = "172.25.1.5" #ip of linked clone
port = 1234

# make socket and connect to tuple host,port. Wrap socket in context
s = context.wrap_socket(socket.socket(socket.AF_INET),server_hostname=host)
s.connect((host,port))

cert = s.getpeercert()
print("What is cert? " +str(cert))
print("\n\n")
# get input
msg = input("out: ")

# Receive msg loop and send loop
while msg.lower().strip() != '':
    s.send(msg.encode())
    data = s.recv(1024).decode()

    print("In: " + data)

    msg = input("Out: ")

s.close()

I am stuck.我被困住了。 I've made sure that my code follows the examples.我已确保我的代码遵循示例。 How do I get around these errors?如何解决这些错误? Is there something I'm missing?有什么我想念的吗?

Any help or explanation is appreciated.任何帮助或解释表示赞赏。 I'm still just learning.我还只是在学习。

Following Patrick Mevzek's advice in the comments, I tried changing the line按照 Patrick Mevzek 在评论中的建议,我尝试更改线路

context.load_cert_chain(certfile="server.crt",keyfile="server.key")

to

context.load_cert_chain(certfile="rootCA.crt",keyfile="rootCA.key")

That worked, and that told me that something went wrong when I created the server.crt and server.key.这行得通,这告诉我在创建 server.crt 和 server.key 时出了点问题。 So, I simply deleted server.key, server.csr, and server.crt in the server VM and recreated them using因此,我只是删除了服务器 VM 中的 server.key、server.csr 和 server.crt 并使用重新创建它们

openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256

After recreating them, I could use server.crt and server.key as the certfile and keyfile.重新创建它们之后,我可以使用 server.crt 和 server.key 作为 certfile 和 keyfile。

Using either my fake CA setup with server.crt or just directly using rootCA for SSL works for encrypting my messages, and using Wireshark also verified that.将我的假 CA 设置与 server.crt 一起使用,或者直接将 rootCA 用于 SSL 可用于加密我的消息,并且使用 Wireshark 也验证了这一点。

I appreciate everyone's help, and I hope this answer helps others who encounter this problem when playing around with socket programming and SSL.感谢大家的帮助,我希望这个答案能帮助其他在玩套接字编程和 SSL 时遇到这个问题的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM