1 - Secure Database Communication
Implement secure communication channels between game servers and the database using encryption, certificate-based authentication, IP restrictions, and role-based access control.
Use Encrypted Connections (SSL/TLS)
-- MySQL: Enable SSL/TLS for database connections
# 1. Generate SSL certificates
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem
openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
# 2. Configure MySQL to use SSL
[mysqld]
ssl-ca=ca.pem
ssl-cert=server-cert.pem
ssl-key=server-key.pem
# 3. Connect using SSL
mysql --ssl-ca=ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem
-- PostgreSQL: Enable SSL/TLS for database connections
# 1. Generate SSL certificates
openssl req -new -text -out server.req
openssl rsa -in privkey.pem -modulus -noout -out modulus
openssl req -x509 -in server.req -text -key privkey.pem -out server.crt
chmod og-rwx privkey.pem
# 2. Configure PostgreSQL to use SSL
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'privkey.pem'
# 3. Connect using SSL
psql "host=localhost user=postgres sslmode=require"
Enforce Certificate-Based Authentication
-- MySQL: Configure certificate-based authentication
# 1. Generate client certificates
openssl req -newkey rsa:2048 -days 3600 -nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
# 2. Configure MySQL to use certificate-based authentication
[mysqld]
ssl-ca=ca.pem
ssl-cert=server-cert.pem
ssl-key=server-key.pem
[client]
ssl-ca=ca.pem
ssl-cert=client-cert.pem
ssl-key=client-key.pem
-- PostgreSQL: Configure certificate-based authentication
# 1. Generate client certificates
openssl req -new -text -out client.req
openssl rsa -in privkey.pem -modulus -noout -out modulus
openssl req -x509 -in client.req -text -key privkey.pem -out client.crt
# 2. Configure PostgreSQL to use certificate-based authentication
hostssl all all 0.0.0.0/0 cert clientcert=1
Restrict Database Access to Specific IP Addresses/Networks
-- MySQL: Restrict access to specific IP addresses/networks
CREATE USER 'game_server'@'192.168.1.100' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON fivem.* TO 'game_server'@'192.168.1.100';
-- PostgreSQL: Restrict access to specific IP addresses/networks (pg_hba.conf)
host fivem game_server 192.168.1.100/32 md5
Implement Database User Roles and Permissions
-- MySQL: Create roles and assign permissions
CREATE ROLE fivem_read_only, fivem_data_entry, fivem_manager;
GRANT SELECT ON fivem.* TO fivem_read_only;
GRANT INSERT ON fivem.player_data TO fivem_data_entry;
GRANT INSERT, UPDATE, DELETE ON fivem.* TO fivem_manager;
CREATE USER 'game_viewer'@'192.168.1.100' IDENTIFIED BY 'StrongPassword123!';
GRANT fivem_read_only TO 'game_viewer'@'192.168.1.100';
-- PostgreSQL: Create roles and assign permissions
CREATE ROLE fivem_read_only;
GRANT SELECT ON ALL TABLES IN SCHEMA fivem TO fivem_read_only;
CREATE ROLE fivem_data_entry;
GRANT INSERT ON fivem.player_data TO fivem_data_entry;
CREATE ROLE fivem_manager;
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA fivem TO fivem_manager;
CREATE USER game_viewer WITH PASSWORD 'StrongPassword123!';
GRANT fivem_read_only TO game_viewer;
2 - Database Server Hardening
Harden your database server by disabling unnecessary services, enabling firewalls, implementing strong authentication, and enabling auditing and logging.
Disable or Remove Unnecessary Services and Features
-- MySQL: Disable unnecessary components during installation
# For MySQL 8.0, add the following options during installation:
mysqld=--skip-profiling,--skip-perfschema
# For existing installations, you can disable components in the my.cnf file:
skip-perfschema
skip-profiling
# PostgreSQL: Disable unnecessary components during installation
# Add the following options to the postgresql.conf file:
shared_preload_libraries = '' # Disables all preloaded libraries
Enable Database Server’s Built-in Firewall
-- MySQL: Enable and configure the built-in firewall
# Enable the firewall
INSTALL SONAME 'MYSQLX_FIREWALL';
# Create a whitelist for allowed IP addresses
MYSQLX_FIREWALL_INSTALL(
'WHITELIST_INET',
'WHITELIST_USERS',
'client_ip=192.168.1.0/24,127.0.0.1, user=fivem_viewer,fivem_entry,fivem_admin'
);
# Start the firewall
MYSQLX_FIREWALL_ACTIVATE();
-- PostgreSQL: Enable and configure the built-in firewall (pg_hba.conf)
# Allow connections from specific IP addresses
host all all 192.168.1.0/24 md5
host all all 127.0.0.1/32 md5
# Deny all other connections
host all all 0.0.0.0/0 reject
Implement Strong Authentication and Least Privilege
-- Create users with strong passwords and assign roles
CREATE USER 'fivem_viewer'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT fivem_read_only TO 'fivem_viewer'@'localhost';
CREATE USER 'fivem_entry'@'localhost' IDENTIFIED BY 'AnotherStrongPass!';
GRANT fivem_data_entry TO 'fivem_entry'@'localhost';
CREATE USER 'fivem_admin'@'localhost' IDENTIFIED BY 'SuperSecurePass123!';
GRANT fivem_manager TO 'fivem_admin'@'localhost';
Enable Auditing and Logging
-- MySQL: Enable and configure audit logging
INSTALL SONAME 'server_audit';
SET GLOBAL server_audit_logging=ON;
SET GLOBAL server_audit_file_rotate_size=1000000; # Rotate log files at 1MB
SET GLOBAL server_audit_file_rotate_max_retained_files=10; # Keep 10 log files
-- Configure log events to capture
SET GLOBAL server_audit_events='CONNECT,QUERY';
-- PostgreSQL: Enable and configure logging
# Edit the postgresql.conf file
log_destination = 'csvlog'
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_truncate_on_rotation = off
log_rotation_age = 1d
log_rotation_size = 100000 # Rotate log files at 100MB
3 - Database Access Monitoring
Monitor database activities, implement intrusion detection/prevention systems, set up alerts for potential threats, and regularly review logs to ensure the security of your database.
Enable Database Activity Logging
-- MySQL: Enable and configure audit logging
INSTALL SONAME 'server_audit';
SET GLOBAL server_audit_logging=ON;
SET GLOBAL server_audit_file_rotate_size=1000000; # Rotate log files at 1MB
SET GLOBAL server_audit_file_rotate_max_retained_files=10; # Keep 10 log files
-- Configure log events to capture
SET GLOBAL server_audit_events='CONNECT,QUERY';
-- PostgreSQL: Enable and configure logging
# Edit the postgresql.conf file
log_destination = 'csvlog'
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_truncate_on_rotation = off
log_rotation_age = 1d
log_rotation_size = 100000 # Rotate log files at 100MB
Implement Intrusion Detection/Prevention Systems (IDS/IPS)
# Install and configure an IDS/IPS solution like Snort or Suricata
# Example for Snort on Ubuntu
sudo apt-get install snort
# Configure Snort to monitor database traffic
# Edit the snort.conf file
ipvar HOME_NET 192.168.1.0/24
ipvar EXTERNAL_NET !$HOME_NET
# Add rules to detect potential threats
include $RULE_PATH/mysql.rules
include $RULE_PATH/postgresql.rules
include $RULE_PATH/sql-injection.rules
# Start Snort in IDS mode
sudo snort -A console -q -u snort -g snort -c /etc/snort/snort.conf -i eth0
Set up Alerts for Potential Threats
-- MySQL: Set up alerts for failed login attempts and SQL injection
DELIMITER $$
CREATE TRIGGER failed_login_attempts_trigger
AFTER INSERT ON mysql.general_log
FOR EACH ROW
BEGIN
IF NEW.argument LIKE 'ACCESS DENIED%' THEN
INSERT INTO failed_login_attempts (user, host, timestamp)
VALUES (SUBSTRING_INDEX(NEW.argument, '@', 1),
SUBSTRING_INDEX(SUBSTRING_INDEX(NEW.argument, '@', -1), ']', 1),
NEW.event_time);
END IF;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER sql_injection_attempts_trigger
AFTER INSERT ON mysql.general_log
FOR EACH ROW
BEGIN
IF NEW.argument RLIKE '(^(\\\\\\\'|\\\'|\\%27|\')|\\b(union|select|insert|update|delete)\\b.*(\\b(from|into)\\b.*(\\b(information_schema|mysql|sys|data)\\b|\\bconcaten\\(|\\bchar\\())|\\b(outfile|load_file|into|dumpfile))' THEN
INSERT INTO sql_injection_attempts (user, host, query, timestamp)
VALUES (SUBSTRING_INDEX(NEW.argument, '@', 1),
SUBSTRING_INDEX(SUBSTRING_INDEX(NEW.argument, '@', -1), ']', 1),
NEW.argument,
NEW.event_time);
END IF;
END$$
DELIMITER ;
-- PostgreSQL: Set up alerts for failed login attempts and SQL injection
CREATE EXTENSION IF NOT EXISTS log_fdw;
CREATE SERVER log_server
FOREIGN DATA WRAPPER log_fdw
OPTIONS (filename '/var/log/postgresql/postgresql-%Y-%m-%d_%H%M%S.log');
CREATE TABLE failed_login_attempts (
username TEXT,
client_addr TEXT,
timestamp TIMESTAMP
);
CREATE RULE failed_login_alert AS
ON INSERT TO failed_login_attempts
WHERE NEW.username IS NOT NULL
DO NOTIFY failed_login_attempt,
E'Username: ' || NEW.username || E'\nClient Address: ' || NEW.client_addr || E'\nTimestamp: ' || NEW.timestamp;
CREATE VIEW failed_logins WITH (security_barrier) AS
SELECT
split_part(message, ' ', 10) AS username,
split_part(message, ' ', 11) AS client_addr,
timestamp
FROM pg_log.postgresql_log
WHERE message LIKE 'FATAL%password authentication failed for user%';
Regularly Review and Analyze Logs
# Analyze MySQL audit logs
sudo mysqlauditgrep --query-log=/var/log/mysql/audit.log --query-pam-ksok --query-has-comment-augment --query-has-sleep-augment --query-has-delay-augment
# Analyze PostgreSQL logs
sudo grep 'FATAL' /var/log/postgresql/*.log | awk '{print $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11}'
4 - Secure FiveM Server Database
Implement robust security measures to protect your FiveM server’s database from potential attacks and unauthorized access.
User Account Management
Principle of Least Privilege
-- Create roles for FiveM server operations
CREATE ROLE fivem_read_only, fivem_data_entry, fivem_manager;
-- Grant minimum required permissions to each role
GRANT SELECT ON fivem.* TO fivem_read_only;
GRANT INSERT ON fivem.player_data TO fivem_data_entry;
GRANT INSERT, UPDATE, DELETE ON fivem.* TO fivem_manager;
-- Create users and assign roles
CREATE USER 'fivem_viewer'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT fivem_read_only TO 'fivem_viewer'@'localhost';
CREATE USER 'fivem_entry'@'localhost' IDENTIFIED BY 'AnotherStrongPass!';
GRANT fivem_data_entry TO 'fivem_entry'@'localhost';
CREATE USER 'fivem_admin'@'localhost' IDENTIFIED BY 'SuperSecurePass123!';
GRANT fivem_manager TO 'fivem_admin'@'localhost';
Strong Password Policies
-- Enforce a strong password policy
SET GLOBAL validate_password.length=14;
SET GLOBAL validate_password.number_count=2;
SET GLOBAL validate_password.mixed_case_count=1;
SET GLOBAL validate_password.special_char_count=1;
SET GLOBAL validate_password.dictionary_file='/usr/share/mysql/english_dictionary.txt';
-- Update user password to comply with the new policy
ALTER USER 'fivem_viewer'@'localhost' IDENTIFIED BY 'N3wStr0ngPa$$word';
Multi-Factor Authentication (MFA)
-- Install the MFA plugin
INSTALL PLUGIN authentication_mfa SONAME 'authentication_mfa.so';
-- Create an MFA-enabled user account
CREATE USER 'fivem_superadmin'@'localhost' IDENTIFIED BY 'UltraSecurePass123!';
-- Configure MFA for the user, using a hardware security key
ALTER USER 'fivem_superadmin'@'localhost'
IDENTIFIED WITH authentication_mfa
BY 'initial_secret_key'
REQUIRE SECURE_REMOTE_USER;
Database Permissions
Role-Based Access Control (RBAC)
-- Create a role for FiveM server developers
CREATE ROLE fivem_developer;
GRANT SELECT, INSERT, UPDATE ON fivem.resources TO fivem_developer;
-- Assign the role to a user
GRANT fivem_developer TO 'dev_user'@'%';
Granular Permissions
-- Grant SELECT permission on specific tables
GRANT SELECT ON fivem.player_data, fivem.server_logs TO 'fivem_viewer'@'%';
-- Grant INSERT permission on specific columns
GRANT INSERT(name, score) ON fivem.player_scores TO 'fivem_entry'@'%';
Secure Database Objects
-- Create a stored procedure for inserting player scores
DELIMITER $$
CREATE PROCEDURE InsertPlayerScore(
IN p_name VARCHAR(50),
IN p_score INT
)
BEGIN
-- Input validation
IF p_score < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Score cannot be negative';
END IF;
-- Check if player exists
IF NOT EXISTS (SELECT 1 FROM player_data WHERE name = p_name) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Player does not exist';
END IF;
-- Insert score
INSERT INTO player_scores (name, score)
VALUES (p_name, p_score);
END$$
DELIMITER ;
-- Grant execute permission on the stored procedure
GRANT EXECUTE ON PROCEDURE InsertPlayerScore TO 'fivem_entry'@'%';
-- Create a view that masks sensitive player data
CREATE VIEW player_data_public AS
SELECT name, game_id, join_date
FROM player_data;
-- Grant SELECT permission on the view
GRANT SELECT ON player_data_public TO 'fivem_viewer'@'%';