zkssyth
zkssyth

Reputation: 31

Checking ip:port is open on remote host

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

Upvotes: 0

Views: 1102

Answers (2)

David Ferenczy Rogožan
David Ferenczy Rogožan

Reputation: 25441

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.

Upvotes: 1

zkssyth
zkssyth

Reputation: 31

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.

Upvotes: 3

Related Questions