Python TLS version matching
Asked Answered
O

1

0

I am using python 3.8 I got below outputs on my Ubuntu system:

>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 1.1.1f  31 Mar 2020'
>>> ssl.PROTOCOL_TLSv1_2
<_SSLMethod.PROTOCOL_TLSv1_2: 5>

I am trying to use Modbus TCP connection with TLS so I added some related function between #warning myCode START and #warning myCode END lines

This is Client side:

    class TcpMaster(Master):
        """Subclass of Master. Implements the Modbus TCP MAC layer"""
    
        def __init__(self, host="127.0.0.1", port=502, timeout_in_sec=5.0):
            """Constructor. Set the communication settings"""
            super(TcpMaster, self).__init__(timeout_in_sec)
            self._host = host
            self._port = port
            self._sock = None
    
        def _do_open(self):
            """Connect to the Modbus slave"""
            if self._sock:
                self._sock.close()
            self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.set_timeout(self.get_timeout())
            self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            call_hooks("modbus_tcp.TcpMaster.before_connect", (self, ))
#warning myCode START
            context = SSLContext(PROTOCOL_TLS_CLIENT)
            context.load_verify_locations('cert.pem')
            with create_connection((self._host, self._port)) as client:
                print("1")
                with context.wrap_socket(client, server_hostname=self._host) as tls:
                 print(2)
                 1==1
#warning myCode END
                 
            self._sock.connect((self._host, self._port))
            call_hooks("modbus_tcp.TcpMaster.after_connect", (self, ))
    
    
        def _do_close(self):
            """Close the connection with the Modbus Slave"""
            if self._sock:
                call_hooks("modbus_tcp.TcpMaster.before_close", (self, ))
                self._sock.close()
                call_hooks("modbus_tcp.TcpMaster.after_close", (self, ))
                self._sock = None
                return True
    
        def set_timeout(self, timeout_in_sec):
            """Change the timeout value"""
            super(TcpMaster, self).set_timeout(timeout_in_sec)
            if self._sock:
                self._sock.setblocking(timeout_in_sec > 0)
                if timeout_in_sec:
                    self._sock.settimeout(timeout_in_sec)
    
        def _send(self, request):
            """Send request to the slave"""
            retval = call_hooks("modbus_tcp.TcpMaster.before_send", (self, request))
            if retval is not None:
                request = retval
            try:
                flush_socket(self._sock, 3)
            except Exception as msg:
                #if we can't flush the socket successfully: a disconnection may happened
                #try to reconnect
                LOGGER.error('Error while flushing the socket: {0}'.format(msg))
                self._do_open()
            self._sock.send(request)
    
        def _recv(self, expected_length=-1):
            """
            Receive the response from the slave
            Do not take expected_length into account because the length of the response is
            written in the mbap. Used for RTU only
            """
            response = to_data('')
            length = 255
            while len(response) < length:
                rcv_byte = self._sock.recv(1)
                if rcv_byte:
                    response += rcv_byte
                    if len(response) == 6:
                        to_be_recv_length = struct.unpack(">HHH", response)[2]
                        length = to_be_recv_length + 6
                else:
                    break
            retval = call_hooks("modbus_tcp.TcpMaster.after_recv", (self, response))
            if retval is not None:
                return retval
            return response
    
        def _make_query(self):
            """Returns an instance of a Query subclass implementing the modbus TCP protocol"""
            return TcpQuery()

I coundt see print("2") program start waiting and contuinue forever. And when I checked the wireshark, I get below outputs: enter image description here

I think this errors occurs because of the TLS version, my python support 1.2 TLS but I see TLS1.0 version on the wireshark. How can I solve the problem ?

When I interrupt the waiting process I get this:

    with context.wrap_socket(client, server_hostname=self._host) as tls:
  File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
KeyboardInterrupt

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

EDIT: If I try below lines, it does not work. Client send TLSv1 version.

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.options |= ssl.OP_NO_SSLv3
context.options |= ssl.OP_NO_TLSv1
context.options |= ssl.OP_NO_TLSv1_1
Odd answered 27/9, 2021 at 8:47 Comment(3)
You see TLSv1, not TLSv1.0.Aciniform
by the way I am using python 3.8Odd
@KlausD. I see TLSv1 but I couldnt see TLSv1.2 from client. How can I solve this problem ?Odd
I
1

I think this errors occurs because of the TLS version,

This is a network/transport layer problem, i.e. the client does not get the servers response and thus does not send the TCP ACK - or the client does send the ACK but it is lost on the way to the server (it is unclear where you sniff the traffic).

It has nothing to do with the TLS version and therefore you cannot solve it as this level.

Issuant answered 27/9, 2021 at 13:47 Comment(1)
Thank you for your reply, I am trying to find why this happenning ? And this is different topic so I oppened new issue stackoverflow.com/questions/69348645/tls-handshaking-issueOdd

© 2022 - 2024 — McMap. All rights reserved.