The code below is meant to copy the features of netcat for instances where netcat is removed from a server but python is not. However, no matter what I try I can't seem to figure out the following problem:
I run the following
./Netcat.py -l -p 9999 -c
followed by
./Netcat.py -t localhost -p 9999
in a separate terminal. I can confirm that, when acting as a server the script does, indeed, receive a connection from the second instance of the script and that it receives data when it is set (upon pressing CTRL+D). However, I then get a hung terminal which does not receive a command prompt back, nor does it have the ability to send more data. I am hoping someone can point out the error at this point.
What should happen is as follows:
spin up server insatance
run script as a client
type some data and close STDIN with CTRL+D at which point the client sends the data to the server
The server should then receive the data and send back a command prompt to the client
The problem is at step 4 and I'm pulling my hair out at this point.
Edit
Having run strace I determined that the client program gets hung up waiting to receive data which I have noted the corresponding line in the code. I do not see why this would be the case.
import sys # used for accessing command line args
import socket # creation of socket objects to listen & send/receive data
import getopt # helps scripts to parse the command line arguments in sys.argv
import concurrent.futures # for running commands in a subshell
import subprocess # The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes.
## Globals ##
listen = False
command = False
target = ""
port = 0
## END GLOBALS ##
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((target, port))
if len(buffer):
# bytes([source[, encoding[, errors]]])
client.send(bytes(buffer, 'utf-8'))
# continue sending and receiving data until user kills script
while True:
recv_len = 1
response = ''
while recv_len:
data = client.recv(4096) #<-- PROBLEM
recv_len = len(data)
response += data.decode('utf-8')
if recv_len < 4096:
break
print(response)
buffer = input('#: ')
buffer += '\n'
client.send(buffer)
except socket.error as e:
print('[*] Exception! Exiting')
print(e)
client.close()
def server_loop():
global target
global port
# if no target is defined, listen on all interfaces
if not len(target):
target = '0.0.0.0'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))
server.listen(5)
print(f'listening on {target}:{port}')
while True:
client_socket, addr = server.accept()
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
executor.submit(client_handler, client_socket)
def run_command(command):
command = command.rstrip()
# run command & retrieve output
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
return 'Failed to execute command.\r\n'
def client_handler(client_socket):
global command
# check if shell requested
if command:
while True:
client_socket.send('<BHP:#> ')
# receive until linefeed
cmd_buffer = ''
while '\n' not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
response = run_command(bufffer)
client_socket.send(response)
def main():
global listen
global port
global command
global target
# make sure the user provided options & arguments
if not len(sys.argv[1:]):
usage()
# parse commandline options
try:
opts, args = getopt.getopt(sys.argv[1:],"lt:p:c", #: succeeds options which expect an argument
['listen', 'target', 'port', 'command'])
except getopt.GetoptError as err:
print(str(err))
usage()
# handle commandline options
for option, argument in opts:
elif option in ('-l', '--listen'):
listen = True
elif option in ('-e', '--execute'):
execute = argument
elif option in ('-c', '--commandshell'):
command = True
elif option in ('-t', '--target'):
target = argument
elif option in ('-p', '--port'):
port = int(argument)
# not listening; sending data from stdin
if not listen and len(target) and port > 0:
buffer = sys.stdin.read()
client_sender(buffer)
if listen:
server_loop()
if __name__ == '__main__':
main()
Related
can anybody make something like this for pythons script, nothing big very small programme , source code which is free.
kindly read throught and check what it does. i will paste the text from the github below.
https://github.com/dechamps/WinIPBroadcast
WinIPBroadcast is a small program that allows Windows applications to send global IP broadcast packets (destination address 255.255.255.255) to all interfaces instead of just the preferred one.
This application is most useful for users of server browsers or other network monitoring software. Specifically, those playing multiplayer games locally on multiple interfaces (for example, a LAN network and a Hamachi VPN) will be able to see games from all networks at once.
ok and now here is a python script i found on stackoverflow post.
this sends broadcast but not relaying or something maybe you can help tweak this
import socket
from time import sleep
def main():
interfaces = socket.getaddrinfo(host=socket.gethostname(), port=None, family=socket.AF_INET)
allips = [ip[-1][0] for ip in interfaces]
msg = b'hello world'
while True:
for ip in allips:
print(f'sending on {ip}')
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind((ip,0))
sock.sendto(msg, ("255.255.255.255", 3074))
sock.close()
sleep(2)
main()
i found this
import socket
import threading
import sys
import getopt
import os
from relay import udp
from relay import tcp
from relay import status
relayport = 0
remoteport = 0
remoteaddress = ""
protocol = "UDP"
help = "Invalid arguments, usage:\nboxy.py -i <input port> -p <remote port> -a <remote address> [-t]"
def quit():
print "Quitting..."
if (protocol == "UDP"):
udp.stop()
else:
tcp.stop()
os._exit(0)
#process args
try:
options, args = getopt.getopt(sys.argv[1:], "i:p:a:t")
except getopt.GetoptError:
print help
sys.exit(2)
try:
for option, arg in options:
if (option == "-i"):
relayport = int(arg)
elif (option == "-p"):
remoteport = int(arg)
elif (option == "-a"):
remoteaddress = arg
elif (option == "-t"):
protocol = "TCP"
except ValueError:
print help
sys.exit(2)
if ((0 < relayport <= 65535 and 0 < remoteport <= 65535 and remoteaddress != "") == False):
print help
sys.exit(2)
print "Relay starting on port {0}, relaying {1} to {2}:{3}".format(relayport, protocol, remoteaddress, remoteport)
if (protocol == "UDP"):
udp.start(relayport, remoteaddress, remoteport)
else:
tcp.start(relayport, remoteaddress, remoteport)
status.start(relayport, remoteaddress, remoteport)
try:
while raw_input() != "quit":
continue
quit()
except KeyboardInterrupt:
quit()
except EOFError:
#this exception is raised when ctrl-c is used to close the application on Windows, appears to be thrown twice?
try:
quit()
except KeyboardInterrupt:
os._exit(0)
how do i fix it ? gives error missing perenthisis.
boxy.py -i 3074 -a 192.168.0.0.1 -p 3074 -t`
https://github.com/OliverF/boxy
how do i send it to all adapters
I know that I can see inside of network traffic for example with WireShark. When i use GET on HTML I can see those stuff in URL, what should not be problem what I am doing. But I believe GET,POST and maybe REQUEST too, as I did not work with that one yet can bee seen on something like Wire Shark network analyzer.
I am making Python client, what i will put on computers in network to show their IP,Host Name and Users on PC. This client will be as gate to the computer for remote control. As our management does not want to spend money for windows server, or other management system we need to get something free to manage all computers.
I am also seeking advice how I could do it as you are more skilled then me here.
I found few ways.
With the client create SSH Gateway for receiving commands.
With Client enable the Powershell remote option, then just push scripts to all computers at once.
Use some way the API requests etc... I am not skilled in this one at all, but I believe this is the way how other similar programs works?
As this client would create big security risk, I am first seeking way what is best way to hide it from network. Probably I will need to come up with some Private and public Key system here as well.
What are yours suggestions please on this topic?
here is just very short code I am playing with to receive basic info as IP, Host name and all Users
the Flask website showing those values is just for test, It will not be there once it is deployed
Update
I took advice from MarulForFlask but I got a couple issues. First this i think can have only one connection at a time. And second if possible Can i get the output of console from the client PC on screen of Server PC?
I want this output only for testing, as I know if i do something like netstat or any other command with multiple clients it would filled up screen with too many text... Currently I am getting back text format as plaintext with \r \n ... and other text deviders.
I am now trying Multicast, but i am getting error for binding the multicast IP.
OSError: [WinError 10049] The requested address is not valid in its context
Master.py
import time
import socket
import sys
import os
valueExit = True
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = socket.gethostname()
BUFFER_SIZE = 1024
# Initialize the port
port = 8080
# Bind the socket with port and host
s.bind(('', port))
print("waiting for connections...")
# listening for conections
s.listen()
# accepting the incoming connections
conn, addr = s.accept()
print(addr, "is connected to server")
def send_query():
keepAllive, repeatIt = True, False
print("""To exit session write: EndSession
For help write: help
""")
while (keepAllive == True):
# commands for server use only
innerCommands = ["endsession", "help"]
# take command as input
command = input(str("Enter Command : "))
if command not in innerCommands:
conn.send(command.encode())
print("Command has been sent successfully.")
keepAllive = False
repeatIt = True
elif (command == "endsession"):
conn.send(command.encode())
valueExit = False
elif (command == "help"):
print("""To exit session write: EndSession""")
while (repeatIt == True):
# recieve the confrmation
data = conn.recv(BUFFER_SIZE)
if data:
print(f"command recieved and executed sucessfully.\n {data}")
keepAllive = True
repeatIt = False
else:
print("No reply from computer")
keepAllive = True
repeatIt = False
while valueExit == True:
send_query()
Slave.py
import time
import socket
import sys
import subprocess
import os
stayOn = True
def establishConnection():
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = "127.0.0.1"
# Initiaze the port
port = 8080
keepAlive = True
try:
# bind the socket with port and host
s.connect((host, port))
print("Connected to Server.")
while keepAlive == True:
# recieve the command from master program
command = s.recv(1024)
command = command.decode()
# match the command and execute it on slave system
if command == "endsession":
print("Program Ended")
keepAlive = False
elif command != "":
# print("Command is :", command)
#s.send("Command recieved".encode())
proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
s.send(f"{out}".encode())
print("program output:", out)
except Exception as err:
print(f"Error: {err}")
s.send(f"Error: {err}".encode())
while stayOn == True:
establishConnection()
see:
https://www.pythonforthelab.com/blog/how-to-control-a-device-through-the-network/
There uses a flask webserver.
otherwise, create a master.py file and paste this code:
import time
import socket
import sys
import os
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = socket.gethostname()
# Initialize the port
port = 8080
# Bind the socket with port and host
s.bind(('', port))
print("waiting for connections...")
# listening for conections
s.listen()
# accepting the incoming connections
conn, addr = s.accept()
print(addr, "is connected to server")
# take command as input
command = input(str("Enter Command :"))
conn.send(command.encode())
print("Command has been sent successfully.")
# recieve the confrmation
data = conn.recv(1024)
if data:
print("command recieved and executed sucessfully.")
open a slave.py and paste this code:
import time
import socket
import sys
import os
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = "127.0.0.1"
# Initiaze the port
port = 8080
# bind the socket with port and host
s.connect((host, port))
print("Connected to Server.")
# recieve the command from master program
command = s.recv(1024)
command = command.decode()
# match the command and execute it on slave system
if command == "open":
print("Command is :", command)
s.send("Command recieved".encode())
# you can give batch file as input here
os.system('ls')
open slave.py in client, master.py in server
https://www.geeksforgeeks.org/how-to-control-pc-from-anywhere-using-python/
i'm trying to do client-server project. In this project i have to send linux command from client to server. Now i can send some commands like a ls, pwd etc. and they are running correctly and i can read output in client terminal but when i try to send "cd" command, i don't get any error but the directory in server doesn't change. If i use os.chdir(os.path.abspath(data)) command instead of subprocess.check_output , it can change directory but it is useless because i can send a other commands like a ls, pwd , mkdir etc. Thanks for your help
server side:
def threaded(c):
while True:
# data received from client
data = c.recv(1024)
if not data:
print('Bye')
break
try:
data_o = subprocess.check_output(data, shell=True)
except subprocess.CalledProcessError as e:
c.send(b'failed\n')
print(e.output)
if(len(data_o) > 0):
c.send(data_o)
else:
c.send(b'There is no terminal output.')
# connection closed
c.close()
client side:
while True:
# message sent to server
s.send(message.encode('ascii'))
# messaga received from server
data = s.recv(1024)
# print the received message
print('Received from the server :',str(data.decode('ascii')))
# ask the client whether he wants to continue
ans = input('\nDo you want to continue(y/n) :')
if ans == 'y':
message = input("enter message")
continue
else:
break
# close the connection
s.close()
You could check if the command being sent is equal to cd and change the runtime behavior based on that.
data_spl = data.split()
if data_spl[0] == 'cd':
data_o = os.chdir(os.path.abspath(data_spl[1]))
else:
data_o = subprocess.check_output(data, shell=True)
i have read other Stackoverflow threads on this. Those are older posts, i would like to get the latest update.
Is it possible to send multiple commands over single channel in Paramiko ? or is it still not possible ?
If so, is there any other library which can do the same.
Example scenario, automating the Cisco router confi. : User need to first enter "Config t" before entering the other other commands. Its currently not possible in paramiko.
THanks.
if you are planning to use the exec_command() method provided within the paramiko API , you would be limited to send only a single command at a time , as soon as the command has been executed the channel is closed.
The below excerpt from Paramiko API docs .
exec_command(self, command) source code Execute a command on the
server. If the server allows it, the channel will then be directly
connected to the stdin, stdout, and stderr of the command being
executed.
When the command finishes executing, the channel will be closed and
can't be reused. You must open a new channel if you wish to execute
another command.
but since transport is also a form of socket , you can send commands without using the exec_command() method, using barebone socket programming.
Incase you have a defined set of commands then both pexpect and exscript can be used , where you read a set of commands form a file and send them across the channel.
See my answer here or this page
import threading, paramiko
strdata=''
fulldata=''
class ssh:
shell = None
client = None
transport = None
def __init__(self, address, username, password):
print("Connecting to server on ip", str(address) + ".")
self.client = paramiko.client.SSHClient()
self.client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
self.client.connect(address, username=username, password=password, look_for_keys=False)
self.transport = paramiko.Transport((address, 22))
self.transport.connect(username=username, password=password)
thread = threading.Thread(target=self.process)
thread.daemon = True
thread.start()
def closeConnection(self):
if(self.client != None):
self.client.close()
self.transport.close()
def openShell(self):
self.shell = self.client.invoke_shell()
def sendShell(self, command):
if(self.shell):
self.shell.send(command + "\n")
else:
print("Shell not opened.")
def process(self):
global strdata, fulldata
while True:
# Print data when available
if self.shell is not None and self.shell.recv_ready():
alldata = self.shell.recv(1024)
while self.shell.recv_ready():
alldata += self.shell.recv(1024)
strdata = strdata + str(alldata)
fulldata = fulldata + str(alldata)
strdata = self.print_lines(strdata) # print all received data except last line
def print_lines(self, data):
last_line = data
if '\n' in data:
lines = data.splitlines()
for i in range(0, len(lines)-1):
print(lines[i])
last_line = lines[len(lines) - 1]
if data.endswith('\n'):
print(last_line)
last_line = ''
return last_line
sshUsername = "SSH USERNAME"
sshPassword = "SSH PASSWORD"
sshServer = "SSH SERVER ADDRESS"
connection = ssh(sshServer, sshUsername, sshPassword)
connection.openShell()
connection.send_shell('cmd1')
connection.send_shell('cmd2')
connection.send_shell('cmd3')
time.sleep(10)
print(strdata) # print the last line of received data
print('==========================')
print(fulldata) # This contains the complete data received.
print('==========================')
connection.close_connection()
Have a look at parallel-ssh:
from pssh.pssh2_client import ParallelSSHClient
cmds = ['my cmd1', 'my cmd2']
hosts = ['myhost']
client = ParallelSSHClient(hosts)
for cmd in cmds:
output = client.run_command(cmd)
# Wait for completion
client.join(output)
Single client, multiple commands over same SSH session and optionally multiple hosts in parallel - also non-blocking.
I find this simple to understand and use. Code provides 2 examples with singlehost and multihost. Also added example where you can login to a second user and continue your commands with that user.
More info can be found in here: https://parallel-ssh.readthedocs.io/en/latest/advanced.html?highlight=channel#interactive-shells
from pssh.clients import SSHClient
from pssh.exceptions import Timeout
from pssh.clients import ParallelSSHClient
from pssh.config import HostConfig
def singleHost():
host_ = "10.3.0.10"
pwd_ = "<pwd>"
pwd_root = "<root pwd>"
user_ = "<user>"
client = SSHClient(host_, user=user_, password=pwd_, timeout=4, num_retries=1)
#####
shell = client.open_shell(read_timeout=2)
shell.run("whoami")
# login as new user example
shell.run("su - root")
shell.stdin.write(pwd_root + "\n")
shell.stdin.flush()
shell.run("pwd")
try:
# Reading Partial Shell Output, with 'timeout' > client.open_shell(read_timeout=2)
for line in shell.stdout:
print(line)
except Timeout:
pass
shell.run("whoami")
shell.run("cd ..")
print(".......")
try:
# Reading Partial Shell Output, with 'timeout' > client.open_shell(read_timeout=2)
for line in shell.stdout:
print(line)
except Timeout:
pass
shell.close()
def multiHost():
pwd_ = "<pwd>"
user_ = "<user>"
workingIP_list = ["10.3.0.10", "10.3.0.10"]
host_config_ = []
# HostConfig is needed one per each 'workingIP_list'
host_config_.append(HostConfig(user=user_, password=pwd_))
host_config_.append(HostConfig(user=user_, password=pwd_))
client_ = ParallelSSHClient(workingIP_list, host_config=host_config_, num_retries=1, timeout=3)
# now you have an open shell
shells = client_.open_shell(read_timeout=2)
command = "pwd"
client_.run_shell_commands(shells, command)
try:
# Reading Partial Shell Output, with 'timeout' > client_.open_shell(read_timeout=2)
for line in shells[0].stdout:
print(line)
except Timeout:
pass
print(".......")
command = "cd repo/"
client_.run_shell_commands(shells, command)
command = "pwd"
client_.run_shell_commands(shells, command)
#Joined on shells are closed and may not run any further commands.
client_.join_shells(shells)
for shell in shells:
for line in shell.stdout:
print(line)
print(shell.exit_code)
if __name__ == '__main__':
print("singleHost example:")
singleHost()
print("multiHost example:")
multiHost()
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(5)
input = [server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input.remove(s)
server.close()
Whenever I run this code, I get this error message for my argument for the while loop:
inputready,outputready,exceptready = select.select(input,[],[])
TypeError: argument must be an int, or have a fileno() method.
How can I fix this to make the server run properly? Sorry if this is a bad question, I'm new to python and I can't figure this out. Thanks.
Yeah found the solution to your problem their seem to be sys.stdin , the python IDLE GUI for some reason doesn't allow you to use sys.stdin.fileno() in your code, while if you run it in the command prompt or the terminal it will work fine on linux. Link
An if your using windows, you cant pass the sys.stdin as an argument to the select() function, as in windows it accepts only sockets as arguments. As Explained in the documentation Documentation
Note: File objects on Windows are not acceptable, but sockets are. On Windows, the underlying select() function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.
So to mitigate the problem , such that it works on both windows and linux:
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input1 = [server]
running = 1
while running:
inputready,outputready,exceptready = select.select(input1,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input1.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input1.remove(s)
server.close()