Connect to SSH server through SOCKS5 proxy - python

how to connect via ssh using shared key with socks in python?
I have tested several ways, any suggestions?
Thank you very much in advance ...
Imports:
import paramiko
from paramiko import RSAKey
import socket
import socks
import base64
Script:
def createSSHClient(server, port, user):
sock=socks.socksocket()
sock.set_proxy(
proxy_type=socks.SOCKS5,
addr='10.0.0.2',
port=1080,
username=base64.b64decode('dXNlcg==').decode("utf-8"),
password=base64.b64decode('cGFzc3dvcmQ=').decode("utf-8")
)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
privkey = paramiko.RSAKey.from_private_key_file('/home/my-user/.ssh/id_rsa')
ssh.connect(server, port, user, privkey, sock)
return ssh
outputsocks = []
ssh = createSSHClient('192.168.1.23', 22, 'my-user')
outputsocks.append((ssh.exec_command('ls -ltr')[1]).read().decode('ascii'))
ssh.close()
print(outputsocks)
Output:
Traceback (most recent call last):
File "/home/my-user/teste2.py", line 26, in <module>
ssh = createSSHClient('192.168.1.23', 22, 'my-user')
File "/home/my-user/teste2.py", line 22, in createSSHClient
ssh.connect(server, port, user, privkey, sock)
File "/usr/local/lib/python3.6/site-packages/paramiko/client.py", line 349, in connect
retry_on_signal(lambda: sock.connect(addr))
File "/usr/local/lib/python3.6/site-packages/paramiko/util.py", line 283, in retry_on_signal
return function()
File "/usr/local/lib/python3.6/site-packages/paramiko/client.py", line 349, in <lambda>
retry_on_signal(lambda: sock.connect(addr))
TimeoutError: [Errno 110] Connection timed out
Note: The same script works if you remove the connection via socks and use a host that does not need a VPN, the socks credentials are correct and the shared key works.

The error was in not opening the connection via sock before starting SSH, this was resolved with sock.connect()
More info: socket connect() vs bind()
Bug fix:
def createSSHClient(server, port, user):
sock=socks.socksocket()
sock.set_proxy(
proxy_type=socks.SOCKS5,
addr='10.0.0.2',
port=1080,
username=base64.b64decode('dXNlcg==').decode("utf-8"),
password=base64.b64decode('cGFzc3dvcmQ=').decode("utf-8")
)
sock.connect(('192.168.1.20',22))
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
privkey = paramiko.RSAKey.from_private_key_file('/home/my-user/.ssh/id_rsa')
ssh.connect(server, port, user, privkey, sock)
return ssh
outputsocks = []
ssh = createSSHClient('192.168.1.23', 22, 'my-user')
outputsocks.append((ssh.exec_command('ls -ltr')[1]).read().decode('ascii'))
ssh.close()
sock.close()
print(outputsocks)

Related

Python Socket SSL OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (wh

Full error code:
Traceback (most recent call last):
File "C:\path\to\my\python\code\server_ssl_testing.py", line 15, in <module>
response = ssock.recv(1024).decode("utf-8")
File "C:\Program Files\Python39\lib\ssl.py", line 1228, in recv
return super().recv(buflen, flags)
OSError: [WinError 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
I created SSL Socket server and client, but then server try to receive info from client it falied and print error that is above this text.
Server:
import socket
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain('certs/server-cert.pem', 'certs/server.key')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
sock.bind(('localhost', 2642))
sock.listen(5)
with context.wrap_socket(sock, server_side=True) as ssock:
conn, addr = ssock.accept()
response = ssock.recv(1024).decode("utf-8")
print(response)
Client:
import socket
import ssl
hostname = 'localhost'
context = ssl.create_default_context()
sock = socket.create_connection((hostname, 2642))
ssock = context.wrap_socket(sock, server_hostname=hostname)
msg = "Hello World!"
ssock.send(msg.encode("utf-8"))
In server.py I should write conn.recv instead of ssock.recv.
Should help if anyone will want do it in future =)

How to use python's sshtunnel to connect to a router running only telnet?

I have to connect to a jumpserver to connect to a bunch of routers running only telnet. I'm new to SSH tunneling, but I've figured out that on the command line on my local machine, the following command forms the necessary tunnel:
$ ssh -fNL 2300:remote_host:23 user#jumpServer
Then all I have to do is connect to port 2300 on the local machine for the traffic to be forwarded to port 23 on the router (which doesn't have SSH and only has telnet):
> telnet localhost 2300
I have a few questions:
Where does the actual tunnel form? As I said, the router has port 22 blocked, i.e., it isn't capable of running SSH. However, my local machine and the gateway/jumpserver can. So, if the tunnel's forming between my local machine and the jump server, what is the mode of transport between the jumpserver and the router?
If I understand this right, there's a listener on my local machine on port 2300, that forwards all traffic to some port on the jump server via the SSH tunnel, that then forwards it to the router. Right?
[Python Specific question] How do I get the sshtunnel module to do this programmatically? I tried the following:
from sshtunnel import open_tunnel
from telnetlib import Telnet
js = '123.456.555.666'
js_usr = "user"
rem_host = '123.456.789.101'
with open_tunnel(
ssh_address_or_host=(js, 22),
ssh_username=js_usr,
ssh_password="password",
remote_bind_address=(rem_host, 23)
) as tunnel:
with Telnet(js, tunnel.local_bind_port, 10) as tn:
tn.interact()
However, this throws the following error:
Traceback (most recent call last):
File "C:/Users/somsinha/PycharmProjects/SysTEst/sshTunnelTest.py", line 14, in
with Telnet(js, tunnel.local_bind_port, 10) as tn:
File "C:\Users\somsinha\bin\WPy64-3741\python-3.7.4.amd64\lib\telnetlib.py", line 218, in init
self.open(host, port, timeout)
File "C:\Users\somsinha\bin\WPy64-3741\python-3.7.4.amd64\lib\telnetlib.py", line 234, in open
self.sock = socket.create_connection((host, port), timeout)
File "C:\Users\somsinha\bin\WPy64-3741\python-3.7.4.amd64\lib\socket.py", line 727, in create_connection
raise err
File "C:\Users\somsinha\bin\WPy64-3741\python-3.7.4.amd64\lib\socket.py", line 716, in create_connection
sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
How to I make python ssh -fNL 2300:remote_host:23 user#jumpServer manually?
Everything is right with your code except use should use "localhost" with telnet:
from sshtunnel import open_tunnel
from telnetlib import Telnet
js = '123.456.555.666'
js_usr = "user"
rem_host = '123.456.789.101'
with open_tunnel(
ssh_address_or_host=(js, 22),
ssh_username=js_usr,
ssh_password="password",
remote_bind_address=(rem_host, 23)
) as tunnel:
# Use localhost as host
with Telnet('localhost', tunnel.local_bind_port, 10) as tn:
tn.interact()
The reason is the port is forwarded to the localhost and it must be accessed from it.

Python script to Connect to remote mongoDB using ssh-tunnel and pymongo client is failing with errors

I am trying to connect to remote mongodb, here the ssh access has a different username and password, And the mongodb has a different username and password.
I tried passing the username and password of ssh in ssh tunnel server, and the mongodb credentials in the client, but getting an error stating:
pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017: [Errno 111] Connection refused
Here the ssh connection is happening, whereas the mongodb is not getting connected
def Collect_Pid_DB():
MONGO_DB = "mydatabasename"
server = SSHTunnelForwarder(
(MONGO_HOST,22),
ssh_username=username,
ssh_password=password,
remote_bind_address=('127.0.0.1', 27017)
)
server.start()
#print (server)
uri = "mongodb://admin:" + urllib.quote("p#ssW0$3") + "#127.0.0.1:27017"
client = pymongo.MongoClient(uri,server.local_bind_port)
db = client[MONGO_DB]
print (db)
print(json.dumps(db.collection_names(), indent=2))
server.stop()
Actual results:
Database(MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True), u'MissingPatches')
Traceback (most recent call last):
File "duplicate.py", line 7, in <module>
class MyClass:
File "duplicate.py", line 41, in MyClass
Collect_Pid_DB('192.142.123.142','root','password','mydatabasename')
File "duplicate.py", line 35, in Collect_Pid_DB
print(json.dumps(db.collection_names(), indent=2))
File "/usr/local/lib/python2.7/dist-packages/pymongo/database.py", line 787, in collection_names
nameOnly=True, **kws)]
File "/usr/local/lib/python2.7/dist-packages/pymongo/database.py", line 722, in list_collections
read_pref) as (sock_info, slave_okay):
File "/usr/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/usr/local/lib/python2.7/dist-packages/pymongo/mongo_client.py", line 1135, in _socket_for_reads
server = topology.select_server(read_preference)
File "/usr/local/lib/python2.7/dist-packages/pymongo/topology.py", line 226, in select_server
address))
File "/usr/local/lib/python2.7/dist-packages/pymongo/topology.py", line 184, in select_servers
selector, server_timeout, address)
File "/usr/local/lib/python2.7/dist-packages/pymongo/topology.py", line 200, in _select_servers_loop
self._error_message(selector))
pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017: [Errno 111] Connection refused
The following is the working code for the above question, In the above code the issue was that the local bind port along with the url was not parsed into a proper format, hence when authenticating the port couldnt be authenticated in order to connect.
Hence in the above code mentioned in the question was not working.
The working code to connect to mongodb, when the ssh and mongo both have different credentials:
def Collect_Pid_DB(hostname,user,password,accountid):
server = SSHTunnelForwarder(
(MONGO_HOST,22),
ssh_username=MONGO_USER,
ssh_password=MONGO_PASS,
remote_bind_address=('127.0.0.1', 27017)
)
host_name="'primary_host_name': 'win-3auvcutkp34'"
patch_name="'patch_name': '[\\& A-Za-z0-9+.,\\-]+'"
server.start()
client = pymongo.MongoClient(host='127.0.0.1',
port=server.local_bind_port,
username='admin',
password='P#ssW0Rd')
db = client[MONGO_DB]
print (db)
print(json.dumps(db.collection_names(), indent=2))
Hope the above answer would be helpful to someone, as i couldn't find one anywhere when i needed :P
Try to pip install ssh-pymongo and then:
from ssh_pymongo import MongoSession
session = MongoSession(MONGO_HOST)
db = session.connection['mydatabasename']
# perform your queries #
session.stop()
If you have more complex settings, check docs for cases, e.g.:
from ssh_pymongo import MongoSession
session = MongoSession(
MONGO_HOST,
port=22,
user='ssh_username',
password='ssh_password',
uri='mongodb://admin:p#ssW0$3#127.0.0.1:27017')
db = session.connection['mydatabasename']
print(db.collection_names())
session.stop()

Proxycommand in paramiko

I'm trying to do a simple proxycommand using paramiko in python.
Basically I'm trying to replicate the behaviour of this ssh command:
ssh -i ~/.ssh/destination_key user#destination.test.internal -o 'ProxyCommand ssh -i ~/.ssh/jumpbox_key -W %h:%p user#jumpbox.test.internal'
The above works as expected amd connects to destination.test.internal.
I'm trying to do the same thing in python with the following on the same box:
#!/usr/bin/python3
import paramiko
import argparse
addresses = ["destination.test.internal"];
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy = paramiko.ProxyCommand("ssh -i ~/.ssh/jumpbox_key -W %h:%p user#jumpbox.test.internal")
for address in addresses:
#Connect over ssh to each server
try:
ssh.connect(address , username='user', key_filename="~/.ssh/destination_key", sock = proxy )
except paramiko.AuthenticationException:
print ("Authentication Failed")
except paramiko.SSHException:
print ("Connection Failed")
stdin,stdout,stderr = ssh.exec_command('ls -l')
print (stdout.readlines())
ssh.close()
Needless to say this isn't working. It's failing with:
Traceback (most recent call last):
Exception: Error reading SSH protocol banner
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 1893, in _check_banner
buf = self.packetizer.readline(timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/packet.py", line 331, in readline
buf += self._read_timeout(timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/packet.py", line 501, in _read_timeout
raise socket.timeout()
socket.timeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 1749, in run
self._check_banner()
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 1897, in _check_banner
raise SSHException('Error reading SSH protocol banner' + str(e))
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner
Connection Failed
Traceback (most recent call last):
File "./log_file_fix.py", line 31, in <module>
stdin,stdout,stderr = ssh.exec_command('ls -l')
File "/usr/local/lib/python3.5/dist-packages/paramiko/client.py", line 436, in exec_command
chan = self._transport.open_session(timeout=timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 716, in open_session
timeout=timeout)
File "/usr/local/lib/python3.5/dist-packages/paramiko/transport.py", line 800, in open_channel
raise SSHException('SSH session not active')
paramiko.ssh_exception.SSHException: SSH session not active
However I'm not sure where I'm going wrong.
Instead of %h:%p, Specify host and port inside paramiko.ProxyCommand()
proxy = paramiko.ProxyCommand("ssh -i ~/.ssh/jumpbox_key -W DESTINATION_HOST_ADDRESS:22 user#jumpbox.test.internal")
You have to change your code like below:
#!/usr/bin/python3
import paramiko
import argparse
addresses = ["destination.test.internal"];
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for address in addresses:
proxy_jump_command='ssh -i ~/.ssh/jumpbox_key -W {HOST}:{PORT} user#jumpbox.test.internal'.format(HOST=address, PORT=22)
proxy = paramiko.ProxyCommand(proxy_jump_command)
#Connect over ssh to each server
try:
ssh.connect(address , username='user', key_filename="~/.ssh/destination_key", sock = proxy )
except paramiko.AuthenticationException:
print ("Authentication Failed")
except paramiko.SSHException:
print ("Connection Failed")
stdin,stdout,stderr = ssh.exec_command('ls -l')
print (stdout.readlines())
ssh.close()

demo python server client interaction

I'm really new to networking in general and I'm trying to set up a simple exchange between a python server and client.
This is the code for the server
import socket, ssl
def do_something(connstream, data):
print "HALLO"
def deal_with_client(connstream):
data = connstream.read()
# null data means the client is finished with us
while data:
if not do_something(connstream, data):
# we'll assume do_something returns False
# when we're finished with client
break
data = connstream.read()
# finished with client
bindsocket = socket.socket()
bindsocket.bind(('127.0.0.1', 10024))
bindsocket.listen(5)
while True:
newsocket, fromaddr = bindsocket.accept()
print "Setting up connection"
connstream = ssl.wrap_socket(newsocket,
server_side=True,
ca_certs=None,
certfile="cert.pem",
keyfile="privatekey.pem",
ssl_version=ssl.PROTOCOL_TLSv1)
try:
deal_with_client(connstream)
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
Here is the code for the client.py
import socket, ssl
clientsocket = socket.socket()
ssl_sock = ssl.wrap_socket(clientsocket,
certfile="cert.pem",
cert_reqs=ssl.CERT_REQUIRED)
ssl_sock.connect(('127.0.0.1', 10024))
print ssl_sock.getpeername()
print ssl_sock.getpeercert()
data = ssl_sock.recv(1024)
ssl_sock.close()
print 'Received', repr(data)
I generated the "cert.pem" and the "privatekey.pem" using openssl.
Traceback (most recent call last):
File "server.py", line 30, in <module>
ssl_version=ssl.PROTOCOL_TLSv1)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 344, in wrap_socket
ciphers=ciphers)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 121, in __init__
self.do_handshake()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 283, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [Errno 8] _ssl.c:499: EOF occurred in violation of protocol
I was wondering if somehow who knows more could point me in the right direction. I really want to do this using SSL btw, but I would be willing to switch to TLS if that is the better approach.
It could be that the sockets are not running with a compatible ssl version, you should put a "ssl.PROTOCOL_TLSv1" compatible version in your client too (or removing it from server and use the default value too).
Googling you can find many examples of socket comunication

Categories