คำตอบสั้น ๆ: เชื่อมต่อ MySQL หรือ MariaDB จากเครื่องอื่นอย่างปลอดภัย ด้วย SSH Tunnel หรือเปิดพอร์ต 3306 เฉพาะ IP ที่อนุญาต พร้อมบังคับใช้การเชื่อมต่อแบบเข้ารหัส
คู่มือนี้อธิบาย MySQL ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
ค่าเริ่มต้นของ MySQL และ MariaDB บน Ubuntu จะรับการเชื่อมต่อจากเครื่องตัวเองเท่านั้น ซึ่งปลอดภัยที่สุดสำหรับเว็บไซต์ที่แอปกับฐานข้อมูลอยู่เครื่องเดียวกัน แต่บางกรณีจำเป็นต้องเชื่อมต่อจากภายนอก เช่น ใช้โปรแกรมจัดการอย่าง MySQL Workbench, DBeaver หรือ HeidiSQL จากคอมพิวเตอร์ในออฟฟิศ หรือแยกเซิร์ฟเวอร์แอปกับเซิร์ฟเวอร์ฐานข้อมูลออกจากกัน
พอร์ต 3306 ที่เปิดสู่อินเทอร์เน็ตทั้งหมดจะถูกสแกนและเดารหัสผ่านตลอดเวลา คู่มือนี้จึงเสนอสองวิธีตามลำดับความปลอดภัย วิธีที่ 1 คือ SSH Tunnel ซึ่งไม่ต้องเปิดพอร์ตฐานข้อมูลเลย และวิธีที่ 2 คือเปิดพอร์ตเฉพาะ IP ที่อนุญาต
สิ่งที่ต้องเตรียม
- สิทธิ์
sudoบนเซิร์ฟเวอร์ฐานข้อมูล และสิทธิ์ root ของ MySQL/MariaDB - IP สาธารณะของเครื่องที่จะเชื่อมต่อเข้ามา ควรเป็น IP คงที่ ตรวจได้จากเว็บไซต์ตรวจ IP หรือคำสั่ง
curl -4 ifconfig.meบนเครื่องนั้น ตัวอย่างในคู่มือใช้203.0.113.10 - MySQL 8 หรือ MariaDB 10.x บน Ubuntu 22.04/24.04 หรือ AlmaLinux/Rocky Linux 8-9
วิธีที่ 1 (แนะนำ): เชื่อมต่อผ่าน SSH Tunnel
SSH Tunnel ส่งการเชื่อมต่อฐานข้อมูลผ่านช่อง SSH ที่เข้ารหัสอยู่แล้ว ฐานข้อมูลยังฟังเฉพาะ 127.0.0.1 เหมือนเดิม และไม่ต้องแก้ Firewall เหมาะกับผู้ดูแลที่เข้าไปจัดการฐานข้อมูลเป็นครั้งคราว
บนเครื่องของคุณ (Linux, macOS หรือ Windows 10/11 ที่มี OpenSSH) เปิด Terminal แล้วรัน
ssh -N -L 3307:127.0.0.1:3306 user@IP-ของเซิร์ฟเวอร์คำสั่งนี้เปิดพอร์ต 3307 บนเครื่องของคุณ แล้วส่งต่อไปยังพอร์ต 3306 ของเซิร์ฟเวอร์ผ่าน SSH ปล่อยหน้าต่างนี้เปิดไว้ระหว่างใช้งาน จากนั้นในโปรแกรมจัดการฐานข้อมูลให้เชื่อมต่อไปที่ Host 127.0.0.1 พอร์ต 3307 ด้วยผู้ใช้ฐานข้อมูลที่มี Host เป็น localhost หรือ 127.0.0.1 ตามที่สร้างไว้ในเซิร์ฟเวอร์
โปรแกรมอย่าง MySQL Workbench, DBeaver และ HeidiSQL มีตัวเลือก "Standard TCP/IP over SSH" หรือแท็บ SSH ให้ใส่ข้อมูล SSH ได้ในหน้าตั้งค่าการเชื่อมต่อโดยตรง ซึ่งให้ผลแบบเดียวกัน
วิธีที่ 2: เปิดพอร์ต 3306 เฉพาะ IP ที่อนุญาต
ใช้เมื่อแอปบนเซิร์ฟเวอร์อีกเครื่องต้องเชื่อมต่อตลอดเวลา ถ้าทั้งสองเครื่องอยู่ในเครือข่ายภายใน (Private Network) เดียวกัน ให้ใช้ IP ภายในแทน IP สาธารณะทุกจุด
ขั้นตอนที่ 1: แก้ bind-address ให้รับการเชื่อมต่อจากภายนอก
ตำแหน่งไฟล์ตั้งค่าต่างกันตามระบบ
| ระบบ | ไฟล์ |
|---|---|
| Ubuntu + MariaDB | /etc/mysql/mariadb.conf.d/50-server.cnf |
| Ubuntu + MySQL 8 | /etc/mysql/mysql.conf.d/mysqld.cnf |
| AlmaLinux/Rocky + MariaDB | /etc/my.cnf.d/mariadb-server.cnf |
| AlmaLinux/Rocky + MySQL 8 | /etc/my.cnf.d/mysql-server.cnf |
หาบรรทัด bind-address = 127.0.0.1 ในส่วน [mysqld] แล้วเปลี่ยนเป็น IP ของเซิร์ฟเวอร์ที่ต้องการให้รับการเชื่อมต่อ หรือ 0.0.0.0 เพื่อรับทุก Interface ของ IPv4
[mysqld]
bind-address = 0.0.0.0บน AlmaLinux และ Rocky Linux ไฟล์มักไม่มีบรรทัด bind-address ซึ่งหมายความว่าฐานข้อมูลฟังทุก Interface อยู่แล้ว และอาศัย firewalld ปิดพอร์ตไว้ ในกรณีนั้นไม่ต้องแก้ไฟล์ ให้ข้ามไปขั้นตอนที่ 2
รีสตาร์ตบริการ ชื่อบริการขึ้นอยู่กับระบบ
sudo systemctl restart mariadb # MariaDB ทุก Distro
sudo systemctl restart mysql # MySQL บน Ubuntu
sudo systemctl restart mysqld # MySQL บน AlmaLinux / Rocky Linuxตรวจว่าฟังพอร์ตแล้ว
sudo ss -tlnp | grep 3306ผลลัพธ์ต้องเห็น 0.0.0.0:3306 หรือ IP ที่กำหนด แทนที่จะเป็น 127.0.0.1:3306
ขั้นตอนที่ 2: สร้างผู้ใช้ที่เชื่อมต่อได้จาก IP ที่กำหนดเท่านั้น
sudo mysqlCREATE USER 'appremote'@'203.0.113.10' IDENTIFIED BY 'รหัสผ่านที่แข็งแรง';
GRANT SELECT, INSERT, UPDATE, DELETE ON shopdb.* TO 'appremote'@'203.0.113.10';ระบุ IP ต้นทางใน Host ของผู้ใช้เสมอ หลีกเลี่ยง '%' ซึ่งหมายถึงเชื่อมต่อได้จากทุกที่ และอย่าเปิดให้ root เชื่อมต่อจากภายนอก ดูรายละเอียดเรื่องสิทธิ์เพิ่มเติมที่ สร้างฐานข้อมูลและผู้ใช้ MySQL/MariaDB พร้อมกำหนดสิทธิ์
ขั้นตอนที่ 3: อนุญาตพอร์ต 3306 เฉพาะ IP ต้นทางใน Firewall
Ubuntu ที่ใช้ UFW
sudo ufw allow from 203.0.113.10 to any port 3306 proto tcp
sudo ufw status numberedAlmaLinux และ Rocky Linux ที่ใช้ firewalld
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --list-rich-rulesห้ามใช้ ufw allow 3306 หรือ --add-port=3306/tcp แบบไม่ระบุต้นทาง เพราะจะเปิดให้ทั้งอินเทอร์เน็ต หากเซิร์ฟเวอร์มี Security Group หรือ Firewall ภายนอกจากฝั่งผู้ให้บริการ ให้เปิดพอร์ตนั้นเพิ่มด้วย โดยจำกัดต้นทางเป็น IP เดียวกัน ดูพื้นฐาน Firewall เพิ่มที่ ตั้งค่า Firewall ด้วย UFW บน Ubuntu และ ตั้งค่า Firewall ด้วย firewalld บน AlmaLinux และ Rocky Linux
ขั้นตอนที่ 4: บังคับใช้การเชื่อมต่อแบบเข้ารหัส
ข้อมูลและรหัสผ่านที่วิ่งผ่านอินเทอร์เน็ตควรเข้ารหัสด้วย TLS เสมอ MySQL 8 สร้างใบรับรองและเปิด TLS ให้อัตโนมัติ จึงบังคับให้ผู้ใช้ต้องใช้ TLS ได้ทันที
ALTER USER 'appremote'@'203.0.113.10' REQUIRE SSL;MariaDB 10.x ไม่ได้เปิด TLS ไว้เป็นค่าเริ่มต้น ตรวจได้ด้วย SHOW VARIABLES LIKE 'have_ssl'; ถ้าได้ DISABLED ต้องสร้างใบรับรองและกำหนด ssl_cert, ssl_key และ ssl_ca ในไฟล์ตั้งค่าก่อน ตามเอกสาร "Securing Connections for Client and Server" ของ MariaDB มิฉะนั้นผู้ใช้ที่ตั้ง REQUIRE SSL จะเชื่อมต่อไม่ได้ หากยังไม่พร้อมตั้งค่า TLS ให้ใช้วิธีที่ 1 แทน