why is it timing out like this? - python

I'm trying to build a TCP-proxy script that sends and receives data, i managed to get it to listen but it doesn't seem to be connecting properly...my code looks right to me and after checking python docs(i'm trying to run it in python 2.7 and 3.6) i get this timeout message:
Output:
anon#kali:~/Desktop/python scripts$ sudo python TCP\ proxy.py 127.0.0.1 21 ftp.target.ca 21 True
[*] Listening on 127.0.0.1:21d
[==>] Received incoming connection from 127.0.0.1:44806d
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "TCP proxy.py", line 60, in proxy_handler
remote_socket.connect((remote_host,remote_port))
File "/usr/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 110] Connection timed out
i looked into the file "/usr/lib/python2.7/socket.py" but couldn't really understand what i was looking for as it seemed right when i compared it to python docs and my script
my code:
# import the modules
import sys
import socket
import threading
#define the server
def server_loop(local_host,local_port,remote_host,remote_port,receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
server.bind((local_host, local_port))
server.listen(5)
print ("[*] Listening on %s:%sd" % (local_host, local_port))
except:
print("[!!] Failed to listen on %s:%sd" % (local_host,local_port))
print ("[!!] Check for others listening sockets or correct permissions")
sys.exit(0)
while True:
client_socket, addr = server.accept()
#print out the local connection information
print ("[==>] Received incoming connection from %s:%sd" % (addr[0],addr[1]))
#start a thread to talk to the remote host
proxy_thread = threading.Thread(target=proxy_handler,args=(client_socket,remote_host,remote_port,receive_first))
proxy_thread.start()
else:
print ("something went wrong")
def main():
#no fancy command-line parasing here
if len(sys.argv[1:]) !=5:
print ("Usage: ./TCP proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]")
print("Example: ./TCP proxy.py 127.0.0.1 9000 10.12.132.1 9000 True")
#set up local listening parameters
local_host = sys.argv[1]
local_port = int(sys.argv[2])
#set up remote target
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
#this tells proxy to connect and receive data before sending to remote host
receive_first = sys.argv[5]
if "True" in receive_first:
receive_first = True
else:
receive_first = False
#now spin up our listening socket
server_loop(local_host,local_port,remote_host,remote_port,receive_first)
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
#connect to the remote host
remote_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
remote_socket.connect((remote_host,remote_port))
#receive data from the remote end if necessary
if receive_first:
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
#send it to the repsonse handler
remote_buffer = respsonse_handler(remote_buffer)
#if data is able to be sent to local client, send it
if len(remote_buffer):
print ("[<==] Sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
#now loop and read from local,sent to remote,send to local,rinse/wash/repeat
while True:
#read from local host
local_buffer = receive_from(client_socket)
if len(local_buffer):
print ("[==>] Received %d bytes from localhost." % len(local_buffer))
#send it to request handler
local_buffer = request_handler(local_buffer)
#send data to remote host
remote_socket.send(local_buffer)
print ("[==>] Sent to remote.")
#receive back response
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print ("[<==] Received %d bytes from remote." % len(remote_buffer))
hexdump(remote_buffer)
#send response to handler
remote_buffer = response_handler(remote_buffer)
#send response to local socket
client_socket.send(remote_buffer)
print ("[<==] Sent to localhost.")
#if no data left on either side, close connection
if not len(local_buffer) or not len(remote_buffer):
client_socket.close()
remote_socket.close()
print ("[*] No more data, closing connections.")
break
#this is a pretty hex dumping function taken from the comments of http://code.activestate.com/recipes/142812-hex-dumper/
def hexdump(src, length=16):
result = []
digits = 4 if isinstance(src,unicode) else 2
for i in xrange(0,len(src), length):
s = src[i:i+length]
hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s])
text = b' '.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
result.append( b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text) )
print (b'/n'.join(result))
def receive_from(connection):
buffer = ""
#set a 2 second timeout; depending on your target this may need to be adjusted
connection.settimeout(2)
try:
#keep reading the buffer until no more data is there or it times out
while True:
data = connection.recv(4096)
if not data:
break
buffer += data
except:
pass
return buffer
#modify any requested destined for the remote host
def request_handler(buffer):
#perform packet modifications
return buffer
#modify any responses destined for the local host
def response_handler(buffer):
#perform packet modifications
return buffer
main()
i have tried different ftp servers/sites,etc but get the same result, where am i going wrong with my code? any input or direction would be greatly appreciated.

okay so turns out my script is good just the ftp servers i was running weren't haha
this is the final output:
anon#kali:~/Desktop/python scripts$ sudo python TCP\ proxy.py 127.0.0.1 21 ftp.uconn.edu 21 True
[*] Listening on 127.0.0.1:21d
[==>] Received incoming connection from 127.0.0.1:51532d
0000 32 32 30 20 50 72 6F 46 54 50 44 20 31 2E 32 2E 2 2 0 P r o F T P D 1 . 2 ./n0010 31 30 20 53 65 72 76 65 72 20 28 66 74 70 2E 75 1 0 S e r v e r ( f t p . u/n0020 63 6F 6E 6E 2E 65 64 75 29 20 5B 31 33 37 2E 39 c o n n . e d u ) [ 1 3 7 . 9/n0030 39 2E 32 36 2E 35 32 5D 0D 0A 9 . 2 6 . 5 2 ] . .
[<==] Sending 58 bytes to localhost.
[==>] Received 353 bytes from localhost.
[==>] Sent to remote.
[<==] Received 337 bytes from remote.

Related

Why does message MAC verification fail with an OpenSSL client but succeed with a python-mbedtls client

Currently I'm trying to develop a simple UDP DTLS server using pre shared keys on Ubuntu 20.04, to receive UDP datagrams from an embedded application.
My remote example echo server based on python-mbedtls correctly echoes messages from a python-mbedtls client used for testing, but fails to verify the message MAC during the handshake with an openssl command line s_client. It similarly fails to verify the MAC of my embedded DTLS client, even though that is correctly sending messages to a command line openssl s_server. These are all using the same pre-shared keys and client-identity.
Ideas on why MAC verification might be failing would be appreciated, or suggestions for diagnostics. There's not a lot that's useful in the debug outputs so far.
Here is my server code:
#!/home/ron/venvs/udpserver/bin/python3
"""Example DTLS server"""
import sys
import time
from contextlib import suppress
from functools import partial
from typing import Any, Callable, NoReturn, Optional, Tuple, Union
import datetime as dt
import socket
import struct
from mbedtls.pk import RSA, ECC
from mbedtls.x509 import BasicConstraints, CRT, CSR
from mbedtls.tls import *
from mbedtls._tls import _enable_debug_output, _set_debug_level # type: ignore
from mbedtls.tls import (
DTLSConfiguration,
HelloVerifyRequest,
ServerContext,
TLSWrappedSocket,
)
conf = DTLSConfiguration(
ciphers=(
"TLS-PSK-WITH-AES-256-CBC-SHA",
"TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
"TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256"
),
pre_shared_key=('Client_identity',b'010102030405060708090a0b0c0d0e0f'),
validate_certificates=False
)
print("conf: {}".format(conf))
_enable_debug_output(conf)
_set_debug_level(3)
def echo_until(sock, end):
cli0, cli_address0 = sock.accept()
cli0.setcookieparam(cli_address0[0].encode("ascii"))
print("cli_address0: {}".format(cli_address0))
try:
# block(cli0.do_handshake)
cli0.do_handshake()
except HelloVerifyRequest:
print("HVR")
cli1, cli_address1 = cli0.accept()
cli0.close()
cli1.setcookieparam(cli_address1[0].encode("ascii"))
print("cli_address1: {}".format(cli_address1))
# block(cli1.do_handshake)
cli1.do_handshake()
print(" .", "handshake", cli1.negotiated_tls_version())
cli = cli1
while True:
# data = block(cli.recv, 4096)
data = cli.recv(4096)
print(" .", "R", data)
# nn = block(cli.send, data)
nn = cli.send(data)
print(" .", "S", nn, len(data))
if data == end:
break
print(" .", "done")
print(cli)
cli.close()
address = ("0.0.0.0", 9009)
host, port = address
ctx = ServerContext(conf)
srv = ctx.wrap_socket(
socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print(" .", "bind", srv, address)
srv.bind(address)
while True:
print(" .", ">>>")
echo_until(srv, b"\0")
print(" .", "<<<")
and here is the client code that works:
#!/media/fred/venvs/dtlsclient/bin/python3
"""An example DTLS PSK client.
"""
from __future__ import annotations
import socket
import sys
import time
from contextlib import suppress
from typing import Any, Optional, Tuple, Union
from mbedtls._tls import _enable_debug_output, _set_debug_level # type: ignore
from mbedtls.exceptions import TLSError
from mbedtls.tls import (
ClientContext,
DTLSConfiguration,
TLSWrappedSocket,
)
if sys.version_info < (3, 10):
from typing_extensions import TypeAlias
else:
from typing import TypeAlias
if sys.version_info < (3, 8):
from typing_extensions import Final
else:
from typing import Final
def _echo_dtls(sock: TLSWrappedSocket, buffer: bytes, chunksize: int) -> bytes:
view = memoryview(buffer)
received = bytearray()
while len(received) != len(buffer):
part = view[len(received) : len(received) + chunksize]
sock.send(part)
data, _addr = sock.recvfrom(chunksize)
received += data
if not data:
# Avoid tight loop.
time.sleep(0.01)
return received
class Client:
def __init__(
self,
cli_conf: DTLSConfiguration,
proto: socket.SocketKind,
srv_address: _Address,
srv_hostname: Optional[str],
) -> None:
super().__init__()
self.cli_conf: Final = cli_conf
self.proto: Final = proto
self.srv_address: Final = srv_address
self.srv_hostname: Final = srv_hostname
self._sock: Optional[TLSWrappedSocket] = None
self._echo: Final = {
socket.SOCK_DGRAM: _echo_dtls,
}[self.proto]
def __enter__(self) -> Client:
self.start()
return self
def __exit__(self, *exc_info: object) -> None:
self.stop()
def __del__(self) -> None:
self.stop()
#property
def context(self) -> Optional[ClientContext]:
if self._sock is None:
return None
assert isinstance(self._sock.context, ClientContext)
return self._sock.context
def do_handshake(self) -> None:
if not self._sock:
return
self._sock.do_handshake()
def echo(self, buffer: bytes, chunksize: int) -> bytes:
if not self._sock:
return b""
return bytes(self._echo(self._sock, buffer, chunksize))
def start(self) -> None:
if self._sock:
self.stop()
self._sock = ClientContext(self.cli_conf).wrap_socket(
socket.socket(socket.AF_INET, self.proto),
server_hostname=self.srv_hostname,
)
self._sock.connect(self.srv_address)
def stop(self) -> None:
if not self._sock:
return
with suppress(TLSError, OSError):
self._sock.close()
self._sock = None
def restart(self) -> None:
self.stop()
self.start()
def main() -> None:
address = "149.28.170.96"
port = 9009
message = "Trundled off to the jungle"
server_name = "dtlsserver"
proto = socket.SOCK_DGRAM
debug = 3
conf = DTLSConfiguration(
ciphers=(
"TLS-PSK-WITH-AES-256-CBC-SHA",
"TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
"TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256"
),
pre_shared_key=('Client_identity',b'010102030405060708090a0b0c0d0e0f'),
validate_certificates=False
)
print(conf)
if debug is not None:
_enable_debug_output(conf)
_set_debug_level(debug)
with Client(
conf, proto, (address, port), server_name
) as cli:
cli.do_handshake()
received = cli.echo(message.encode("utf-8"), 1024)
print("Received:" + received.decode("utf-8"))
if __name__ == "__main__":
main( )
Whereas an openssl command line client invocation like this fails:
openssl s_client -psk "010102030405060708090a0b0c0d0e0f" -psk_identity "Client_identity" -dtls1_2 -port 9009 -host 149.28.170.96 -async -debug
This same call works ok with an openssl s_server running on the same remote Ubuntu server.
Here's a partial listing of debug text from the server showing the failure using the openssl client:
ssl_msg.c:3620: input record: msgtype = 22, version = [3:3], msglen = 68
ssl_msg.c:1131: => decrypt buf
ssl_msg.c:1342: using encrypt then mac
ssl_msg.c:1385: message mac does not match
ssl_msg.c:3755: ssl_decrypt_buf() returned -29056 (-0x7180)
ssl_msg.c:4921: => send alert message
ssl_msg.c:4922: send alert level=2 message=20
ssl_msg.c:2684: => write record
ssl_msg.c:2797: output record: msgtype = 21, version = [254:253], msglen = 2
ssl_msg.c:2087: => flush output
ssl_msg.c:2105: message length: 15, out_left: 15
ssl_msg.c:2112: ssl->f_send() returned 15 (-0xfffffff1)
ssl_msg.c:2140: <= flush output
ssl_msg.c:2853: <= write record
ssl_msg.c:4934: <= send alert message
ssl_msg.c:3917: ssl_get_next_record() returned -29056 (-0x7180)
ssl_tls.c:3650: mbedtls_ssl_read_record() returned -29056 (-0x7180)
ssl_msg.c:0072: set_timer to 0 ms
ssl_msg.c:0072: set_timer to 0 ms
Traceback (most recent call last):
File "/home/ron/venvs/udpserver/./dtlsthreaded.py", line 96, in <module>
echo_until(srv, b"\0")
File "/home/ron/venvs/udpserver/./dtlsthreaded.py", line 64, in echo_until
block(cli1.do_handshake)
File "/home/ron/venvs/udpserver/./dtlsthreaded.py", line 28, in block
result = cb(*args, **kwargs)
File "/home/ron/venvs/udpserver/lib/python3.10/site-packages/mbedtls/tls.py", line 341, in do_handshake
self._buffer.do_handshake()
File "src/mbedtls/_tls.pyx", line 1404, in mbedtls._tls.MbedTLSBuffer.do_handshake
File "src/mbedtls/_tls.pyx", line 1429, in mbedtls._tls.MbedTLSBuffer._handle_handshake_response
File "src/mbedtls/exceptions.pyx", line 53, in mbedtls.exceptions.check_error
File "src/mbedtls/exceptions.pyx", line 56, in mbedtls.exceptions.check_error
mbedtls.exceptions.TLSError: TLSError([0x7180] 'SSL - Verification of the message MAC failed')
ssl_tls.c:6800: => free
The same errors occur when all cipher suites are enabled, so am pretty sure the problem isn't the cipher.
Suggestions for diagnosis appreciated. Thanks.
Though a similar question got answered in the Nordic DevZone it may be also the answer for this question.
For openssl, "010102030405060708090a0b0c0d0e0f" results in a 16 bytes secret.
About
b'010102030405060708090a0b0c0d0e0f'
I'm not that sure. From other SO questions, I think it's a 32 bytes secret.
If the peers don't share the same secret, the handshake fails. Some implementations will simple timeout the handshake, other may report a MAC validation error, because a mismatching secret creates different association keys, and with that, the MAC validation of the handshake 'Finish' fails.
Either use "30 31 30 31 30 32 30 33 30 34 30 35 30 36 30 37 30 38 30 39 30 61 30 62 30 63 30 64 30 65 30 66" (remove the spaces!) for openssl, or use b'\x01\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' for python.
Hope, that works.

Why this simple port scanner hangs?

I'm making very simple unthreaded Python port scanner:
import sys, socket
1
2 try:
3 host = sys.argv[1]
4 print(host)
5 except IndexError:
6 print('missing arg')
7 sys.exit()
8
9 ports = [22, 23, 80, 53, 443, 8080]
10 try:
11 for port in ports:
12 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
13 socket.setdefaulttimeout(1.0)
14 result = sock.connect_ex((host, port)) # hangs on this line
15 print(result)
16 print(f'Checking port {port}')
17 if result == 0:
18 print(f'Port {port} is open')
19 sock.close()
20 except KeyboardInterrupt:
21 print('Exiting ...')
22 sys.exit()
23 except Exception as e:
24 print(str(e))
25 sys.exit()
Before I removed all print statements I found out that the script hung on indicated line. The line where simple indication of established connection is made (or not made).
Port scanner is ran against my router by running python port_scanner.py 192.168.1.254
What might be an issue here ?
Moving socket.setdefaulttimeout(1.0) above the for loop solved the issue. Thanks goes to #Barmar

Python socket.recv() returning new lines?

I'm fairly new to Python. I have two scripts running that are communicating with each other, but once the sender process stops sending bytes, the receiver process receives an endless stream of what decodes (UTF-8) to new lines. I've reduced the code as much as I could to keep things simple:
Sender Python script.
import socket
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.bind((host, port))
data_to_send = ['1','2','3','4','5','6','7','8','9']
s.listen(1)
c, addr = s.accept()
print ('Got connection from ', addr,'. Sending data...', sep='')
for data in data_to_send:
message = data.encode('utf-8')
c.sendall(message)
Receiver Python script.
import socket
messages_received = 0
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.connect((host, port))
while True:
incoming_message = s.recv(1024).decode('utf-8')
messages_received += 1
# This condition is just to avoid printing thousands of lines
if messages_received < 10:
print(messages_received, ':', incoming_message)
Receiver output.
1 : 1
2 : 23456789
3 :
4 :
5 :
6 :
7 :
8 :
9 :
What am I doing wrong? I would ideally want the sender script to break out of the "While True" loop if the socket closes.
As #jasonharper pointed out, all I needed to do was to check for empty messages and break the loop as soon as that happens. When the sender doesn't send anything, the receiver doesn't receive empty massages, it just waits for a valid message, which I didn't know. The following code worked for me:
Sender Python script.
import socket
import time
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.bind((host, port))
data_to_send = ['1','2','3','4','5','6','7','8','9']
s.listen(1)
c, addr = s.accept()
print ('Got connection from ', addr,'. Sending data...', sep='')
for data in data_to_send:
message = data.encode('utf-8')
c.sendall(message)
time.sleep(1)
Receiver Python script.
import socket
messages_received = 0
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.connect((host, port))
while True:
incoming_message = s.recv(1024).decode('utf-8')
messages_received += 1
if not incoming_message:
break
if messages_received < 10:
print(messages_received, ':', incoming_message)
Receiver output.
1 : 1
2 : 2
3 : 3
4 : 4
5 : 5
6 : 6
7 : 7
8 : 8
9 : 9
well you can try setting the buffer size on sender side :
socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) # Buffer size 1024
if it dosent work you can try even dict format so you send data as json format.

python socket; my connection is breaking my data stream

I am trying to connect to a socket server and view/download a temperature readings polling stream
i.e.
72.81
72.83
72.79
72.85
But what I get are float values split in half.
72
.35
72
.36
72
.36
72
.37
72
.38
72
.38
72
.38
72
.39
How do I output unbroken float values from a socket connection?
client code:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("192.168.1.249" , 8080))
s.sendall(b"GET / HTTP/1.1\r\nHost: webcode.me\r\nAccept: text/html\r\nConnection: close\r\n\r\n")
while True:
data = s.recv(1024)
if not data:
break
print(data.decode())

Pyserial - RS232 9600,8,N,1 send and receive data

I need to communicate and pass values to a serial connected device using RS232 Protocol. I need to pass commands through the 8 bytes of data and then be able to receive the response afterwards.. Im not sure how to write this in PySerial so if anyone can help out it would be great (9600 Baud, 8 data bits, No parity, and 1 stop bit.)
import serial
ser = serial.Serial('/dev/ttyUSB0') # open serial port
print(ser.name) # check which port was really used
ser.write(b'hello') # write a string
ser.close() # close port
The Timer Manager Command structure consists of one start byte, one command byte, five bytes of data, and a one byte checksum. Each message packet is formatted as follows:
BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
200 COMMAND DATA1 DATA2 DATA3 DATA4 DATA5 CK SUM
Im looking to receive the following back from the machine:
If command was successfully received, the Timer Manager will respond with:
BYTE 0 BYTE 1 BYTE 2
6 0 6
The actual data that I want to send is this
Data i need to pass to the timer is structured this way:
BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 BYTE 5 BYTE 6 BYTE 7
200 31 4 0 0 0 0 235
Is this passed via bytearray ?
ser.write( bytearray(200,31,4,0,0,0,0,235) );
I generally have something like this to do binary IO over a serial port:
from timeit import default_timer as clk
from serial import Serial, SerialException
class TimeManager(object):
def __init__(self, port, baudrate=9600):
self.ser = Serial(port, baudrate=baudrate)
self.ser.open()
self.ser.flushInput()
self.ser.flushOutput()
def send(self, tx):
tx = bytearray(tx)
try:
self.ser.write(tx)
self.ser.flush()
except SerialException as e:
if e.args == (5, "WriteFile", "Access is denied."):
# This occurs on win32 when a USB serial port is
# unplugged and replugged. It should be fixed by
# closing and reopening the port, which should happen
# in the error handling of our caller.
raise IOError(errno.ENOENT, "Serial port disappeared.",
self.ser.portstr)
else:
raise
def receive(self):
rx = bytearray()
delay = 10e-3 # s
timeout = 1 # s
end_time = clk() + timeout
while True:
time_remaining = end_time - clk()
if time_remaining < 0:
break
rx += self.ser.read(self.ser.inWaiting())
if 0 in rx:
break
time.sleep(delay)
if time_remaining <= 0:
raise IOError(errno.ETIMEDOUT, "Communication timed out.")
return rx
tm = TimeManager("/dev/ttyS0")
My device sends null terminated messages (the if 0 in rx: line). You'd have to figure out a similar condition for your messages.
First of all, due to the fact that you use RS232, you must set the ASCII characters you wanna send in variables. And then, when you got in a variable all the sentence you want to send, sent it decoding it into bytes.
It would be something like this.
def sendserial(sendstring):
ser.port(yourport)
try:
ser.open()
except Exception as e:
flag=1
if ser.isOpen():
try:
ser.flushInput()
ser.flushOutput()
ser.write(bytes(sendstring,'iso-8859-1'))
#iso 8859-1 is the only encode that works for me
time.sleep(0.5)
numOfLines = 0
while True:
resp = bytes.decode(ser.readline())
result = ord(str(response))
if result == ord(ACK)
#I set previously the ACK var to the ASCII symbol that the machine returns
response = 'Y'
else:
response = 'N'
numOfLines = numOfLines +1
if (numOfLines>=1):
break
ser.close()
except Exception as e1:
print('Communication error...:' + str(e1))
else:
pass
return(response)

Categories

Resources