Connecting Node VM to SQL VM on VPN Azure - mysql

I have two VM on Azure:
Machine A: is the server which run a Nodejs application
Machine B: is a VM which is running a mysql instance
Machine A and B are in the same VPN, either with a local address. I tested the connection from Machine A to B using ping and it works.
My problem is regarding the database connection from the nodejs app and mysql instance.
app.js
var express = require('express'),
config = require('./config/config'),
db = require('./app/models');
var app = express();
module.exports = require('./config/express')(app, config);
db.sequelize
.sync()
.then(function () {
if (!module.parent) {
app.listen(config.port, function () {
console.log('Express server listening on port ' + config.port);
});
}
}).catch(function (e) {
throw new Error(e);
});
config.js
var path = require('path'),
rootPath = path.normalize(__dirname + '/..'),
env = process.env.NODE_ENV || 'production';
var config = {
development: {
root: rootPath,
app: {
name: 'api-http-revo'
},
port: process.env.PORT || 3000,
db: 'mysql://localhost/api-http-revo-development'
},
test: {
root: rootPath,
app: {
name: 'api-http-revo'
},
port: process.env.PORT || 3000,
db: 'mysql://localhost/api-http-revo-test'
},
production: {
root: rootPath,
app: {
name: 'api-http-revo'
},
port: process.env.PORT || 3000,
db: {
host: '10.0.0.4', //Local Ip address on VPN
user: 'myusername',
password: 'mypassword',
database: 'db-revo',
port: 3306
}
}
};
module.exports = config[env];
ERROR on 'npm start':
Unhandled rejection Error: SequelizeConnectionRefusedError: connect
ECONNREFUSED 10.0.0.4:3306
at /home/giovannimarino/api-http-revo/app.js:20:11
at tryCatcher (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/promise.js:689:18)
at Async._drainQueue (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues [as _onImmediate] (/home/giovannimarino/api-http-revo/node_modules/bluebird/js/release/async.js:17:14)
at processImmediate [as _immediateCallback] (timers.js:383:17)
The following screenshot are the firewall configuration:
Machine B:
Machine A

This might be due to firewall blocking your DB connections. To confirm do a telnet on the port 3306 and if it's found to be blocking then setup an inbound rule for allowing network traffic on port 3306 on both the systems.
More information here on how to setup network traffic rules.

Related

Unable to connect NodeJS app in Azure App Services to Azure MySQL Database

I have deployed an NodeJS (with ExpressJS, Sequelize) to Azure App Services. The simple APIs with no database connection work, however when I use the part of the app where I load the data from my Azure MySQL Database, it's having problem with certificate. I get this log message from App Service Log Stream:
Unhandled rejection SequelizeConnectionError: unable to get local issuer certificate
I have followed the steps from here on how to enable firewall and use the certificate (BaltimoreCyberTrustRoot.crt.pem).
Using the same instruction, from my laptop, I can connect to the remote Azure MySQL database, using this CLI:
$ mysql -h <my-db>.mysql.database.azure.com -u <my-user> --ssl-mode=REQUIRED --ssl-ca=.\BaltimoreCyberTrustRoot.crt.pem -p
I have followed other StackOverflow / Github questions related to this and I followed their configurations like this:
const mysql = require('mysql2');
...
var sequelize = new Sequelize(config.db, config.username, config.password, {
host: "<my-db>.mysql.database.azure.com",
port: 3306,
dialect: 'mysql',
dialectOptions: {
ssl: {
ca: fs.readFileSync(__dirname + "/ssl/BaltimoreCyberTrustRoot.crt.pem")
}
}
});
Do I need to set additional key/cert under ssl?
ssl: {
key: fs.readFileSync(__dirname + "./certs/client-key.pem"),
cert: fs.readFileSync(__dirname + "./certs/client-cert.pem"),
ca: fs.readFileSync(__dirname + "/ssl/BaltimoreCyberTrustRoot.crt.pem")
}
I am using Node 12 (Node 12.13 in Azure App Service) and here's my package.json dependencies:
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"faker": "^4.1.0",
"mysql2": "^2.1.0",
"sequelize": "^5.21.5"
}
According my test, I can connect to mysql. You can add additional key/cert yes or not.
If you add, you can see my code like below,
/*configuration*/
const sequelizeInstance = new Sequelize("***db", "azure_root#***mysql", "Ja***.****20", {
host: "***mysql.mysql.database.azure.com",
dialect: 'mysql',
dialectOptions: {
ssl: {
ca: fs.readFileSync(path.resolve(__dirname, 'BaltimoreCyberTrustRoot.crt.pem'));
}
}
});
/*test connection*/
try
{
sequelizeInstance.authenticate();
console.log('Connection has been established successfully.');
}
catch (error) {
console.error('Unable to connect to the database:', error);
}
If not, you just set ssl=true like the document .
Hope it's useful to u.

docker mysql with Error: connect ECONNREFUSED

Attempting to connect database from within the microservice, failing to the connect the database
Error: connect ECONNREFUSED 172.18.0.2:3306
service/index.js
var http = require('http');
//create a server object:
http.createServer(function (req, res) {
res.write('Hello World!'); //write a response to the client
res.end(); //end the response
}).listen(8080); //the server object listens on port 8080
console.log("Listening at 8080");
var mysql = require('mysql');
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
});
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
docker-compose.yml
version: '3'
services:
database:
build:
./database
ports:
- "6603:3306"
image: "test-mysql"
container_name: "test-mysql"
service:
build:
./service
ports:
- "8080:8080"
depends_on:
- database
image: "test-nodejs"
container_name: "test-nodejs"
restart: on-failure
I've attempted connecting to database with different settings.
1) Without port
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
});
2) specified port 3306
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
port: 3306
});
3) specified port 6603
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password",
port: 6603
});
database/Dockerfile
FROM mysql
ENV MYSQL_DATABASE=test
ENV MYSQL_ROOT_PASSWORD=password
EXPOSE 6603:3306
COPY ./schema.sql /docker-entrypoint-initdb.d/
Basically how my node.js microservice can discover the database service?
Edit
I suspected that database wasn't ready by the time nodejs kicks in, so I added some delay before connecting to database and error changed
Updated Code
setTimeout(function(){
var mysql = require('mysql');
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
});
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
}, 20 * 1000);
output
Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
Probably you are using a version of MySQL that doesnt support the login you are trying. Try with mysql v5.7:
docker run -d -p 6603:3306 --name mysql-container -e MYSQL_ROOT_PASSWORD=password mysql:5.7
You miss order:
First connect to database, then listen the port.
var http = require('http');
var mysql = require('mysql');
var con = mysql.createConnection({
host: "database",
user: "root",
password: "password"
} );
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
//create a server object:
http.createServer(function (req, res) {
res.write('Hello World!'); //write a response to the client
res.end(); //end the response
}).listen(8080); //the server object listens on port 8080
console.log("Listening at 8080");
the database port does not get translated as it's within the container. just use 3306 in your app

Error accessing remote DB with sequelize via tunnel-ssh

I have an EC2 Ubuntu instance on AWS with MySQL DB which I can access with the following configuration via HeidiSQL and everything works fine. My main goal is to connect to this DB through sequelize. I have tried to do it with npm package tunnel-ssh but constantly getting errors.
Settings
SSH Tunnel Settings
AWS EC2 Instance security group settings:
Error message:
{ SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306
at Utils.Promise.tap.then.catch.err (G:\study\ssh-tunnel\sqlize-ssh\node_modules\sequelize\lib\dialects\mysql\connection-manager.js:139:19)
at tryCatcher (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\promise.js:512:31)
at Promise._settlePromise (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\promise.js:569:18)
at Promise._settlePromise0 (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\promise.js:614:10)
at Promise._settlePromises (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\promise.js:690:18)
at _drainQueueStep (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\async.js:138:12)
at _drainQueue (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\async.js:131:9)
at Async._drainQueues (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\async.js:147:5)
at Immediate.Async.drainQueues [as _onImmediate] (G:\study\ssh-tunnel\sqlize-ssh\node_modules\bluebird\js\release\async.js:17:14)
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
name: 'SequelizeConnectionRefusedError',
parent:
{ Error: connect ECONNREFUSED 127.0.0.1:3306
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3306,
fatal: true },
original:
{ Error: connect ECONNREFUSED 127.0.0.1:3306
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1117:14)
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3306,
fatal: true } }
packages I use: mysql2, sequelize, tunnel-ssh
I think so far I was able to open the ssh-tunnel and run sequelize but with errors. This is the code I've written:
const fs = require('fs');
const Sequelize = require("sequelize");
const tunnel = require('tunnel-ssh');
const ppk = fs.readFileSync('./sample.ppk', 'utf-8');
const sequelize = new Sequelize('test', 'login', 'password', {
host: 'localhost',
port: 3306,
dialect: "mysql",
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
const sshConfig = {
user: 'ubuntu',
host: 'sshServer',
port: 22,
dstHost: 'localhost',
dstPort: 3306,
localHost: 'localhost',
localPort: 3307,
privateKey: ppk
}
// initiate tunnel
tunnel(sshConfig, (error, server) => {
if(error) {
console.error(error);
} else {
console.log('server:', server);
sequelize
.authenticate()
.then((db) => {
console.log('CONNECTION ESTABLISHED! ', db);
})
.catch((err) => {
console.error('UNABLE TO ESTABLISH CONNECTION: ', err);
})
}
})
The issue was resolved by not using ssh-tunnel connection at all. I opened mysql port only for my home ip instead and created a new user with all permissions granted.
Fixed my code a bit: added a server's ip address instead of localhost. It works now.
const sequelize = new Sequelize('DBname', 'userName', 'password', {
host: 'ec2-xx-xxx-xx-x.ap-xxxxxxxxxxxx.compute.amazonaws.com',
port: 3306,
dialect: "mysql",
});
for mysql/aurora there custom Ip address if your script running locally on that EC# then you will be able make connection.
Add one rule with anywhere access and try it. for mysql

Connect Sequelize/Node to XAMPP Mysql

I've a working script to connect and work with Sequelize on Node.js
But now i'm trying to connect this to my MySQL database on XAMPP
MySQL Port on XAMPP: 3306
When i run node.js after i have configured the app.listen and the config of sequealize i get the following error
ERROR: listen EADDRINUSE :::3306
I've looked for but i didn't find much information about that, i don't know what i'm doing bad.
Thanks you for every answer!
app.js
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan')
const { sequelize } = require('./models')
const config = require('./config/config')
const app = express()
app.use(morgan('combined'))
app.use(bodyParser.json())
app.use(cors())
require('./routes')(app)
sequelize.sync()
.then(() => {
app.listen(config.db.options.port || 3306) // 8081 original
console.log(`Server iniciado en puerto: ${config.db.options.port}`)
})
config.js
module.exports = {
db: {
database: process.env.DB_NAME || 'intraenvios',
user: process.env.DB_USER || 'root',
password: process.env.DB_PASS || '',
options: {
dialect: process.env.DIALECT || 'mysql', // sqlite original
host: process.env.HOST || 'localhost',
storage: './intraenvios.sqlite',
port: process.env.PORT || 3306 // 8081 original
}
}
}
EDIT:
For to connect by xampp simply, i made this:
const sequelize = new Sequelize('test', 'root', '', {
host: "127.0.0.1",
dialect : 'mysql',
operatorsAliases: false
});
sequelize.authenticate().then(function(){
console.log("sucess");
}).catch(function(error){
console.log("error: "+error);
});
Obs: operatorsAliases: false - To fix deprecated message of sequelize
Good Fun :)

Error in connecting to Mysql from nodejs

I have started node-js recently and i was trying to connect my nodejs server with mysql.
The problem is i am getting an error, i really don't know why, i am using phpmyadmin.
Phpmyadmin details
user: root
host: localhost
password is not set
This is the image of my phpmyadmin database
This is the settings of my phpmyadmin console
This is the terminal where it is showing error connecting to DB
index.js
var express = require("express");
var app = express();
var mysql = require('mysql');
var port = process.env.PORT || 3000;
var connection = mysql.createConnection({
host: "localhost",
user: "root",
database: "learning",
});
connection.connect(function(err){
if(err) {
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
console.log('3');
connection.end(function(err) {
console.log('Connection closed');
console.log('4');
process.exit();
});
});
app.listen(port,function(err1){
console.log("Listening on the port 3000");
});
connection to mysql from node js, you are use to mysql from node js connection
/config
/database.js
/server.js
/.env
const http = require('http');
const app = require('express')();
require('./config/database.js');
const bodyParser = require('body-parser');
const server = http.createServer(app);
server.listen(process.env.ServerPort, '0.0.0.0', () => {
logger.info(`Express server listening on port ${process.env.ServerPort}`);
});
When you run this:
node server.js
database.js file
const My = require('jm-ez-mysql');
// Init DB Connection
const connection = My.init({
host: process.env.DBHOST,
user: process.env.DBUSER,
password: process.env.DBPASSWORD,
database: process.env.DATABASE,
dateStrings: true,
charset: 'utf8mb4',
timezone: 'utc',
multipleStatements: true,
connectTimeout: 100 * 60 * 1000,
acquireTimeout: 100 * 60 * 1000,
timeout: 100 * 60 * 1000,
});
module.exports = {
connection,
};
I had changed the port from default 3306 of phpmyadmin mysql to 3308
therefore i added port: 3308 and it started working.
var connection = mysql.createConnection({
host: "localhost",
user: "root",
database: "learning",
port: 3308
});