Back to blog
AWSBest PracticesCloud SecurityDatabasesNetworking

Redshift Using Default Port: Why 5439 Is a Liability and How to Fix It

Learn why Amazon Redshift clusters on the default port 5439 attract scanners, how to change the port safely, and how to prevent regressions with policy-as-code.

TL;DR

This check flags Redshift clusters listening on the default port 5439, a value attackers scan for by default. Move the cluster to a non-standard port and lock it down with tight security group rules to cut down on automated probing.

Amazon Redshift listens on TCP port 5439 out of the box. It is a small detail that ships with every cluster created from the console or API without an explicit override, and most teams never think to change it. That is exactly why it shows up on bot scan lists. The Redshift Using Default Port check looks at the Port value in your cluster's endpoint configuration and reports any cluster still sitting on 5439.

On its own, running on the default port is not a vulnerability. It is a low-friction indicator that your network surface follows the predictable path of least resistance, and predictable surfaces are the ones that get found first.


What this check detects

The check inspects each Redshift cluster in your account and reads the port assigned to its endpoint. If the value is 5439, the default, the cluster is flagged.

You can see the same value yourself with a quick describe call:

aws redshift describe-clusters \
  --query 'Clusters[*].{Cluster:ClusterIdentifier,Port:Endpoint.Port,VpcId:VpcId}' \
  --output table

Any row showing 5439 is what the check reports.

Note: The port lives on the cluster endpoint, not the underlying database. Clients connect to cluster-name.xxxxxx.region.redshift.amazonaws.com:5439, and that port is what determines which security group rules need to match.


Why it matters

Default ports are the first thing automated scanners check. Mass internet scanning tools like masscan and the data feeds behind services such as Shodan index well-known ports continuously. When a host responds on 5439, the scanner already knows it is talking to Redshift before it sends a single application packet. That saves the attacker a fingerprinting step and tells them precisely which exploits, credential lists, and connection tooling to reach for.

The real damage happens when a default port lines up with a permissive security group. We see this combination constantly: a cluster on 5439, a security group with 0.0.0.0/0 ingress added during a debugging session and never removed, and publicly accessible mode left on. Each piece is survivable alone. Together they put your entire data warehouse one credential-stuffing run away from exposure.

Changing the port does not make a cluster secure. It removes one of the cheapest signals an attacker uses to find and target it, which raises the cost of casual scanning and buys you time.

There is also a compliance angle. Several internal hardening baselines and CIS-style benchmarks call out default service ports as a configuration weakness. If you are audited against one of those, a fleet of 5439 clusters is an easy finding for a reviewer to write up.

Warning: Port obscurity is defense in depth, not a control on its own. Do not let a port change distract you from the things that actually keep data in: network isolation, private subnets, IAM-based authentication, and encryption.


How to fix it

Redshift lets you set the port at creation time. Changing it on an existing cluster is also supported, but it requires care because the endpoint and any dependent connection strings change with it.

Option 1: Set a non-default port at creation

When you provision a new cluster, pass an explicit --port. Pick something outside the well-known and registered ranges that scanners hammer, and document it for your team:

aws redshift create-cluster \
  --cluster-identifier analytics-prod \
  --node-type ra3.xlplus \
  --number-of-nodes 2 \
  --master-username admin \
  --manage-master-password \
  --db-name analytics \
  --port 54390 \
  --cluster-subnet-group-name private-redshift-subnets \
  --vpc-security-group-ids sg-0abc123def4567890 \
  --publicly-accessible false \
  --encrypted

Option 2: Modify an existing cluster

For a running cluster, use modify-cluster with the new port:

aws redshift modify-cluster \
  --cluster-identifier analytics-prod \
  --port 54390

Danger: A port change updates the cluster endpoint and triggers a brief connectivity interruption. Every client, BI tool, ETL job, and connection string pointing at 5439 will fail until updated. Treat this as a planned change with a maintenance window, not a quick console click on a busy production warehouse.

After the change, update the matching security group rule so traffic on the new port is allowed and the old rule is removed:

# Allow the new port from your internal CIDR
aws ec2 authorize-security-group-ingress \
  --group-id sg-0abc123def4567890 \
  --protocol tcp \
  --port 54390 \
  --cidr 10.0.0.0/16

# Remove the old 5439 rule once clients are migrated
aws ec2 revoke-security-group-ingress \
  --group-id sg-0abc123def4567890 \
  --protocol tcp \
  --port 5439 \
  --cidr 10.0.0.0/16

Option 3: Terraform

If you manage Redshift as code, set the port in the resource definition so it is consistent across every environment:

resource "aws_redshift_cluster" "analytics" {
  cluster_identifier  = "analytics-prod"
  node_type           = "ra3.xlplus"
  number_of_nodes     = 2
  database_name       = "analytics"
  master_username     = "admin"
  manage_master_password = true
  port                = 54390
  publicly_accessible = false
  encrypted           = true

  cluster_subnet_group_name = aws_redshift_subnet_group.private.name
  vpc_security_group_ids    = [aws_security_group.redshift.id]
}

resource "aws_security_group" "redshift" {
  name_prefix = "redshift-"
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 54390
    to_port     = 54390
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }
}

Tip: Define the port as a variable shared between the cluster and its security group. That way the ingress rule and the listener can never drift apart, which is the most common way a port change quietly breaks connectivity.


How to prevent it from happening again

Catching this once is easy. Keeping it from creeping back as people spin up new clusters is the harder part. Push the rule left into your pipeline so a default port never reaches production.

Block it in Terraform with a policy check

Using Open Policy Agent with Conftest, you can fail a plan that leaves the port unset or at 5439:

package redshift

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_redshift_cluster"
  port := object.get(resource.change.after, "port", 5439)
  port == 5439
  msg := sprintf("Redshift cluster '%s' uses default port 5439", [resource.address])
}

Wire that into CI so the check runs on every pull request:

terraform plan -out=tfplan
terraform show -json tfplan > plan.json
conftest test plan.json --policy policy/

Catch existing drift with AWS Config

For clusters created outside your IaC, an AWS Config custom rule that evaluates the endpoint port gives you ongoing detection across the account. Pair it with an SNS notification so a non-compliant cluster pages the right team rather than waiting for the next audit.

Tip: Lensix runs the redshift_defaultport check continuously across every region and account you connect, so you get drift detection without writing and maintaining Config rules yourself. Use the policy gate for prevention and Lensix for the catch-all.


Best practices

  • Treat the port as one layer, not the fix. Combine it with private subnets, publicly_accessible = false, and security groups scoped to known CIDRs or source security groups.
  • Standardize a port across environments. Pick one non-default value and use it everywhere through shared modules. Random per-cluster ports create connectivity confusion without adding meaningful security.
  • Never open Redshift to 0.0.0.0/0. If external access is genuinely required, front it with a bastion, VPN, or AWS PrivateLink rather than a public ingress rule.
  • Use IAM authentication and rotate credentials. A non-default port slows scanners, but strong auth is what stops them when they do find you.
  • Audit security group rules alongside the port change. A port move is the perfect moment to clean up stale ingress rules that have accumulated over the life of the cluster.
  • Document the chosen port in your runbook. The most common fallout from this fix is an on-call engineer who cannot connect because they assumed 5439.

Changing a port is a five-minute task that closes a free reconnaissance shortcut for attackers. Done as part of a wider network-hardening pass, it is one of the cheaper improvements you can make to a Redshift deployment.