RDSデータベースとクラスターのデフォルトポートの変更について

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、 「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、RDSデータベースとクラスターのデフォルトポート使用について、リスクと対策を解説します。

ポリシーの説明
RDSデータベースインスタンスやクラスターをデフォルトポート(MySQL/MariaDB: 3306、PostgreSQL: 5432、SQL Server: 1433、Oracle: 1521、Aurora MySQL: 3306、Aurora PostgreSQL: 5432)で運用することは、セキュリティ上の重大な脆弱性を生み出します。
デフォルトポートは世界中の攻撃者に広く知られており、自動化されたスキャニングツールやボットネットがこれらのポートを継続的に監視し、攻撃可能なデータベースを探しています。特に、パブリッククラウド環境では、セキュリティグループの設定ミスにより、意図せずインターネットに公開されるリスクがあります。
カスタムポートの使用は「多層防御(Defense in Depth)」戦略の重要な要素であり、「Security through Obscurity」だけに依存するものではありませんが、他のセキュリティ対策と組み合わせることで、データベースへの不正アクセスのリスクを大幅に低減できます。
修復手順
AWS Management Consoleでの修復手順
RDSインスタンスのポート変更
- AWS Management Consoleにログイン
- RDSダッシュボードに移動
- 対象のDBインスタンスを選択
- データベース一覧から変更対象を選択
- 「変更」ボタンをクリック
- 接続とセキュリティの設定
- 「追加設定」セクションを展開
- 「データベースポート」フィールドでカスタムポート番号を入力
- 推奨ポート範囲:
- ユーザーポート: 1024-49151(IANA登録済みポートを避ける)
- 動的/プライベートポート: 49152-65535(推奨)
- 避けるべきポート: 8080, 8443, 9000番台(一般的なアプリケーションポート)
- 変更の適用タイミングを選択
- 「すぐに適用」または「次のメンテナンスウィンドウ中に適用」を選択
- 本番環境では計画的なメンテナンスウィンドウでの適用を推奨
- 注意: ポート変更にはデータベースの再起動が必要(ダウンタイム: 約1-3分)
- セキュリティグループの更新
- 関連するセキュリティグループを編集
- インバウンドルールを新しいポート番号に更新
- 古いポートのルールを削除
Aurora クラスターのポート変更
- クラスターの変更
- RDSコンソールでAuroraクラスターを選択
- 「変更」をクリック
- ポート設定の変更
- 「ネットワークとセキュリティ」セクションで新しいポート番号を入力
- クラスター内の全インスタンスに適用される
AWS CLIでの修復手順
# 1. 現在の設定確認
aws rds describe-db-instances \
--db-instance-identifier <db-instance-id> \
--query 'DBInstances[0].[DBInstanceIdentifier,Endpoint.Port,DBInstanceStatus]' \
--output table
# 2. RDSインスタンスのポート変更(即時適用)
aws rds modify-db-instance \
--db-instance-identifier <db-instance-id> \
--db-port-number 23306 \
--apply-immediately
# またはメンテナンスウィンドウで適用
aws rds modify-db-instance \
--db-instance-identifier <db-instance-id> \
--db-port-number 23306 \
--no-apply-immediately
# 3. Aurora クラスターのポート変更
aws rds modify-db-cluster \
--db-cluster-identifier <cluster-id> \
--port 25432 \
--apply-immediately
# クラスターインスタンスの確認
aws rds describe-db-clusters \
--db-cluster-identifier <cluster-id> \
--query 'DBClusters[0].DBClusterMembers[*].DBInstanceIdentifier' \
--output table
# 4. セキュリティグループの更新
# 新しいポートのルール追加(特定のセキュリティグループからのみ許可)
aws ec2 authorize-security-group-ingress \
--group-id <security-group-id> \
--protocol tcp \
--port 23306 \
--source-group <source-security-group-id> \
--group-owner <account-id>
# IPアドレスベースの場合(VPN経由など)
aws ec2 authorize-security-group-ingress \
--group-id <security-group-id> \
--protocol tcp \
--port 23306 \
--cidr 10.0.0.0/8 \
--description "Database access from internal network"
# 古いポートのルール削除(確認後)
aws ec2 revoke-security-group-ingress \
--group-id <security-group-id> \
--protocol tcp \
--port 3306 \
--source-group <source-security-group-id>
# 5. 変更の確認
aws rds describe-db-instances \
--db-instance-identifier <db-instance-id> \
--query 'DBInstances[0].PendingModifiedValues'
# 6. 接続テスト(各データベースエンジン別)
# MySQL/MariaDB
mysql -h <endpoint> -P 23306 -u <username> -p
# PostgreSQL
psql -h <endpoint> -p 25432 -U <username> -d <database>
# SQL Server
sqlcmd -S <endpoint>,21433 -U <username> -P <password>
# Oracle
sqlplus <username>/<password>@<endpoint>:21521/<service_name>
Terraformでの修復手順
# カスタムポートを使用したRDSインスタンス
resource "aws_db_instance" "database" {
identifier = var.db_instance_identifier
allocated_storage = var.allocated_storage
storage_type = "gp3"
engine = "mysql"
engine_version = "8.0.35"
instance_class = var.instance_class
db_name = var.database_name
username = var.master_username
password = var.master_password
# カスタムポートの設定(本番環境推奨値)
port = var.db_port != null ? var.db_port : 23306
# セキュリティ設定
vpc_security_group_ids = [aws_security_group.rds.id]
db_subnet_group_name = aws_db_subnet_group.database.name
# バックアップ設定
backup_retention_period = 30
backup_window = "03:00-04:00"
maintenance_window = "sun:04:00-sun:05:00"
# 暗号化設定
storage_encrypted = true
kms_key_id = aws_kms_key.rds.arn
# 監査設定
enabled_cloudwatch_logs_exports = ["error", "general", "slowquery"]
# その他の設定
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "${var.db_instance_identifier}-final-snapshot-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
tags = merge(
var.common_tags,
{
Name = var.db_instance_identifier
Port = "Custom"
}
)
}
# Aurora クラスターの設定
resource "aws_rds_cluster" "aurora" {
cluster_identifier = var.cluster_identifier
engine = "aurora-mysql"
engine_version = "8.0.mysql_aurora.3.04.0"
database_name = var.database_name
master_username = var.master_username
master_password = var.master_password
# カスタムポートの設定(Auroraクラスター)
port = var.aurora_port != null ? var.aurora_port : 25432
# ネットワーク設定
db_subnet_group_name = aws_db_subnet_group.aurora.name
vpc_security_group_ids = [aws_security_group.aurora.id]
# バックアップ設定
backup_retention_period = 35
preferred_backup_window = "03:00-04:00"
preferred_maintenance_window = "sun:04:00-sun:05:00"
# 暗号化設定
storage_encrypted = true
kms_key_id = aws_kms_key.aurora.arn
# 監査とログ設定
enabled_cloudwatch_logs_exports = ["audit", "error", "general", "slowquery"]
# 削除保護
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "${var.cluster_identifier}-final-${formatdate("YYYY-MM-DD-hhmm", timestamp())}"
tags = var.common_tags
}
# セキュリティグループの設定
resource "aws_security_group" "rds" {
name_prefix = "${var.environment}-rds-sg"
description = "Security group for RDS instance with custom port"
vpc_id = var.vpc_id
# カスタムポートでのアクセス許可(動的設定)
ingress {
description = "Database access from application layer on custom port"
from_port = var.db_port
to_port = var.db_port
protocol = "tcp"
security_groups = [aws_security_group.app.id]
}
# タグでポート情報を管理(セキュリティ上、値は隠蔽)
tags = merge(
var.common_tags,
{
Name = "${var.environment}-rds-sg"
CustomPort = "Enabled"
}
)
# アウトバウンドルール
egress {
description = "Allow all outbound traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = merge(
var.common_tags,
{
Name = "${var.environment}-rds-sg"
}
)
lifecycle {
create_before_destroy = true
}
}
# ポート番号の変数定義(セキュリティ強化版)
variable "db_port" {
description = "Custom port for database connection"
type = number
default = null # 意図的にデフォルト値を設定しない
sensitive = true # ポート番号をログに出力しない
validation {
condition = var.db_port == null || (
var.db_port >= 49152 &&
var.db_port <= 65535 &&
!contains([3306, 5432, 1433, 1521, 3389, 22, 23, 25, 80, 443, 8080, 8443], var.db_port)
)
error_message = "Database port must be between 49152-65535 (dynamic/private range) and not a commonly used port."
}
}
# 環境別設定の例(ランダム化を含む)
resource "random_integer" "db_port" {
min = 49152
max = 65535
keepers = {
# インスタンスIDが変わった場合のみポートを再生成
instance_id = var.db_instance_identifier
}
}
locals {
# 環境ごとに異なるポートレンジを使用
port_mapping = {
production = {
mysql = 50000 + random_integer.db_port.result % 1000
postgresql = 51000 + random_integer.db_port.result % 1000
sqlserver = 52000 + random_integer.db_port.result % 1000
oracle = 53000 + random_integer.db_port.result % 1000
}
staging = {
mysql = 54000 + random_integer.db_port.result % 1000
postgresql = 55000 + random_integer.db_port.result % 1000
sqlserver = 56000 + random_integer.db_port.result % 1000
oracle = 57000 + random_integer.db_port.result % 1000
}
development = {
mysql = 58000 + random_integer.db_port.result % 1000
postgresql = 59000 + random_integer.db_port.result % 1000
sqlserver = 60000 + random_integer.db_port.result % 1000
oracle = 61000 + random_integer.db_port.result % 1000
}
}
# 選択されたポートをSecrets Managerに保存
db_config = {
engine = var.db_engine
port = local.port_mapping[var.environment][var.db_engine]
endpoint = aws_db_instance.database.endpoint
}
}
最後に
この記事では、RDSデータベースとクラスターのデフォルトポート使用について、リスクと対策を解説しました。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。