I have problem to connect to any mysql database using jdbc connector in google apps scripts, I'm using tutorial code:
var conn = Jdbc.getConnection("jdbc:mysql://host(or ip):3306/database", "username", "password");
But in each case ( I've tested 4 different databases on 4 different host names) i get the same error:
Failed to establish a database connection. Check connection string, username and password. (line 2)
I'm looking for some help, I have no idea what could be the problem ;-(
ps. usernames/passwords are ok.
pps. In each database remote access is working ( I've tested by using telnet).
Since your issue was Remote access to a MySQL Database I will post some related documentation so that future viewers like TonyMiao will have a avenue to fix their own related issues.
Step # 1: Login Using SSH (if server is outside your data center)
First, login over ssh to remote MySQL database server. You may need to login to your MySQL server as the root user:
ssh user#server1.cyberciti.biz
login as the root using su or sudo
su
or use sudo
sudo -i
OR directly login as root user if allowed:
ssh root#server1.cyberciti.biz
Step # 2: Edit the my.cnf file
Once connected you need to edit the MySQL server configuration file my.cnf using a text editor such as vi:
If you are using Debian/Ubuntu Linux file is located at /etc/mysql/my.cnf location.
If you are using Red Hat Linux/Fedora/Centos Linux file is located at /etc/my.cnf location.
If you are using FreeBSD you need to create a file /var/db/mysql/my.cnf location.
Edit the /etc/my.cnf, run:
# vi /etc/my.cnf
Step # 3: Once file opened, locate line that read as follows
[mysqld]
Make sure line skip-networking is commented (or remove line) and add following line
bind-address=YOUR-SERVER-IP
For example, if your MySQL server IP is 65.55.55.2 then entire block should be look like as follows:
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
language = /usr/share/mysql/English
bind-address = 65.55.55.2
# skip-networking
....
..
....
Where,
bind-address: IP address to bind to.
skip-networking : Don’t listen for TCP/IP connections at all. All
interaction with mysqld must be made via Unix sockets. This option is
highly recommended for systems where only local requests are allowed.
Since you need to allow remote connection this line should be removed
from my.cnf or put it in comment state.
Step# 4 Save and Close the file
If you are using Debian / Ubuntu Linux, type the following command to restart the mysql server:
# /etc/init.d/mysql restart
OR
# systemctl restart mysql
If you are using RHEL / CentOS / Fedora / Scientific Linux, type the following command to restart the mysql server:
# /etc/init.d/mysqld restart
OR
# systemctl restart mysqld
If you are using FreeBSD, type the following command to restart the mysql server:
# /usr/local/etc/rc.d/mysql-server restart
OR
# service mysql-server restart
Step # 5 Grant access to remote IP address
Connect to mysql server:
$ mysql -u root -p mysql
GRANT ACCESS TO A NEW DATABASE
If you want to add a new database called foo for user bar and remote IP 202.54.10.20 then you need to type the following commands at mysql> prompt:
mysql> CREATE DATABASE foo;
mysql> GRANT ALL ON foo.* TO bar#'202.54.10.20' IDENTIFIED BY 'PASSWORD';
HOW DO I GRANT ACCESS TO AN EXISTING DATABASE?
Let us assume that you are always making connection from remote IP called 202.54.10.20 for database called webdb for user webadmin, To grant access to this IP address type the following command At mysql> prompt for existing database, enter:
mysql> update db set Host='202.54.10.20' where Db='webdb';
mysql> update user set Host='202.54.10.20' where user='webadmin';
Step # 6: Logout of MySQL
Type exit command to logout mysql:
mysql> exit
Step # 7: Open port 3306
You need to open TCP port 3306 using iptables or BSD pf firewall.
A SAMPLE IPTABLES RULE TO OPEN LINUX IPTABLES FIREWALL
/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 3306 -j ACCEPT
OR only allow remote connection from your web server located at 10.5.1.3:
/sbin/iptables -A INPUT -i eth0 -s 10.5.1.3 -p tcp --destination-port 3306 -j ACCEPT
OR only allow remote connection from your lan subnet 192.168.1.0/24:
/sbin/iptables -A INPUT -i eth0 -s 192.168.1.0/24 -p tcp --destination-port 3306 -j ACCEPT
Finally save all rules (RHEL / CentOS specific command):
# service iptables save
A SAMPLE FREEBSD / OPENBSD / NETBSD PF FIREWALL RULE ( /ETC/PF.CONF)
Use the following to open port # 3306 on a BSD based systems:
pass in on $ext_if proto tcp from any to any port 3306
OR allow only access from your web server located at 10.5.1.3:
pass in on $ext_if proto tcp from 10.5.1.3 to any port 3306 flags S/SA synproxy state
Step # 8: Test it
From your remote system or your desktop type the following command:
$ mysql -u webadmin -h 65.55.55.2 -p
Where,
-u webadmin: webadmin is MySQL username
-h IP or hostname: 65.55.55.2 is MySQL server IP address or hostname (FQDN)
-p : Prompt for password
You can also use the telnet or nc command to connect to port 3306 for testing purpose:
$ echo X | telnet -e X 65.55.55.2 3306
OR
$ nc -z -w1 65.55.55.2 3306
Sample outputs:
Connection to 65.55.55.2 3306 port [tcp/mysql] succeeded!
Resource information: Click Here!
Related
I have a complex SSH tunnel problem I'm trying to solve and can't seem to get it quite right.
Simply put:
ME -> Bastion:22 -> Instance:8500
Bastion uses a different username and key than instance. I would like to be able to access port 1234 on instance from localhost:1234
Right now I have the following:
Host bastion
HostName bastion.example.com
ForwardAgent yes
IdentityFile ~/.ssh/id_ecdsa
User spanky
Host internal
ForwardAgent yes
HostName consul.internal
IdentityFile ~/.ssh/aws.pem
ProxyJump bastion
User ec2-user
Port 8500
But I don't think I've got it.
The following two commands work, but I'm trying to distill them into a working config:
ssh -L 2222:10.0.0.42:22 bastion.example.com -N -i ~/.ssh/id_ecdsa
ssh -L 8500:localhost:8500 ec2-user#localhost -N -i ~/.ssh/aws.pem -p 2222
With a current version of ssh, you should be able to use:
ssh -L1234:localhost:1234 -J spanky#bastion.example.com ec2-user#consul.internal
From man ssh:
-J destination
Connect to the target host by first making a ssh
connection to the jump host described by destination and then
establishing a TCP forwarding to the ultimate destination from there.
Multiple jump hops may be specified separated by comma characters.
This is a shortcut to specify a ProxyJump configuration directive.
Note this is different from How to expose a service running inside a docker container, bound to localhost, which can be addressed in multiple ways in Docker for Linux, say through --net host or even -v to bind my Linux-flavor client in etc. My problem is specific for Docker for Mac, so it's not as straightforward.
I have a TCP server binding to localhost:5005 running inside Docker for Mac. (For security reason, I must not bind to 0.0.0.0:5005.)
I have a TCP client sending request to this server from my Mac (not inside the docker container).
My question is, how do I make it work?
In Linux Docker, I would simply use --net=host so the server binds to my host lo interface, but it seems that Docker for Mac runs on a managed VM, so the host network behavior is different behavior.
To illustrate my point:
On MacBook
It simply would not work
[me#MacBook App]$ docker run -v `pwd`:/App -p 127.0.0.1:5005:5005 nitincypher/docker-ubuntu-python-pip /App/server.py
[me#MacBook App]$ ./client.py
Client received data:
On Linux
In comparison, it would be trivial to do on Linux by using host network mode. Since I'm using my Linux's lo interface as my container lo interface.
[me#Linux App]$ docker run -v `pwd`:/App --net=host nitincypher/docker-ubuntu-python-pip /App/server.py
Server Connection address: ('127.0.0.1', 52172)
Server received data: Hello, World!
[me#Linux App]$ ./client.py
Client received data: Hello, World!
My Simulated Server Code
Requirement: It MUST bind to localhost, and nothing else. So I cannot change it to 0.0.0.0.
#!/usr/bin/env python
import socket
TCP_IP = 'localhost'
TCP_PORT = 5005
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Server Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "Server received data:", data
conn.send(data) # echo
conn.close()
My Simulated Client Code
Requirement: It MUST be ran on MacBook, since the real client is written in CPP and compiled to run only on MacBook.
#!/usr/bin/env python
import socket
TCP_IP = 'localhost'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "Client received data:", data
Here's a working solution. The basic idea is to use SSH tunneling to do the port forwarding.
High Level Idea
You first need to build a docker image to support SSH access, because
ubuntu image doesn't have a sshd out of box, and also
you will need to know the password of root of your running container.
Then you will spin up your container as what you would normally do except that you are doing that based on the new image you created.
You create a SSH tunneling session from your MacBook, then you run your client on MacBook as you would normally do.
For reference, the command for SSH tunneling can be found here, the process of creating a sshd docker image is explained here, and how to ssh into docker container is explained here
Steps
Create a Docker file Dockerfile
#Use whatever image you are using on Docker Linux , say "FROM ubuntu:16.04"
FROM nitincypher/docker-ubuntu-python-pip
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:screencast' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# SSH login fix. Otherwise user is kicked off after login
RUN sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
Create a Docker Image from the Dockerfile
[me#MacBook App]$ docker build -t my_ssh_python .
Spin up your server container
[me#MacBook App]$ docker run -d -P -v `pwd`:/App --name myserver my_ssh_python
Start your server inside the container
[me#MacBook App]$ docker exec myserver /App/server.py
Create a SSH tunnel
[me#MacBook App]$ ssh root#`hostname` -p `docker port myserver 22 | awk -F ":" '{print $2}'` -L 8000:localhost:8000 -N
#Password is "screencast" as you built in Dockerfile
Note that
a. You have to use the IP address of your MacBook instead of your docker container's IP address.
b. You will use the port where the default container ssh port 22 is mapped to on host
c. In tunneling -L 8000:localhost:8000, you are saying forward anything from your MacBook 8000 (the first 8000) to Docker container's localhost at port 8000
Now you can use you client locally
[me#MacBook App]$ ./client.py
Client received data: Hello, World!
And on server side, you can see
Server Connection address: ('127.0.0.1', 55396)
Server received data: Hello, World!
I am trying to fetch some data using psql command. If I run the command directly in the console its working fine. The same command if I try to run from shell script, it says unable to connect to psql server. I have checked the listen_address variable in postgresql.conf, as I expected it was set to some name instead of * or localhost.
This server is running under cluster environment, so its using virtual ip in listen_address. The pg_hba.conf allowing local (IPv4 and IPv6) with trust authentication.
It makes sense to me so far. But, I'm confused why it isn't allowing through shell script on same server?
Edit 1:
myuser # psql -d mydb -U postgres -c "select 1"
?column?
----------
1
(1 row)
myuser # cat myscript.sh
psql -d mydb -U postgres -c "select 1"
myuser # sh myscript.sh
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/run/postgresql/.s.PGSQL.5432"?
can be used postgres_fdw to connect via ssh tunnel?
The database is accessible only from the DB server, andI need to join from another remote server. The DB server log in with SSH keys.
If it's possible, how please?
Yes It is possible. I solved it for mysql_fdw like that;
I use autossh for port forwarding. With autossh, you can keep connection up all time.
Run command on Postgres server:
autossh -L 127.0.0.1:3306:mysql_ip:3306 root#mysql_ip -N -i .ssh/id_rsa.mysql
Test autossh access from Postgres to Mysql.
Run command on Postgres server;
mysql --host=127.0.0.1 --port=3306 -u mysqldbuser -p
Last different part is;
CREATE SERVER mysql_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS (host '127.0.0.1', port '3306');
Other things are same.
I'm trying to use the Docker API to connect to docker daemon from another machine. I am able to do this command successfully:
docker -H=tcp://127.0.0.1:4243 images
But NOT when I use the real IP address:
docker -H=tcp://192.168.2.123:4243 images
2013/08/04 01:35:53 dial tcp 192.168.2.123:4243: connection refused
Why can't I connect when using a non-local IP?
I'm using a Vagrant VM with the following in Vagrantfile: config.vm.network :private_network, ip: "192.168.2.123"
The following is iptables:
# Generated by iptables-save v1.4.12 on Sun Aug 4 01:24:46 2013
*filter
:INPUT ACCEPT [1974:252013]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1511:932565]
-A INPUT -p tcp -m tcp --dport 4243 -j ACCEPT
COMMIT
# Completed on Sun Aug 4 01:24:46 2013
# Generated by iptables-save v1.4.12 on Sun Aug 4 01:24:46 2013
*nat
:PREROUTING ACCEPT [118:8562]
:INPUT ACCEPT [91:6204]
:OUTPUT ACCEPT [102:7211]
:POSTROUTING ACCEPT [102:7211]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.16.42.0/24 ! -d 172.16.42.0/24 -j MASQUERADE
Came across a similar issue, one thing I don't see mentioned here is you need to start docker to listen to both the network and a unix socket. All regular docker (command-line) commands on the host assume the socket.
sudo docker -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock -d &
will start docker listening to any ip address on your host, as well as the typical unix socket.
You need to listen to 0.0.0.0. When you listen on 127.0.0.1, it means that no one outside your host will be able to connect.
Please note that in doing this, you have given anyone, and any URL sent to you by email access to your Docker API, and thus root permission.
you should, at minimum, secure your socket using https: http://docs.docker.com/articles/https/
There are 2 ways in configuring the docker daemon port
1) Configuring at /etc/default/docker file:
DOCKER_OPTS="-H tcp://127.0.0.1:5000 -H unix:///var/run/docker.sock"
2) Configuring at /etc/docker/daemon.json:
{
"hosts": ["tcp://<IP-ADDRESS>:<PORT>", "unix:///var/run/docker.sock"]
}
IP-ADDRESS - any address which is accessible can be used.
Restart the docker service after configuring the port.
The reason for adding both the user port[ tcp://127.0.0.1:5000] and default docker socket[unix:///var/run/docker.sock] is that the user port enables the access to the docker APIs whereas the default socket enables the CLI.