Python client hanging when sending empty message to server - python

I have a python reverse shell that I am working on that utilizes a client-server connection using TCP. I am testing them both right now on my localhost windows machine and I am utilizing the subprocess library to handle commands. The client is supposed to send a command to the server and the server will reply back with the output.
Server:
import socket
import subprocess
import os
# Server
# creates TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# port and server ip(localhost)
LOCAL_HOST = '127.0.0.1'
PORT = 5565
BUFFER_SIZE = 5000 # size of message
no_char_message = "-1: Please enter a command"
# test connection
print("Server starting up on %s with port number %s" % (LOCAL_HOST, PORT))
# bind socket to ip and port
sock.bind((LOCAL_HOST, PORT))
# listen to socket
sock.listen(1)
# socket will accept connection and client address
print("Waiting for connection") # waiting for connection
connection, address = sock.accept() # accept connection with client address
print("Connected to", address) # connected by address
while True:
command = connection.recv(BUFFER_SIZE) # receive message from client
if not command:
break
if len(command) == 0:
connection.send(str.encode(no_char_message))
if len(command) > 0:
terminal = subprocess.Popen(command[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=subprocess.PIPE)
output = terminal.stdout.read() + terminal.stderr.read()
output_as_string = str(output, "utf-8")
connection.send(str.encode(output_as_string))
print(output_as_string)
print("Closing Server")
sock.close()
connection.close()
Client
import socket
# Client
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # creates TCP Socket
# local host and port
LOCAL_HOST = '127.0.0.1'
PORT = 5565
BUFFER_SIZE = 5000 # size of message
# connect socket to ip and port
sock.connect((LOCAL_HOST, PORT))
print("Connected to server\n")
while True:
message = input("Please enter a command:\n") # ask user to input message
if message == 'quit':
break
print("Sending %s" % message)
sock.send(str.encode(message)) # send message
command = str(sock.recv(BUFFER_SIZE), "utf-8") # receive message
print("received %s" % command)
print("closing connection with server")
sock.close()
The issue is when I send an empty message to the server it hangs and just says sending in the terminal and the server never receives anything. I am not sure what is causing this but I am assuming the pipes are being blocked or that I am not handling this correctly.
I want the server to return an error message to the client rather than handle the message error in the client itself.
I tried checking the condition if the length of the command is 0 and handling it with an error message but it did not work and still hangs.
The program also seems to hang when I try for example the date command.
In general, how do I handle the condition if a command is not recognized, empty or doesn't execute successfully?

TCP has no concept of an empty message. TCP has no concept of a message at all, it knows only bytes. Thus, if you call send with an empty string it will simply send nothing (not an empty packet but no packet at all) to the server which means that there is nothing for the server to receive - it will still block while waiting for data. In other words: there is no empty command, there is simply no comment at all.
if len(command) == 0:
This will not check for an empty message (which again does not exist) but will trigger if the client closes the connection. Any check for an empty command had to be done at the client already.

Related

Python socket throwing the following error ConnectionResetError: [Errno 54] Connection reset by peer

I have been trying to create a messaging service in python using sockets. I have written the code to host two connections and allow one to send messages to the other using username and host_addr.
But every time I try to connect the second client and send a message from the first getting the following error.
ConnectionResetError: [Errno 54] Connection reset by peer
Server.py
import socket
import _thread as thread
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 1237 # Port to listen on (non-privileged ports are > 1023)
user_mapping = {}
def on_new_client(conn, addr):
data = conn.recv(1024)
data = data.decode()
print(data)
print(user_mapping)
if data[:8] == "username":
user_mapping[data[9:]] = (addr, data[9:])
elif data[0] == "#":
for i in user_mapping.values():
if i[0] == addr:
from_user = i[1]
else:
str = "user not found"
conn.sendto(str.encode(), addr)
str = "%s:%s" % (from_user, data[data.find(":") + 1:])
conn.sendto(str.encode(), user_mapping[data[1:data.find(":")](0)])
else:
pass
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(10)
while True:
conn, addr = s.accept()
thread.start_new_thread(on_new_client,(conn,addr))
s.close()
Client.py
import socket
HOST = "127.0.0.1" # The server's hostname or IP address
PORT = 1237 # The port used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
username = input("Enter user name")
str = "username: %s" % username
s.send(str.encode())
while True:
message = input(username+">")
s.send(message.encode())
data = s.recv(1024)
print(data)
Was hoping some would could answer why this is happening and guide me to any good links where there is Information on creating a messaging service in python.
Client is sending 2 messages and then receiving one.
But server just listen once and then send one or two packages.
Chronologically:
Client sends a package, and server reads it.
Then both client and server try to send a package. Both packages that won't meet a listening peer.
Then client try to receive a package, but server won't send (he already sent it before) or it may send but its too late because communication is already broken.
Concepts you may implement always:
If one talk, another one may listen.
If a package is mean to be sent, it shall be sent anyway. Dont let a 'if' statment that send package when at 'else' that does not (or viceversa).
==== EDIT ====
About solution:
You need to work with paralel loops.
Take a look at this code https://www.neuralnine.com/tcp-chat-in-python/
He uses two threads on client, one for keep listening for new server updates (messages for other people) and another one to wait input from user.

FTP server not sending data to proxy in Python with sockets

I'm building a proxy in Python between a ftp client and a ftp server. All the control phase and data phase is well done (currently on active mode), but when I send the request (LIST, for example), server does not send the information back. I don't know what is causing this fault...
Here is the Wireshark capture:
And the corresponding code:
print(f"Waiting for a message from the server to the PORT message")
answer = fw_proxy_server.recv(BUFFER_FTP)
print(answer) # 200 PORT command successful
fw_proxy_client.send(answer) # forward to client
# Create the socket to listen on 192.168.30.80:port (IP_PROXY:port)
server_socket2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket2.setsockopt(socket.SOL_SOCKET, 25, str(INTERFACE_PROXY_SERVER + '\0').encode('utf-8'))
server_socket2.bind((IP_PROXY, port))
server_socket2.listen()
print(f"Waiting for a message from the client")
message = fw_proxy_client.recv(BUFFER_FTP) # REQUEST: LIST
print(f"Forwarding message from the server")
message = send(fw_proxy_server, "LIST") # REQUEST: LIST (sent to port 21)
# Accept an incoming connection from the Server with data
server_socket2, data_address = server_socket2.accept() # HERE PROGRAM HANG
print(f"Data connection from {data_address} has been established!")
print(f"Waiting for a message from the data from server")
message = fw_proxy_server.recv(BUFFER_FTP) # never executed
The IPs are the following:
Client: 192.168.40.50
Proxy-client: 192.168.40.80
Proxy-server: 192.168.30.80
Server: 192.168.30.90
Thanks in advance.
EDIT:
Changed order of listening to port, so that the port is listened before sending the PORT command and the LIST request. Same result, connection refused:
start = str(message).find("(")
end = str(message).find(")")
tuple = str(message)[start+1:end].split(',')
port = int(tuple[4])*256 + int(list(filter(str.isdigit, tuple[5]))[0])
#Create the socket to listen on 192.168.40.80:port
server_socket2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket2.setsockopt(socket.SOL_SOCKET, 25, str(INTERFACE_PROXY_SERVER + '\0').encode('utf-8'))
server_socket2.bind(("192.168.40.80", port)) # With 192.168.30.80 it doesn't work too
server_socket2.listen()
answer = send(fw_proxy_server, "PORT 192,168,30,80," + tuple[4] + "," + tuple[5])
print(f"Waiting for a message from the server to the PORT message")
print(answer) # 200 PORT command successful
fw_proxy_client.send(answer)
#Create the socket to forward the data to the server
print(f"Waiting for a request from the client") # REQUEST: LIST
message = fw_proxy_client.recv(BUFFER_FTP)
print(message)
fw_proxy_server.send(message)
print(f"Waiting for an answer from the server") # Response 425: Unable to build data connection: Connection refused
answer = fw_proxy_server.recv(BUFFER_FTP)
print(answer)
#Accept an incoming connection from the Client
server_socket2, data_address = server_socket2.accept() #Program hang
print(f"Data connection from {data_address} has been established!")
print(f"Waiting for a message from the server")
print(answer)
From the Wireshark capture session, it sounds like the port you are sending to the FTP server and the port you are actually listening for data-connection on the proxy-server are not same hence FTP server reporting connection refused. Make sure the port server_socket2 is binding i.e, port is equal to 256 * tuple[4] + tuple[5]. I believe the socket_option 25 refers to SO_BINDTODEVICE, in that case when you are binding the socket using bind() then there is no need to explicitly bind the socket to interface (in general use case). Can you remove that line and check if it is still working ? It will be a learning for me too ! Thanks.

How to encode traffic socket?

Hi i have my server client model i need to encode the traffic which is HTTP1.1 how should i do this this is my server code
server:
import socket
from base64 import b64encode
SERVER_HOST = "0.0.0.0"
SERVER_PORT = 5003
BUFFER_SIZE = 1024
# create a socket object
s = socket.socket()
# bind the socket to all IP addresses of this host
s.bind((SERVER_HOST, SERVER_PORT))
# make the PORT reusable
# when you run the server multiple times in Linux, Address already in use error will raise
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.listen(5)
print(f"Listening as {SERVER_HOST}:{SERVER_PORT} ...")
# accept any connections attempted
client_socket, client_address = s.accept()
print(f"{client_address[0]}:{client_address[1]} Connected!")
# just sending a message, for demonstration purposes
message = "Hello and Welcome".encode()
client_socket.send(message)
while True:
# get the command from prompt
command = input("Enter the command you wanna execute:")
# send the command to the client
if command == "3":
command2 = "arp -a"
client_socket.send(command2.encode())
else:
client_socket.send(command.encode())
if command.lower() == "exit":
# if the command is exit, just break out of the loop
break
# retrieve command results
results = client_socket.recv(BUFFER_SIZE).decode()
# print them
print(results)
# close connection to the client
client_socket.close()
# close server connection
s.close()
and this is what i am trying to do:
How should i achive this thanku.
First you should have encryption and decryption mechanism both on
server side and client side depending on your needs.
The next thing is to use Web Socket Secure Protocol (WSS) Configured
in your web server.

Python Socket, how do i choose between s.send and conn.send?

def send_Button():
try:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
except NameError:
myMsg = "ME: " + text.get()
msg = text.get()
conn.send(msg) ###
textBox.insert(END, myMsg + "\n")
textEntry.delete(0, END)
textBox.yview_pickplace("end")
This program uses the tkinter module with socket in python2.7. My program allows for you to either connect to a server to chat with or host a server for others to connect to you, but whenever I try and test it out then the lines with the '###' on always bring up an error and it doesn't work, the error which comes up is: "NameError: global name 'conn' is not defined" OR "error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied".
Any help please?
I think that you are trying to get the program to act as a Client or as a Server just changing s.send() to conn.send() saddly it isn't that simple.
Socket Initializzation
The socket have to be initialized before sending or receiving data.
For a client usually it's something like this.
send_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
send_socket.connect((serverIp, serverPort)) # Connect to the server
send_socket.send(data) # Send the data to the server
And like this for a Server:
listen_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create the socket
listen_socket.bind(("0.0.0.0", port)) # Set the socket to accept client from every interface on the port port
listen_socket.listen(1) # Put the server on listen on the port setted before
accept_socket, addr = self.listen_socket.accept() # when a client connect return the socket to talk with it
data = self.accept_socket.recv(buffer_size) # Receive data form the client of max size buffer_size
Docs examples
From your question I guess that with s.send() and conn.send() you are talking about
this example from the python 2.7 socket docs
Here are four minimal example programs using the TCP/IP protocol: a server that echoes all data that it receives back (servicing only one client), and a client using it. Note that a server must perform the sequence socket(), bind(), listen(), accept() (possibly repeating the accept() to service more than one client), while a client only needs the sequence socket(), connect(). Also note that the server does not sendall()/recv() on the socket it is listening on but on the new socket returned by accept().
Client
Echo client program
import socket
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
the client is pretty stright forward, it create the socket s and then after using s.connect() it just send data through it.
Server
The server one is where there there are both s and conn
Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
conn.close()
in this one first of all we create a socket s on which the server will listen and then using s.accept() it will wait till a client connect to the server and then return the conn which is the socket of the connected client.
So to receive or send data to the client you have to use conn.
Notes
As said in the documentation in these two example the server accept only one client. So if you want to deal with multiple clients you have to repeat the accept step and possibly generate a new Thread for each client so that other clients don't have to wait for each others.

Errno 111: Connection refused only in python IDLE

When I try to execute Python server socket program and client socket program (both running in same linux machine) in Linux terminal I don't get any error, server accepts connection and sends data to client successfully.
But when I execute the same programs in python IDLE I get "[Errno 111] Connection refused" error.
What is the difference in both execution?
I'm using serversock.bind(('',port#)) in server
and in client i'm using clientsock.connect(('localhost',port#))
Server.py
import socket
serversock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = ''
print host
port = 5800
serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversock.bind((host,port))
serversock.listen(2)
try:
while True:
csock,addr = serversock.accept()
print 'Recieved address from %s '% str(addr)
csock.send('hello')
csock.close()
except Exception,e:
print e
client.py
import socket
try:
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = 'localhost'
port = 5800
c.connect((host,port))
data = c.recv(1024)
print data
except Exception,e:
print e
finally:
c.close()
Server side you must use:
serversock.bind(('',port#)) # binds to port
serversock.listen(5) # actually listen to port and allow 5 incoming calls
conv = serversock.accept() # accept first incoming call
The connection will only be accepted after the listen call, before it, you have only bound a socket, but have not declared that you were ready to accept incoming calls, so they are refused.
With added code, another possible error cause is that you close connection (server side) immediately after sending data. That is bad: the close condition can destroy the socket before the data has actually been sent.
You should use a graceful shutdown:
server side:
csock.send('hello')
csock.shutdown(socket.SHUT_WR) # shutdown the socket
csock.read() # wait the close from peer
csock.close()
client side: you can leave the code as is in your use case you do not send anything to server, so when the client has finished reading it can safely close the socket
Anyway you should close serversock when everything is finished
try:
...
except ...:
...
finally:
serversock.close()

Categories