I have a list of servers and ip:ports (external addressses) and i need to check if each server can connect to those addresses.
Looping through the file and trying to open an sshtunnel and doing connect as below
tunnel=sshtunnel.SSHTunnelForwarder(
ssh_host=host,
ssh_port=22,
ssh_username=ssh_username,
ssh_pkey=privkey,
remote_bind_address=(addr_ip, int(addr_port)),
local_bind_address=('0.0.0.0', 10022)
#,logger=sshtunnel.create_logger(loglevel=10)
)
tunnel.start()
# use socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
res = s.connect(('localhost', 10022))
print(res)
#s.connect((addr_ip, int(addr_port)))
s.close()
except socket.error as err:
print('socket err:')
print(err)
finally:
s.close()
time.sleep(2)
tunnel.stop()
When i do this though, the response is always 0 (i.e. the sock can connect to the local bind) even if the remote is incorrect - however sshtunnelforwarder throws
ERROR | Secsh channel 0 open FAILED: Network is unreachable: Connect failed
ERROR | Could not establish connection from ('127.0.0.1', 10022) to remote side of the tunnel
How do I make my socket command check if the remote_bind_address is available?
I tried to do use telnetlib, but get a similar issue
the code is effectively the same with the socket block replaced with
tn=telnetlib.Telnet()
tn.open('localhost',10022)
tn.close()
Im relatively new to all this, so still learning. If there is a better way to achieve what i need to do please let me know.
Thanks
Set the attribute skip_tunnel_checkup to False to enable checking of the remote side availability (it's disabled by default for backwards compatibility):
tunnel.skip_tunnel_checkup = False
Adding this before starting the tunnel checks the remote side is up on start and throws an exception which can be handled.
Removed my socket code.
I haven't tried that, but there's the tunnel_is_up attribute of the SSH tunnel class, which according to the documentation:
Describe whether or not the other side of the tunnel was reported to be up (and we must close it) or not (skip shutting down that tunnel)
Example of its content (it's a dictionary):
{('127.0.0.1', 55550): True, # this tunnel is up
('127.0.0.1', 55551): False} # this one isn't
So you shouldn't need to make an explicit connection yourself.
Note: you may need to set the attribute skip_tunnel_checkup to False (which is True by default for backwards compatibility) first before setting up the tunnel, otherwise tunnel_is_up may always report True:
When skip_tunnel_checkup is disabled or the local bind is a UNIX socket, the value will always be True
So the code may look like:
tunnel=sshtunnel.SSHTunnelForwarder(
# ...
)
tunnel.skip_tunnel_checkup = False
tunnel.start()
# tunnel.tunnel_is_up should be populated with actual tunnel status(es) now
In the code you posted, you're setting up a tunnel and then just opening a socket to the local endpoint of the tunnel, which is apparently open no matter what state the tunnel is in, so it always connects successfully.
Another approach would be to actually try to establish an SSH connection through the tunnel, but that's the paramiko.SSHclient alternative you're mentioning in a comment I guess.
Related
I have this program which is for now supposed to only listen on port 80 and receive data either from browser connections or from another python scripts.
this code:
import socket # Import socket module
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname() # Get local machine name
port = 80 # Reserve a port for your service.
s.bind(("192.168.252.7", port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
print c.recv(1024)
c.close() # Close the connection
which is all copied from tutorialspoint. This code receives data, when the port is set to anything but 80 (eg 8080, 12345), but when it is 80, it only accepts the client but seems to not receive any data despite the data being successfully sent from somewhere else....
PLEASE HELP GUYS
Port 80 and all ports <1024 are privileged ports, your program must run as root in order to properly bind to these ports. I'm guessing you are running on Windows, since on any unix calling s.bind(("127.0.0.1", 80)) results in PermissionError: [Errno 13] Permission denied exception immediately.
I'm not sure how Windows deals with priveleged ports, but quick google search points towards windows firewall messing with your program.
Proper web servers, such as Nginx or Apache, start as root, bind to the port 80 and immediately drop to a less privileged user, since running under root is dangerous.
P.S.: A couple of suggestions:
You can skip the socket.gethostname(). Use ip 127.0.0.1 if you want your program to be accessible only from your machine, or use ip 0.0.0.0 if you want to be accessible from any machine on your network.
You should try to switch to Python 3 ASAP, since Python 2 is basically dead at this point. Don't get used to two's syntax, you gonna relearn it in a couple of years tops.
I have a python code that brings up an SSH connection to remote server to further forward telnet traffic to several routers hidden behind this server, in order to remote manage those. The code is the following:
def sshStart(self):
try:
self.sshServer = SSHTunnelForwarder(
(SRVR_IP, SRVR_PORT),
ssh_username = SRVR_USER[0],
ssh_password = SRVR_USER[1],
remote_bind_address = (self.systemIP, 23),
local_bind_address = ("127.0.0.1", self.localPort)
)
self.sshServer.start()
except:
fncPrintConsole(self.strConn + "Error SSH Tunnel")
self.quit()
def routerLogin(self):
try:
self.tn = telnetlib.Telnet("127.0.0.1",self.localPort)
except:
fncPrintConsole(self.strConn + "No route to host!")
self.quit()
This is working very nice. Indeed, I can easily manage several routers with this code, provided that there is networking towards the far-end router.
The problem arises when the remote router (in other words, the combination of 127.0.0.1:self.localPort -> self.systemIP, 23) is not reachable because of something (timeout, no routing available, etc ... ).
In such a case, I get the following error:
2017-07-24 10:38:57,409| ERROR | Could not establish connection from ('127.0.0.1', 50000) to remote side of the tunnel
2017-07-24 10:38:57,448| ERROR | Secsh channel 0 open FAILED: Network is unreachable: Connect failed
Even though the error is correct (there actually is no reachability to the remote router) I cannot catch that error: the python program gets stuck there for ever and I cannot exit it properly (i.e.: if error -> quit() )
Do you have any clue on how to accomplish this?
Thanks!
Lucas
So, the issue of catching the exception was solved at a later stage within the code.
After triggering the telnet connection ...
def routerLogin(self):
try:
self.tn = telnetlib.Telnet("127.0.0.1",self.localPort)
except:
fncPrintConsole(self.strConn + "No route to host!")
self.quit()
... I do expect some string before going on.
i = self.tn.expect(PROMPT_LOGIN, TIME_LOGIN)
For some reason I thought that including try | except when creating the tn connection was enough. But no, I kept on receiving the SSH error mentioned.
Wrapping the tn.expect with try|except did the trick. So now I have...
try:
i = self.tn.expect(PROMPT_LOGIN, TIME_LOGIN)
except:
quit()
... and in the case of reachability problems I can catch it up there.
Don't know if this is the more elegant / right way of doing it but at least is working ...
Thanks!
Lucas
I am writing TLS server in Python. I accept a connection from a client, wrap the socket and then try to read data - without success.
My server inherits from socketserver.TCPServer. My socket is non-blocking - I overwrote server_bind() method. Socket is wrapped, but handshake has to be done separately, because of the exception which is raised otherwise:
def get_request(self):
cli_sock, cli_addr = self.socket.accept()
ssl_sock = ssl.wrap_socket(cli_sock,
server_side=True,
certfile='/path/to/server.crt',
keyfile='/path/to/server.key',
ssl_version=ssl.PROTOCOL_TLSv1,
do_handshake_on_connect=False)
try:
ssl_sock.do_handshake()
except ssl.SSLError as e:
if e.args[1].find("SSLV3_ALERT_CERTIFICATE_UNKNOWN") == -1:
raise
return ssl_sock, cli_addr
To handle received data, I created a class which inherits from socketserver.StreamRequestHandler (I tried also with BaseRequestHandler, but with no luck, ended with the same problem - no data received).
When I print self.connection in handle() method, I can see that it is of type SSLSocket, fd is set (to some positive value), both local and remote IP and port have values as expected, so I assume that a client is successfully connected to my server and the connection is opened. However when I try to read data
self.connection.read(1)
There should be more bytes received, I tried with 1, 10, 1024, but it does not make any difference, the read() method always returns nothing. I tried to check len or print it, but there is nothing to be printed.
I was monitoring packages using Wireshark. And I can see that the data I am expecting to read, comes to my server (I checked that IP and port are the same for self.connection and in Wireshark), which sends ACK and then receives FIN+ACK from the client. So it looks like the data comes and are handled properly on a low level, but somehow read() method is not able to access it.
If I remove wrap_socket() call, then I am able to read data, but that is some data which client is sending for authentication.
I am using Python 3.4 on Mac machine.
How is that possible that I can in Wireshark that packets are coming, but I am not able to read the data in my code?
I'm working on a script that grabs the banner from common ports of a host. I'm using sockets to make the connection but I'm facing some issues. Here is the code:
try:
connsocket = socket(AF_INET, SOCK_STREAM)
connsocket.settimeout( 5 )
connsocket.connect((ip, port))
connsocket.send("HEAD / HTTP/1.0")
results = connsocket.recv(400)
connsocket.close()
return str(results)
except:
print '[ERROR]Failed to connect or Connection timed out'
The are two major issues:
First time I run the script to a host all the banners are retrieved correctly except port 80 which exits with the timeout
The second problem is that when I relaunch the script to the same host there is no response from any port.
I suspect that the second issue is due to the connection is still open and the script fails retying to connect. With the first issue I have no idea why it's not working.
Any idea?
Regards.
Below is the code I am running within a service. For the most part the script runs fine for days/weeks until the script hiccups and crashes. I am not so worried about the crashing part as I can resolve the cause from the error logs an patch appropriately. The issue I am facing is that sometimes when the service restarts and tries to connect to the server again, it gets a (10061, 'Connection refused') error, so that the service is unable to start up again. The bizarre part is that there is no python processes running when connections are being refused. IE no process with image name "pythonw.exe" or "pythonservice.exe." It should be noted that I am unable to connect to the server with any other machine as well until I reset computer which runs the client script. The client machine is running python 2.7 on a windows server 2003 OS. It should also be noted that the server is coded on a piece of hardware of which I do not have access to the code.
try:
EthernetConfig = ConfigParser()
EthernetConfig.read('Ethernet.conf')
HOST = EthernetConfig.get("TCP_SERVER", "HOST").strip()
PORT = EthernetConfig.getint("TCP_SERVER", "PORT")
lp = LineParser()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
reader = s.makefile("rb")
while(self.run == True):
line = reader.readline()
if line:
line = line.strip()
lp.parse(line)
except:
servicemanager.LogErrorMsg(traceback.format_exc()) # if error print it to event log
s.shutdown(2)
s.close()
os._exit(-1)
Connection refused is an error meaning that the program on the other side of the connection is not accepting your connection attempt. Most probably it hasn't noticed you crashing, and hasn't closed its connection.
What you can do is simply sleep a little while (30-60 seconds) and try again, and do this in a loop and hope the other end notices that the connection in broken so it can accept new connections again.
Turns out that Network Admin had the port closed that I was trying to connect to. It is open for one IP which belongs to the server. Problem is that the server has two network cards with two separate IP's. Issue is now resolved.