Question

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

Hi,

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?


Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

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.

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in Q&A, subscribe to topics of interest, and get courses and tools that will help you grow as a developer and scale your project or business.

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 = digitalocean_certificate.cert.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 = ["0.0.0.0/0"]
  }

  inbound_rule {
    protocol         = "tcp"
    port_range       = "80"
    source_load_balancer_uids = [digitalocean_loadbalancer.public.id]
  }

  outbound_rule {
    protocol              = "tcp"
    port_range            = "80"
    destination_load_balancer_uids = [digitalocean_loadbalancer.public.id]
  }
}

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…