Sending numerous packets instead of 1 SSL Python

447 views Asked by At

I have set up an experiment where I pass Modbus traffic over a SSL tunnel (this being the first thing I've ever done in python). I am able to send and receive data but when I send one request numerous requests are actually sent (see screenshot)

enter image description here

I've tried numerous configurations including (in both client and server):

send()--no change
sendall() --no change
setblocking(1)
setblocking(0)--doesn't read all the data

On the server side:
if data == Read_Coils_Answer-- I don't think I'm converting the big endian properly for comparison and this didn't work
while data: --the while loop seems to be the only way to prevent either side from stopping short with a "Broken Pipe" error. So this is what I'm using.

I eventually plan to use a for loop (now commented out and set to 4).

My Server code:

from ModLib import *
import socket, ssl, sys, pprint

try:
bindsocket = socket.socket()
bindsocket.bind(('', 502))
bindsocket.listen(5)
bindsocket.setblocking(1)

def do_something(connstream, data):
    readCoilsReq = str('\x01\x01\x00')
    answer = str(ModbusPDU01_Read_Coils_Answer)
    while data:
        print ("Request Recevied from Client:")
        print pprint.pformat(data)
        connstream.send(answer)
        print ("Answer Sent to Client")
        print pprint.pformat(answer)
    return False

def deal_with_client(connstream):
    data = connstream.recv(64)
    while data:
        if not do_something(connstream, data):
            break
        data = connstream.recv(64)

while True:
    newsocket, fromaddr = bindsocket.accept()
    connstream = ssl.wrap_socket(newsocket,
                         server_side=True,
                         certfile="server.crt",
                         keyfile="server.key",
                         ssl_version=ssl.PROTOCOL_TLSv1)
    try:
        deal_with_client(connstream)
    finally:
        connstream.shutdown(socket.SHUT_RDWR)
        connstream.close()
except KeyboardInterrupt:
print ("\nTerminating Session at User Request")
print ("No More Data Will be Sent/Recieved\n")
sys.exit(1)

My Client Side code:

from ModLib import *
from time import sleep
import socket, ssl, pprint

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ssl_sock = ssl.wrap_socket(s,
           ca_certs="server.crt",
           cert_reqs=ssl.CERT_REQUIRED)

ssl_sock.connect(('localhost', 502))
ssl_sock.setblocking(1)

readCoils = ModbusPDU01_Read_Coils()

#for i in range(4):
sleep(2)
ssl_sock.sendall(str(readCoils))
print ("Request for Read Coils Sent")

#start receive
data = ssl_sock.recv(64)
print ("Response from Server:")
print pprint.pformat(data)

if False: #from the python docs
    ssl_sock.write("""GET / HTTP/1.0\r
    Host: www.verisign.com\n\n""")

    data = ssl_sock.read()

    ssl_sock.close()
1

There are 1 answers

0
Chris On

The do_something() loop was not necessary, as the deal_with_client() loop was doing the same thing. I removed do_something() and put the code in deal_with_client() which allows me to keep the connection open (see below)

from ModLib import *
import socket, ssl, sys, pprint

try:
    bindsocket = socket.socket()
    bindsocket.bind(('', 502))
    bindsocket.listen(5)
    bindsocket.setblocking(1)

    def deal_with_client(connstream):
        data = connstream.recv(1120)
        answer = str(ModbusPDU01_Read_Coils_Answer())
        while data:
            print ("Request Received from Client:")
            print pprint.pformat(data)
            connstream.send(answer)
            print ("Answer Sent to Client")
            print pprint.pformat(answer)
            data = connstream.recv(1120)

    while True:
        newsocket, fromaddr = bindsocket.accept()
        connstream = ssl.wrap_socket(newsocket,
                                     server_side=True,
                                     certfile="server.crt",
                                     keyfile="server.key",
                                    ssl_version=ssl.PROTOCOL_TLSv1)
        try:
            deal_with_client(connstream)
        finally:
            connstream.shutdown(socket.SHUT_RDWR)
            connstream.close()
except KeyboardInterrupt:
    print ("\nTerminating Session at User Request")
    print ("No More Data Will be Sent/Received\n")
    sys.exit(1)