Restricting port 80 to private network with a cloud firewall, using terraform.

Posted January 10, 2020 2.1k views
NetworkingDigitalOcean Cloud FirewallsTerraform


I’m using terraform to provision an environment. But I’m running into an issue.

I’d like to terminate SSL on the LB, and then restrict port 80 on my 2 backend servers to only allow the LB to connect on the private network.

The problem I’m seeing with terraform is, there’s no way to define a private IP for the LB (no output, seems it only outputs the public IP).

Is there a way to at least restrict it to the private network CIDR without knowing it ahead of time?

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Submit an Answer
1 answer

There are a couple important things to know about how load balancers and firewalls work. First, from the load balancer docs:

The load balancer will connect to Droplets over the private network if it is enabled on the Droplets in question when they are added to the load balancer. If private networking is disabled, the load balancer will contact the Droplet using its public IP address.

And from the firewall docs:

Firewalls affect both public and private network traffic. Rules specific to either must specify the public or private IP range.

So if you have both enabled private networking on the Droplets and specified the load balancer in the firewall rules, communication will happen over the private network and be properly restricted.

The key thing is using source_load_balancer_uids and destination_load_balancer_uids to specify the load balancer rather than its public IP address.

So your Terraform configuration would (in part) look something like:

resource "digitalocean_droplet" "web" {
  count  = 2
  name   = format("web-%03d", count.index + 1)
  size   = "s-1vcpu-1gb"
  image  = "lemp-18-04"
  region = "nyc3"
  private_networking = true

resource "digitalocean_loadbalancer" "public" {
  name   = "loadbalancer-1"
  region = "nyc3"

  forwarding_rule {
    entry_port = 443
    entry_protocol = "https"

    target_port = 80
    target_protocol = "http"

    certificate_id =

  redirect_http_to_https = true

  healthcheck {
    port     = 22
    protocol = "tcp"

  droplet_ids = digitalocean_droplet.web[*].id

resource "digitalocean_firewall" "web" {
  name = "only-22-and-80-tolb"

  droplet_ids = digitalocean_droplet.web[*].id

  inbound_rule {
    protocol         = "tcp"
    port_range       = "22"
    source_addresses = [""]

  inbound_rule {
    protocol         = "tcp"
    port_range       = "80"
    source_load_balancer_uids = []

  outbound_rule {
    protocol              = "tcp"
    port_range            = "80"
    destination_load_balancer_uids = []

If I attempt to ping the Droplets or run nmap against them, I can see that port 80 is not accessible publicly nor from another Droplet using private networking while the load balancer is serving content as expected..