Делаем доступной базу данных для удаленного подключения

Начнем с того что бывают случаи, когда нужно делать приложение с подключением к базе данных. Это делается для того чтобы особо не копаться в бэкэнд разработке и сконцентрироваться на фронтэнде из-за нехватки рук и навыков. Я не берусь говорить, что мое решение будет безопасным, но оно работает.

Поскольку я не люблю платить за хостинг, я воспользовался сетью на своей работе, там есть белый IP. Вот ее структура:

Делаем доступной базу данных для удаленного подключения

У меня имеется доступ к нескольким компьютерам точнее к 192.168.1.2 (он же 192.168.0.2) там стоит Linux и к 192.168.0.3 с Windows. В общем, для своего приложения я выбрал mysql и посмотрел что есть на Linux. Там уже был установлен он, но пароль никто не знает, а те кто знали забыли (те кто работал до меня). Узнав что он никому не нужен, я его удалил и попытался установить заново. Память не хватало и поскольку чтобы исправить эту ошибку пришлось бы подключать к нему монитор и клавиатуру с мышью, я решил бросить это дело. Тем более что машина с Windows куда мощней и плюс ко всему у меня у самого стоит она на ноутбуке домашнем. В принципе саму установку я описывать не буду, есть куча мануалов и видео про это. Установив mysql на Windows машину, я решил сделать бэкап таблиц с ноутбука на рабочую станцию.

Делается это так (в моем случае):

mysqldump -uroot -p your_base > dump_file.sql

Далее в новой базе данных создаем базу данных и восстанавливаем бэкап на «новой» машине.

mysql -h localhost -u root -p

create database your_base;
use your_base;

mysql -uroot -p your_base < dump_file.sql

show tables;


Файл с бэкапом надо на новую машину положить и возможно если не в директории с утилитой то полный путь к ней. (Я просто залил бэкап на гитхаб и клонировал его на новую машину). Я бы добавил как создаются сами таблицы, но не сохранил скрины, да и думаю это не сложно даже студенту 2-3 курса.

Когда восстановил все таблицы, пришло время сделать доступным удаленный доступ к бд. В общем, такие команды к успеху не привели (выдал только право на чтение select)

create user 'client'@'%' IDENTIFIED by 'client';
grant select on your_base . * to 'client'@'%';
flush privileges;

Точнее я мог подключится к базе только командой,

mysql -h localhost -u client -pclient

а такой уже не мог

mysql -h 192.168.0.3 -u client -pclient

мне это не подходило также не мог подключится через этот адрес и от root.

Помогла программка mysql workbench там в настройках меняете localhost на % и работает, хотя client это не помогло. Теперь вы можете подключаться к бд из консоли или из кода с любого адреса.

Делаем доступной базу данных для удаленного подключения

Еще нужно сделать сеть домашней или предприятия и выключить брандмауэр Windows иначе не сможете даже сделать пинг этой машины(не то чтобы подключится к бд).

Пол дела сделано, дальше нужно чтобы я мог из дома подключится к базе данных.

Как видно из схемы сети, то до интернета надо пройти путь от 192.168.0.3 до 192.168.1.1 (роутер) пойдем в обратную сторону. Настроим маршрут от 192.168.1.1 до 192.168.1.2 вот таким образом:

Делаем доступной базу данных для удаленного подключения

В общем, картинку не показывает — напишу руками:

route add 192.168.0.0 mask 255.255.255.0 gateway 192.168.1.2

Это можно сделать только в одной подсети то есть нельзя сразу пробросить на адрес 192.168.0.2 или 192.168.0.3

Это нужно чтобы роутер знал где находится подсеть 192.168.0.0/24 (учите основы сетей это полезно).

Теперь добавляем проброс порта 3306 (порт mysql по дефолту (если вы его при установки только не поменяли)) на адрес 192.168.1.2

Делаем доступной базу данных для удаленного подключения

Вот осталось сделать самое сложное это сделать форвардинг на линукс машине(на ней две сетевые карточки 192.168.1.2 (интерфейс enp3s1) и 192.168.0.2(интерфейс enp3s0) чтобы сетевухи знали что перебросить их с 192.168.1.2 на 192.168.0.2, а потом на нашу Windows машину с MySql.

sudo iptables -A FORWARD -i enp3s1 -o enp3s0 -p tcp --syn --dport 3306 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i enp3s1 -o enp3s0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i enp3s0 -o enp3s1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A PREROUTING -i enp3s1 -p tcp --dport 3306 -j DNAT --to-destination 192.168.0.3
sudo iptables -t nat -A POSTROUTING -o enp3s0 -p tcp --dport 3306 -d 192.168.0.3 -j SNAT --to-source 192.168.1.2
и последняя строчка сохраняет введенные команды чтобы они при перезапуске оси не стерлись
sudo service iptables-persistent save

Т.е. 1я строчка значит что мы принимаем первое соединение, 2-я и 3-я что можно в обе стороны пускать пакеты, 4-я и 5-я значит замену адреса назначения и источника. И вуаля можно коннектиться из дома через mysql. И напоследок мой код на с++ который это делает:

//DataBaseConnection.cpp
#include "DataBaseConnection.h"

DataBaseConnection::DataBaseConnection()
{
}
void DataBaseConnection::Connect()
{
	// Получаем дескриптор соединения
	conn = mysql_init(NULL);
	if (conn == NULL)
	{
		// Если дескриптор не получен – выводим сообщение об ошибке
		fprintf(stderr, "Error: can'tcreate MySQL-descriptorn");
		//exit(1); //Если используется оконное приложение
	}
	// Подключаемся к серверу
	if (!mysql_real_connect(conn, "192.168.0.3", "root", "password", "your_base", NULL, NULL, 0))
	{
		// Если нет возможности установить соединение с сервером 
		// базы данных выводим сообщение об ошибке
		fprintf(stderr, "Error: can't connect to database: %sn", mysql_error(conn));
	}
	else
	{
		// Если соединение успешно установлено выводим фразу - "Success!"
		fprintf(stdout, "Success!n");
	}
}
std::vector<std::string> DataBaseConnection::Query()
{
	vectordrum.clear();
	std::string query = "SELECT * FROM drum where id=0";
	const char * q = query.c_str();
	qstate = mysql_query(conn, q);
	if (!qstate)
	{
		res = mysql_store_result(conn);
		while (row = mysql_fetch_row(res))
		{
			//printf("ID: %s,Position: %s, Image: %sn", row[0], row[1], row[2]);
			vectordrum.push_back(row[2]);
		}
	}
	else
	{
		std::cout << "Query failed:" << mysql_error(conn) << std::endl;
	}
	return vectordrum;
}
void DataBaseConnection::Close()
{
	// Закрываем соединение с сервером базы данных
	mysql_close(conn);
}
DataBaseConnection::~DataBaseConnection()
{
	vectordrum.clear();
}
//DataBaseConnection.h
#pragma once
#include <iostream>
#include <mysql.h>
#include <vector>
#pragma comment(lib,"mysqlcppconn.lib")
#pragma comment(lib,"libmysql.lib")
class DataBaseConnection
{
public:
	DataBaseConnection();
	void Connect();
	std::vector<std::string> Query();
	void Close();
	~DataBaseConnection();
	MYSQL *conn;
	MYSQL_ROW row;
	MYSQL_RES *res;
	int qstate;
	std::vector<std::string> vectordrum;
};

Теперь можно смело скидывать эту программу кому угодно, и не надо переписывать чтобы она работала локально.

Источник: habr.com