I have tried solutions found on other SO questions but none of them have worked for me. I am attempting to pull data from a mysql db running on a remote server by setting up an ssh tunnel. My code is as follows:
server = sshtunnel.SSHTunnelForwarder(
('10.6.41.10', 22),
ssh_username= 'serveruser',
ssh_password= 'serverpw',
remote_bind_address=('127.0.0.1', 3306))
server.start()
print(server.local_bind_port)
cnx = mysql.connector.connect(user='root', password='mysqlpw',
host='127.0.0.1',
database='mydb',
charset='utf8',
use_unicode='FALSE',
port = 3306)
However, when I run this code I receive:
1045 (28000): Access denied for user 'root'#'localhost' (using password: YES)
I have also tried adding
local_bind_address = ('0.0.0.0', 3306)
to the sshtunnel setup and instead recieved
Problem setting SSH Forwarder up: Couldn't open tunnel 0.0.0.0:3306 <> 127.0.0.1:3306 might be in use or destination not reachable
I don't fully understand the remote_bind_address and local_bind_address, so my guess is that must be doing something wrong there. I know my username/pw/server info is correct, I am able to ssh into my server via terminal and then use
mysql -h 127.0.0.1 -u root -p
to successfully log into my mysql server. So what do I need to fix to get it running in python? Thanks.
If you don't specify local_bind_address in sshtunnel.SSHTunnelForwarder, the local port is allocated randomly. In that case set port=server.local_bind_port in mysql.connector.connect().
Instead, you can also set local_bind_address=('0.0.0.0', [some port which is not in use]) in sshtunnel.SSHTunnelForwarder. The sshtunnel.HandlerSSHTunnelForwarderError ("Problem setting...") tells you that you can't use local_bind_address=('0.0.0.0', 3306).
Related
In my Python script, I want to be able to connect to a Postgres DB via an SSH tunnel.
I'm using sshtunnel package to create a tunnel, and using PyGreSQL to connect to the DB.
When I try to establish the database connection, the pg.connect call just hangs. I don't get any errors at all. When I use psql to connect to the DB using the tunnel created by sshtunnel, the connection is successful.
When I create the tunnel beforehand using ssh in shell, pg.connect call successfully connects to the database.
So to summarize:
Tunnel created in Python/sshtunnel -> pg.connect call hangs
Tunnel created in Python/sshtunnel -> psql works just fine
Tunnel created using ssh -> pg.connect call is successful
This seems to be a problem with PyGreSQL since psql can access the DB using tunnel by sshtunnel just fine. However, there could be something different about the tunnel by sshtunnel package that I'm not seeing.
This is the command I'm using to create the tunnel using SSH:
ssh -g -L <local_bind_port>:localhost:<remote_bind_port> -f -N root#myip
Following is my code to connect to the DB in Python using SSH Tunnel and pg.connect
from sshtunnel import SSHTunnelForwarder
dbasename = 'db'
username = 'admin'
password = 'admin'
portnum = 5432
tunnel = SSHTunnelForwarder(
<ip_address>,
ssh_username="admin",
ssh_password="admin",
remote_bind_address=('127.0.0.1', portnum)
)
tunnel.start()
# The line below hangs
db = pg.connect(host=tunnel.local_bind_host, port=tunnel.local_bind_port, dbname=dbasename, user=username, passwd=password)
Any ideas about what could cause this problem? Are there any logs etc I that might help identify the problem?
Thanks.
EDIT:
It turns out that if I open a tunnel using python/SSHTunnel in one python shell, but use pg.connect to connect to that tunnel in the 2nd python shell it connects successfully.
So if I copy paste the following in the 1st shell:
from sshtunnel import SSHTunnelForwarder
dbasename = 'db'
username = 'admin'
password = 'admin'
portnum = 5432
tunnel = SSHTunnelForwarder(
<ip_address>,
ssh_username="admin",
ssh_password="admin",
remote_bind_address=('127.0.0.1', portnum)
)
tunnel.start()
then open another shell and connect to the tunnel from the 1st shell
import pg
# This works for some reason
db = pg.connect(host='127.0.0.1', port=<local hind port from the 1st shell>, dbname=dbasename, user=username, passwd=password)
the connection is successful
I am trying to connect to GHTorrent database through ssh in python so I can deal with the data.
There is the example of how this ssh works in command lines and it works.
http://ghtorrent.org/mysql.html
import pymysql
from sshtunnel import SSHTunnelForwarder
mypkey = paramiko.RSAKey.from_private_key_file("/Users/***/.ssh/id_rsa")
with SSHTunnelForwarder(
('web.ghtorrent.org', 3306),
ssh_username="ghtorrent",
ssh_pkey=mypkey,
ssh_private_key_password="*****",#my password for my pc
remote_bind_address=('web.ghtorrent.org', 3306)) as server:
conn = pymysql.connect(host='127.0.0.1',
port=server.local_bind_port,
user='ght',
passwd='',
db='ghtorrent')
From my code the ssh can't connect to the server. I am not really sure whether my connection information is correct.
Since it uses a website name rather than the IP address so I have no idea whether it works.
Thank you so much!
Firstly, the GHTorrent SSH server is listening on port 22, you are trying to connect to 3306, which is incorrect.
Also, have you tried just specifying the SSH private key path directly?
i.e. ssh_pkey="/Users/***/.ssh/id_rsa"
SSHTunnelForwarder(
('web.ghtorrent.org', 22),
ssh_username="ghtorrent",
ssh_pkey="/Users/***/.ssh/id_rsa",
ssh_private_key_password="*****",#my password for my pc
remote_bind_address=('web.ghtorrent.org', 3306))
While I have no problems to connect to my localhost database that way:
import MySQLdb
localdb = MySQLdb.connect( host="127.0.0.1",
user="root",
passwd="password",
db="events")
I couldent connect to my online database.
Usually I access manually to this database with phpmyadmin and the adress is something like 212.227.000.000/phpmyadmin
So I tried something like
onlinedb = MySQLdb.connect( host="212.227.000.000" ...
or
onlinedb = MySQLdb.connect( host="212.227.000.000/phpmyadmin" ...
But I get an error such as:
OperationalError: (2003, "Can't connect to MySQL server on '212.227.000.000' (10061)")
It sounds like 212.227.000.000/phpmyadmin is the URL of PHPMyAdmin (the thing you open in the browser). If so, the database may not be hosted on the machine with IP 212.227.000.000. You should check how PHPMyAdmin connects to the database. If PHPMyAdmin connects to 127.0.0.1, that probably means the database doesn't listen on the external IP address, and can't be reached over the network.
If you have ssh access to 212.227.000.000 you can check that with the netstat command:
$ netstat -pant | grep LISTEN | grep 3306
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN -
The 0.0.0.0 above indicates that MySQL is listening on all IPs, and barring any firewalls, you should be able to connect to the database.
Otherwise, if it says 127.0.0.1:3306, the database can only be accessed from the machine itself and not over the network. In that case you can use an SSH tunnel.
I'm trying to connect to a postgresql database using the following python code:
try:
conn = psycopg2.connect("host = '10.47.65.237' dbname = 'testDB' user = 'pi' password = 'raspberry'")
except:
print("Unable to connect to testDB at 10.47.65.237. Sending Alert.")
This code works with localhost 127.0.0.1 but when I go to a different machine and try to run it with its ip above it won't connect.
Things I've done:
1. Port 5432 is open
2. edited postgresql.conf by adding the line "listen_addresses='10.47.65.138'"
3. edited pg_hba.conf by adding the following configuration "host all all 10.47.65.138 md5"
Any other things I could try or I'm missing?
Running telnet 10.47.65.237 5432 on the client should result in a Connection Refused error, which indicates that the problem has nothing to do with psycopg2.
You have misconfigured the server. listen_addresses controls which IPs the server will answer on, not which IPs the server will permit connections from. Your server's postgresql.conf should have either listen_addresses='10.47.65.237' or listen_addresses='*'. Edit the configuration and restart PostgreSQL on the server, then you should be able to connect successfully using telnet and psycopg2.
I'm having trouble with the MySQLdb module.
db = MySQLdb.connect(
host = 'localhost',
user = 'root',
passwd = '',
db = 'testdb',
port = 3000)
(I'm using a custom port)
the error I get is:
Error 2002: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
Which doesn't make much sense since that's the default connection set in my.conf.. it's as though it's ignoring the connection info I give..
The mysql server is definitely there:
[root#baster ~]# mysql -uroot -p -P3000
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19
Server version: 5.0.77 Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> use testdb;
Database changed
mysql>
I tried directly from the python prompt:
>>> db = MySQLdb.connect(user='root', passwd='', port=3000, host='localhost', db='pyneoform')
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib64/python2.5/site-packages/MySQLdb/__init__.py", line 74, in Connect
return Connection(*args, **kwargs)
File "/usr/lib64/python2.5/site-packages/MySQLdb/connections.py", line 169, in __init__
super(Connection, self).__init__(*args, **kwargs2)
_mysql_exceptions.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)")
>>>
I'm confused... :(
Changing localhost to 127.0.0.1 solved my problem using MySQLdb:
db = MySQLdb.connect(
host = '127.0.0.1',
user = 'root',
passwd = '',
db = 'testdb',
port = 3000)
Using 127.0.0.1 forces the client to use TCP/IP, so that the server listening to the TCP port can pickle it up. If host is specified as localhost, a Unix socket or pipe will be used.
add unix_socket='path_to_socket' where path_to_socket should be the path of the MySQL socket, e.g. /var/run/mysqld/mysqld2.sock
Make sure that the mysql server is listening for tcp connections, which you can do with netstat -nlp (in *nix). This is the type of connection you are attempting to make, and db's normally don't listen on the network by default for security reasons. Also, try specifying --host=localhost when using the mysql command, this also try to connect via unix sockets unless you specify otherwise. If mysql is not configured to listen for tcp connections, the command will also fail.
Here's a relevant section from the mysql 5.1 manual on unix sockets and troubleshooting connections. Note that the error described (2002) is the same one that you are getting.
Alternatively, check to see if the module you are using has an option to connect via unix sockets (as David Suggests).
I had this issue where the unix socket file was some place else, python was trying to connect to a non-existing socket. Once this was corrected using the unix_socket option, it worked.
Mysql uses sockets when the host is 'localhost' and tcp/ip when the host is anything else. By default Mysql will listen to both - you can disable either sockets or networking in you my.cnf file (see mysql.com for details).
In your case forget about the port=3000 the mysql client lib is not paying any attention to it since you are using localhost and specify the socket as in unix_socket='path_to_socket'.
If you decided to move this script to another machine you will need to change this connect string to use the actual host name or ip address and then you can loose the unix_socket and bring back the port. The default port for mysql is 3306 - you don't need to specify that port but you will need to specify 3000 if that is the port you are using.
As far as I can tell, the python connector can ONLY connect to mysql through a internet socket: unix sockets (the default for the command line client) is not supported.
In the CLI client, when you say "-h localhost", it actually interprets localhost as "Oh, localhost? I'll just connect to the unix socket instead", rather than the internet localhost socket.
Ie, the mysql CLI client is doing something magical, and the Python connector is doing something "consistent, but restrictive".
Choose your poison. (Pun not intended ;) )
Maybe try adding the keyword parameter unix_socket = None to connect()?