Answers: <p>So, for anyone else who stumbles across this, the ACLs don't know that the SYN-ACK packets coming back from a connection initiated from within an EC2 is traffic that is related to that connection (stateless).</p>
  <p>This means you can't just <code>apt update &amp;&amp; apt dist-upgrade -y</code> without first opening <code>0/0</code> on the inbound side of the ACL.</p>
  
Answers: CC BY-SA 4.0
Answers: 2024-11-26T15:16:16.423Z
Answers: Security groups are supposed to be statefull (cf https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html). So I guess your problem is more about an asymetric routing.
Answers: Tensibai
Answers: CC BY-SA 4.0
Answers: 2024-02-29T19:01:03.523Z
Answers: 2024-02-29T19:01:03.523Z
Answers: Nstevens
Body: <p>I've applied the terraform code below (<code>variables.tf</code> and <code>main.tf</code> are, of course, separate IRL) to setup an AWS <code>VPC</code>, private and public subnets, routes, NAT gateway, Internet Gateway, Network ACLs, an EC2 instance (in the public subnet) with a Security Group attached.</p>
  <p>I can ssh into the EC2 just fine, but <code>apt update</code> won't complete. <code>tcpdump</code> shows <code>SYN</code> packets going out <code>eth0</code> but nothing coming back. DNS resolution works, and I can ping <code>10.12.100.1</code> which is something upstream from <code>eth0</code>, I'm not sure what, but that's about it. The EC2 has a private IP on <code>eth0</code> which is in the <code>10.12.100.x</code> CIDR and an IPv6 address which god only knows what IP is on that.</p>
  <p>I've spent the better part of a day redoing <code>aws_route</code> and <code>aws_route_table</code> resources trying to figure out if I have something wrong there and comparing my resources to the terraform <code>vpc</code> module code and I just can't figure it out.</p>
  <p>It seems like it should be an <code>SG</code> or <code>ACL</code> issue but when I look at those configurations in the AWS console, they are as configured, and allowing all egress traffic.</p>
  <p>Anyone know what's missing, or how I can troubleshoot this more efficiently?
  Thanks</p>
  <pre><code>############################################################################# 
  #                         variables.tf 
  #############################################################################
  
  variable &quot;aws_region&quot; {
    description = &quot;AWS region where resources will be created&quot;
    type        = string
    default     = &quot;us-east-2&quot;
  }
  
  variable &quot;project&quot; {
    description = &quot;Project tag value for resources&quot;
    type        = string
    default     = &quot;vpc-test&quot;
  }
  
  variable &quot;environment&quot; {
    description = &quot;Environment tag value for resources&quot;
    type        = string
    default     = &quot;test&quot;
  }
  
  variable &quot;owner&quot; {
    description = &quot;The owner of the project&quot;
    type        = string
    default     = &quot;xyz&quot;  # initials
  }
  
  variable &quot;ssh_pub_key&quot; {
    description = &quot;pubkey of the SSH key pair for EC2 instances&quot;
    type        = string
    default     = &quot;ssh-ed25519 AAAAC...9&quot;
  }
  
  variable &quot;ingress_cidr_blocks&quot; {
    description = &quot;CIDR blocks to allow for ingress traffic&quot;
    type        = list(string)
    default     = [&quot;63.9.0.0/16&quot;, &quot;64.10.1.1/32&quot;]  
  }
  
  variable &quot;vpc_dns_support&quot; {
    description = &quot;Enable DNS support for the VPC&quot;
    type        = bool
    default     = true
  }
  
  variable &quot;vpc_dns_hostnames&quot; {
    description = &quot;Enable DNS hostnames for the VPC&quot;
    type        = bool
    default     = true
  }
  
  variable &quot;vpc_cidr_block&quot; {
    description = &quot;IPv4 CIDR block for the VPC&quot;
    type        = string
    default     = &quot;10.12.0.0/16&quot;
  }
  
  variable &quot;subnet_cidr_public&quot; {
    description = &quot;CIDR block for the public end of the subnet&quot;
    type        = string
    default     = &quot;10.12.100.0/24&quot;
  }
  
  variable &quot;subnet_cidr_private&quot; {
    description = &quot;CIDR block for the private end of the subnet&quot;
    type        = string
    default     = &quot;10.12.1.0/24&quot;
  }
  
  variable &quot;availability_zone&quot; {
    description = &quot;Availability zone for the subnet&quot;
    type        = string
    default     = &quot;us-east-2a&quot;
  }
  
  variable &quot;instance_type&quot; {
    description = &quot;EC2 instance type&quot;
    type        = string
    default     = &quot;t2.micro&quot;  # Free tier - could be a policy in spacelift
  }
  
  variable &quot;ami_instance&quot; {
    description  = &quot;AMI Instance identifier&quot;
    type         = string
    default      = &quot;ami-024e6efaf93d85776&quot; # Ubuntu 22.04 Server in us-east-2
  }
  
  
  variable &quot;ec2_webserver_data&quot; {
    description = &quot;User data script to initialize EC2 instances&quot;
    type        = string
    default     = &lt;&lt;-EOF
      #!/bin/bash
  
      test ! -d /var/www/html &amp;&amp; mkdir -p /var/www/html
  
      # Update package repositories and install tmux and vim
      apt-get update -y
      apt-get install apache2 tmux vim dig -y
      
      echo &quot;&lt;b&gt;Private appserver instance B&lt;/b&gt;&quot; &gt; /var/www/html/index.html
      systemctl enable apache2
  
      # Disable web caching in apache config so subsequent page loads don't conflict 
      cat &lt;&lt;EOT &gt;&gt; /etc/apache2/apache2.conf
      &lt;Directory /var/www/html&gt;
          &lt;IfModule mod_headers.c&gt;
              Header unset ETag
              Header set Cache-Control &quot;max-age=0, no-cache, no-store, must-revalidate&quot;
              Header set Pragma &quot;no-cache&quot;
              Header set Expires &quot;Wed, 11 Jan 1984 05:00:00 GMT&quot;
          &lt;/IfModule&gt;
      &lt;/Directory&gt;
      EOT               
  
      systemctl start apache2       
      EOF
  }
  
  variable &quot;ec2_std_data&quot; {
    description = &quot;User data script to initialize EC2 instances&quot;
    type        = string
    default     = &lt;&lt;-EOF
      #!/bin/bash
  
      # Update package repositories and install tmux and vim
      apt-get update -y
      apt-get install apache2 tmux vim dig -y
      EOF
  }
  
  
  ############################################################################# 
  #                         main.tf 
  #############################################################################
  
  
  # Define the provider (AWS)
  provider &quot;aws&quot; {
    region = var.aws_region
  }
  
  
  # the ssh pub key to use --  get from environment variable TV_VAR_ssh_pub_key
  resource &quot;aws_key_pair&quot; &quot;my_key_pair&quot; {
    key_name   = &quot;${var.project}-key-pair&quot;  # Replace with the desired key name
    public_key = var.ssh_pub_key
  }
  
  
  
  # VPC 
  resource &quot;aws_vpc&quot; &quot;my_vpc&quot; {
    cidr_block           = var.vpc_cidr_block
    enable_dns_support   = var.vpc_dns_support
    enable_dns_hostnames = var.vpc_dns_hostnames
  
    tags = {
      Name        = &quot;${var.project}-TEST-VPC&quot;
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  
  # private subnet within the VPC
  resource &quot;aws_subnet&quot; &quot;private_subnet&quot; {
    vpc_id                  = aws_vpc.my_vpc.id
    cidr_block              = var.subnet_cidr_private
    availability_zone       = var.availability_zone
    map_public_ip_on_launch = false
  
    tags = {
      Name        = &quot;${var.project}-PRIV-SUB&quot;
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  # public subnet within VPC
  resource &quot;aws_subnet&quot; &quot;public_subnet&quot; {
    vpc_id                  = aws_vpc.my_vpc.id
    cidr_block              = var.subnet_cidr_public
    availability_zone       = var.availability_zone
    map_public_ip_on_launch = true     # For public subnet
  
    tags = {
      Name        = &quot;${var.project}-PUB-SUB&quot;
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  
  resource &quot;aws_network_acl&quot; &quot;priv_sub_acl&quot; {
    vpc_id      = aws_vpc.my_vpc.id
    subnet_ids  = [aws_subnet.private_subnet.id]
  
    # Define ingress for trusted networks
    ingress {
      rule_no       = 100
      protocol      = &quot;-1&quot;
      action        = &quot;allow&quot;
      cidr_block    = aws_vpc.my_vpc.cidr_block
      from_port     = 0
      to_port       = 0
    }
  
    # Define ingress (inbound) rules
    egress {
      rule_no       = 100
      protocol      = &quot;-1&quot;
      action        = &quot;allow&quot;
      cidr_block    = &quot;0.0.0.0/0&quot;
      from_port     = 0
      to_port       = 0
    }
    
    # Tags
    tags = {
      Name          = &quot;${var.project}-PRIV-ACL&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  
  resource &quot;aws_network_acl&quot; &quot;pub_sub_acl&quot; {
    vpc_id      = aws_vpc.my_vpc.id
    subnet_ids  = [aws_subnet.public_subnet.id]
  
    # allow trusted networks ingress
    ingress {
      rule_no       = 100
      protocol      = &quot;-1&quot;
      action        = &quot;allow&quot;
      cidr_block    = var.ingress_cidr_blocks[0]
      from_port     = 0
      to_port       = 0
    }
  
    # dynamic config for multiple elements of var.ingress_cidr_blocks
    dynamic &quot;ingress&quot; {
      for_each  = range(length(var.ingress_cidr_blocks))
      iterator = i
      content {
        rule_no       = 100 + i.value * 100
        protocol      = &quot;-1&quot;
        action        = &quot;allow&quot;
        cidr_block    = var.ingress_cidr_blocks[i.value]
        from_port     = 0
        to_port       = 0
      }
    }
  
    # Define egress
    egress {
      rule_no       = 100
      protocol      = &quot;-1&quot;
      action        = &quot;allow&quot;
      cidr_block    = &quot;0.0.0.0/0&quot;
      from_port     = 0
      to_port       = 0
    }
  
    # Define IPv6 egress rule
    egress {
      rule_no             = 101
      protocol            = &quot;-1&quot;
      action              = &quot;allow&quot;
      ipv6_cidr_block     = &quot;::/0&quot;  # IPv6 CIDR block
      from_port           = 0
      to_port             = 0
    }
    
    # Tags
    tags = {
      Name          = &quot;${var.project}-PUB-ACL&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  
  
  # Create an Internet Gateway
  resource &quot;aws_internet_gateway&quot; &quot;my_igw&quot; {
    vpc_id       = aws_vpc.my_vpc.id
  
    tags = {
      Name        = &quot;${var.project}-IGW&quot;
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  # Elastic IP for the NAT Gateway
  resource &quot;aws_eip&quot; &quot;nat_eip&quot; {
    domain           = &quot;vpc&quot;
  
    # Tags
    tags = {
      Name          = &quot;${var.project}-NATG-EIP&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  # NAT Gateway in the public subnet for private resources to reach internet resources
  resource &quot;aws_nat_gateway&quot; &quot;my_natg&quot; {
    allocation_id     = aws_eip.nat_eip.id
    subnet_id         = aws_subnet.public_subnet.id  #&lt; NATG needs to reside in pub sub
  
    # Tags
    tags = {
      Name          = &quot;${var.project}-NATG&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }  
    
    depends_on = [aws_internet_gateway.my_igw]
  }
  
  
  # route for private subnet - uses NATG
  resource &quot;aws_route_table&quot; &quot;private_route_table&quot; {
    vpc_id = aws_vpc.my_vpc.id
  
    route {
      cidr_block = &quot;0.0.0.0/0&quot;
      nat_gateway_id = aws_nat_gateway.my_natg.id
    }
  
    tags = {
     Name = &quot;${var.project}-PRIV-RT&quot;
      Environment = var.environment
      Project     = var.project
      Owner       = var.owner
    }
  }
  
  # route to internet for vpc resources
  resource &quot;aws_route_table&quot; &quot;public_route_table&quot; {
    vpc_id = aws_vpc.my_vpc.id
  
    route {
        cidr_block = &quot;0.0.0.0/0&quot;
        gateway_id = aws_internet_gateway.my_igw.id
    }
  
    tags = {
      Name        = &quot;${var.project}-PUB-RT&quot;
      Environment = var.environment
      Project     = var.project
      Owner       = var.owner
    }
  }
  
  
  resource &quot;aws_default_route_table&quot; &quot;default_route_table&quot; {
    default_route_table_id = aws_vpc.my_vpc.default_route_table_id
  
    tags = {
      Name        = &quot;${var.project}-DEF-RT&quot;
      Environment = var.environment
      Project     = var.project
      Owner       = var.owner
    }
  }
  
  
  # Associate pubsub with pub route
  resource &quot;aws_route_table_association&quot; &quot;public_association&quot; {
    subnet_id      = aws_subnet.public_subnet.id
    route_table_id = aws_route_table.public_route_table.id
    
    # no tags
  }
  
  # Associate privsub with priv route
  resource &quot;aws_route_table_association&quot; &quot;private_association&quot; {
    subnet_id      = aws_subnet.private_subnet.id
    route_table_id = aws_route_table.private_route_table.id
  
    # no tags
  }
  
  
  # Define a security group to allow incoming SSH traffic (adjust rules as needed)
  resource &quot;aws_security_group&quot; &quot;ec2_sg&quot; {
    name                = &quot;${var.project}-SG&quot;
    description         = &quot;Security group allowing SSH traffic from campus only, egress anywhere&quot;
    vpc_id              = aws_vpc.my_vpc.id 
  
    # Ingress rule for SSH
    ingress {
      from_port         = 22
      to_port           = 22
      protocol          = &quot;tcp&quot;
      cidr_blocks       = var.ingress_cidr_blocks
    }
  
    # Egress rule for all IPv4 traffic anywhere
    egress {
      from_port         = 0
      to_port           = 0
      protocol          = &quot;-1&quot;
      cidr_blocks       = [&quot;0.0.0.0/0&quot;]
    }
  
    # Egress rule for all IPv6 traffic anywhere
    egress {
      from_port         = 0
      to_port           = 0
      protocol          = &quot;-1&quot;
      ipv6_cidr_blocks  = [&quot;::/0&quot;]
    }
  
    # Tags
    tags = {
      Name          = &quot;${var.project}-EC2-SG&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  
  /*
  
  # Create an EC2 instance in privsub
  resource &quot;aws_instance&quot; &quot;my_ec2_instance&quot; {
    ami                     = var.ami_instance
    instance_type           = var.instance_type
    key_name                = aws_key_pair.my_key_pair.key_name
    user_data               = var.ec2_std_data
    vpc_security_group_ids  = [aws_security_group.ec2_sg.id]
    subnet_id               = aws_subnet.private_subnet.id
  
    metadata_options {
      http_tokens          = &quot;required&quot;
    }
  
    # Tags
    tags = {
      Name          = &quot;${var.project}-priv1-ec2&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
  
    }
  }
  
  
  # Create a second EC2 instance in privsub
  resource &quot;aws_instance&quot; &quot;my_ec2_instance_b&quot; {
    ami                     = var.ami_instance
    instance_type           = var.instance_type
    key_name                = aws_key_pair.my_key_pair.key_name
    user_data               = var.ec2_std_data
    vpc_security_group_ids  = [aws_security_group.ec2_sg.id]
    subnet_id               = aws_subnet.private_subnet.id
  
    metadata_options {
      http_tokens          = &quot;required&quot;
    }
  
  
    # Tags
    tags = {
      Name          = &quot;${var.project}-priv2-ec2&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  */
  
  
  # Create a second EC2 instance in pubsub
  resource &quot;aws_instance&quot; &quot;my_ec2_instance_c&quot; {
    ami                     = var.ami_instance
    instance_type           = var.instance_type
    key_name                = aws_key_pair.my_key_pair.key_name  # Reference the key name from the aws_key_pair 
    user_data               = var.ec2_webserver_data
    vpc_security_group_ids  = [aws_security_group.ec2_sg.id]
    subnet_id               = aws_subnet.public_subnet.id
  
    metadata_options {
      http_tokens          = &quot;required&quot;
    }
  
    # Tags
    tags = {
      Name          = &quot;${var.project}-pub1-ec2&quot;
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  </code></pre>
  
Tags: <amazon-web-services>
Title: EC2 can't get to internet? SG and ACL seem OK
UserDisplayName: Nstevens
ThreadText: # EC2 can't get to internet? SG and ACL seem OK
  
  (Asked by: username_0 on 2024-02-29)
  
  I've applied the terraform code below (`variables.tf` and `main.tf` are, of course, separate IRL) to setup an AWS `VPC`, private and public subnets, routes, NAT gateway, Internet Gateway, Network ACLs, an EC2 instance (in the public subnet) with a Security Group attached.
  
  I can ssh into the EC2 just fine, but `apt update` won't complete. `tcpdump` shows `SYN` packets going out `eth0` but nothing coming back. DNS resolution works, and I can ping `10.12.100.1` which is something upstream from `eth0`, I'm not sure what, but that's about it. The EC2 has a private IP on `eth0` which is in the `10.12.100.x` CIDR and an IPv6 address which god only knows what IP is on that.
  
  I've spent the better part of a day redoing `aws_route` and `aws_route_table` resources trying to figure out if I have something wrong there and comparing my resources to the terraform `vpc` module code and I just can't figure it out.
  
  It seems like it should be an `SG` or `ACL` issue but when I look at those configurations in the AWS console, they are as configured, and allowing all egress traffic.
  
  Anyone know what's missing, or how I can troubleshoot this more efficiently?
  Thanks
  
  ```
  ############################################################################# 
  #                         variables.tf 
  #############################################################################
  
  variable "aws_region" {
    description = "AWS region where resources will be created"
    type        = string
    default     = "us-east-2"
  }
  
  variable "project" {
    description = "Project tag value for resources"
    type        = string
    default     = "vpc-test"
  }
  
  variable "environment" {
    description = "Environment tag value for resources"
    type        = string
    default     = "test"
  }
  
  variable "owner" {
    description = "The owner of the project"
    type        = string
    default     = "xyz"  # initials
  }
  
  variable "ssh_pub_key" {
    description = "pubkey of the SSH key pair for EC2 instances"
    type        = string
    default     = "ssh-ed25519 AAAAC...9"
  }
  
  variable "ingress_cidr_blocks" {
    description = "CIDR blocks to allow for ingress traffic"
    type        = list(string)
    default     = ["63.9.0.0/16", "64.10.1.1/32"]  
  }
  
  variable "vpc_dns_support" {
    description = "Enable DNS support for the VPC"
    type        = bool
    default     = true
  }
  
  variable "vpc_dns_hostnames" {
    description = "Enable DNS hostnames for the VPC"
    type        = bool
    default     = true
  }
  
  variable "vpc_cidr_block" {
    description = "IPv4 CIDR block for the VPC"
    type        = string
    default     = "10.12.0.0/16"
  }
  
  variable "subnet_cidr_public" {
    description = "CIDR block for the public end of the subnet"
    type        = string
    default     = "10.12.100.0/24"
  }
  
  variable "subnet_cidr_private" {
    description = "CIDR block for the private end of the subnet"
    type        = string
    default     = "10.12.1.0/24"
  }
  
  variable "availability_zone" {
    description = "Availability zone for the subnet"
    type        = string
    default     = "us-east-2a"
  }
  
  variable "instance_type" {
    description = "EC2 instance type"
    type        = string
    default     = "t2.micro"  # Free tier - could be a policy in spacelift
  }
  
  variable "ami_instance" {
    description  = "AMI Instance identifier"
    type         = string
    default      = "ami-024e6efaf93d85776" # Ubuntu 22.04 Server in us-east-2
  }
  
  variable "ec2_webserver_data" {
    description = "User data script to initialize EC2 instances"
    type        = string
    default     = <<-EOF
      #!/bin/bash
  
      test ! -d /var/www/html && mkdir -p /var/www/html
  
      # Update package repositories and install tmux and vim
      apt-get update -y
      apt-get install apache2 tmux vim dig -y
      
      echo "<b>Private appserver instance B</b>" > /var/www/html/index.html
      systemctl enable apache2
  
      # Disable web caching in apache config so subsequent page loads don't conflict 
      cat <<EOT >> /etc/apache2/apache2.conf
      <Directory /var/www/html>
          <IfModule mod_headers.c>
              Header unset ETag
              Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
              Header set Pragma "no-cache"
              Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
          </IfModule>
      </Directory>
      EOT               
  
      systemctl start apache2       
      EOF
  }
  
  variable "ec2_std_data" {
    description = "User data script to initialize EC2 instances"
    type        = string
    default     = <<-EOF
      #!/bin/bash
  
      # Update package repositories and install tmux and vim
      apt-get update -y
      apt-get install apache2 tmux vim dig -y
      EOF
  }
  
  ############################################################################# 
  #                         main.tf 
  #############################################################################
  
  # Define the provider (AWS)
  provider "aws" {
    region = var.aws_region
  }
  
  # the ssh pub key to use --  get from environment variable TV_VAR_ssh_pub_key
  resource "aws_key_pair" "my_key_pair" {
    key_name   = "${var.project}-key-pair"  # Replace with the desired key name
    public_key = var.ssh_pub_key
  }
  
  # VPC 
  resource "aws_vpc" "my_vpc" {
    cidr_block           = var.vpc_cidr_block
    enable_dns_support   = var.vpc_dns_support
    enable_dns_hostnames = var.vpc_dns_hostnames
  
    tags = {
      Name        = "${var.project}-TEST-VPC"
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  # private subnet within the VPC
  resource "aws_subnet" "private_subnet" {
    vpc_id                  = aws_vpc.my_vpc.id
    cidr_block              = var.subnet_cidr_private
    availability_zone       = var.availability_zone
    map_public_ip_on_launch = false
  
    tags = {
      Name        = "${var.project}-PRIV-SUB"
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  # public subnet within VPC
  resource "aws_subnet" "public_subnet" {
    vpc_id                  = aws_vpc.my_vpc.id
    cidr_block              = var.subnet_cidr_public
    availability_zone       = var.availability_zone
    map_public_ip_on_launch = true     # For public subnet
  
    tags = {
      Name        = "${var.project}-PUB-SUB"
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  resource "aws_network_acl" "priv_sub_acl" {
    vpc_id      = aws_vpc.my_vpc.id
    subnet_ids  = [aws_subnet.private_subnet.id]
  
    # Define ingress for trusted networks
    ingress {
      rule_no       = 100
      protocol      = "-1"
      action        = "allow"
      cidr_block    = aws_vpc.my_vpc.cidr_block
      from_port     = 0
      to_port       = 0
    }
  
    # Define ingress (inbound) rules
    egress {
      rule_no       = 100
      protocol      = "-1"
      action        = "allow"
      cidr_block    = "0.0.0.0/0"
      from_port     = 0
      to_port       = 0
    }
    
    # Tags
    tags = {
      Name          = "${var.project}-PRIV-ACL"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  resource "aws_network_acl" "pub_sub_acl" {
    vpc_id      = aws_vpc.my_vpc.id
    subnet_ids  = [aws_subnet.public_subnet.id]
  
    # allow trusted networks ingress
    ingress {
      rule_no       = 100
      protocol      = "-1"
      action        = "allow"
      cidr_block    = var.ingress_cidr_blocks[0]
      from_port     = 0
      to_port       = 0
    }
  
    # dynamic config for multiple elements of var.ingress_cidr_blocks
    dynamic "ingress" {
      for_each  = range(length(var.ingress_cidr_blocks))
      iterator = i
      content {
        rule_no       = 100 + i.value * 100
        protocol      = "-1"
        action        = "allow"
        cidr_block    = var.ingress_cidr_blocks[i.value]
        from_port     = 0
        to_port       = 0
      }
    }
  
    # Define egress
    egress {
      rule_no       = 100
      protocol      = "-1"
      action        = "allow"
      cidr_block    = "0.0.0.0/0"
      from_port     = 0
      to_port       = 0
    }
  
    # Define IPv6 egress rule
    egress {
      rule_no             = 101
      protocol            = "-1"
      action              = "allow"
      ipv6_cidr_block     = "::/0"  # IPv6 CIDR block
      from_port           = 0
      to_port             = 0
    }
    
    # Tags
    tags = {
      Name          = "${var.project}-PUB-ACL"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  # Create an Internet Gateway
  resource "aws_internet_gateway" "my_igw" {
    vpc_id       = aws_vpc.my_vpc.id
  
    tags = {
      Name        = "${var.project}-IGW"
      Environment = var.environment
      Project     = var.project
      Owner         = var.owner    
    }
  }
  
  # Elastic IP for the NAT Gateway
  resource "aws_eip" "nat_eip" {
    domain           = "vpc"
  
    # Tags
    tags = {
      Name          = "${var.project}-NATG-EIP"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  # NAT Gateway in the public subnet for private resources to reach internet resources
  resource "aws_nat_gateway" "my_natg" {
    allocation_id     = aws_eip.nat_eip.id
    subnet_id         = aws_subnet.public_subnet.id  #< NATG needs to reside in pub sub
  
    # Tags
    tags = {
      Name          = "${var.project}-NATG"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }  
    
    depends_on = [aws_internet_gateway.my_igw]
  }
  
  # route for private subnet - uses NATG
  resource "aws_route_table" "private_route_table" {
    vpc_id = aws_vpc.my_vpc.id
  
    route {
      cidr_block = "0.0.0.0/0"
      nat_gateway_id = aws_nat_gateway.my_natg.id
    }
  
    tags = {
     Name = "${var.project}-PRIV-RT"
      Environment = var.environment
      Project     = var.project
      Owner       = var.owner
    }
  }
  
  # route to internet for vpc resources
  resource "aws_route_table" "public_route_table" {
    vpc_id = aws_vpc.my_vpc.id
  
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.my_igw.id
    }
  
    tags = {
      Name        = "${var.project}-PUB-RT"
      Environment = var.environment
      Project     = var.project
      Owner       = var.owner
    }
  }
  
  resource "aws_default_route_table" "default_route_table" {
    default_route_table_id = aws_vpc.my_vpc.default_route_table_id
  
    tags = {
      Name        = "${var.project}-DEF-RT"
      Environment = var.environment
      Project     = var.project
      Owner       = var.owner
    }
  }
  
  # Associate pubsub with pub route
  resource "aws_route_table_association" "public_association" {
    subnet_id      = aws_subnet.public_subnet.id
    route_table_id = aws_route_table.public_route_table.id
    
    # no tags
  }
  
  # Associate privsub with priv route
  resource "aws_route_table_association" "private_association" {
    subnet_id      = aws_subnet.private_subnet.id
    route_table_id = aws_route_table.private_route_table.id
  
    # no tags
  }
  
  # Define a security group to allow incoming SSH traffic (adjust rules as needed)
  resource "aws_security_group" "ec2_sg" {
    name                = "${var.project}-SG"
    description         = "Security group allowing SSH traffic from campus only, egress anywhere"
    vpc_id              = aws_vpc.my_vpc.id 
  
    # Ingress rule for SSH
    ingress {
      from_port         = 22
      to_port           = 22
      protocol          = "tcp"
      cidr_blocks       = var.ingress_cidr_blocks
    }
  
    # Egress rule for all IPv4 traffic anywhere
    egress {
      from_port         = 0
      to_port           = 0
      protocol          = "-1"
      cidr_blocks       = ["0.0.0.0/0"]
    }
  
    # Egress rule for all IPv6 traffic anywhere
    egress {
      from_port         = 0
      to_port           = 0
      protocol          = "-1"
      ipv6_cidr_blocks  = ["::/0"]
    }
  
    # Tags
    tags = {
      Name          = "${var.project}-EC2-SG"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  /*
  
  # Create an EC2 instance in privsub
  resource "aws_instance" "my_ec2_instance" {
    ami                     = var.ami_instance
    instance_type           = var.instance_type
    key_name                = aws_key_pair.my_key_pair.key_name
    user_data               = var.ec2_std_data
    vpc_security_group_ids  = [aws_security_group.ec2_sg.id]
    subnet_id               = aws_subnet.private_subnet.id
  
    metadata_options {
      http_tokens          = "required"
    }
  
    # Tags
    tags = {
      Name          = "${var.project}-priv1-ec2"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
  
    }
  }
  
  # Create a second EC2 instance in privsub
  resource "aws_instance" "my_ec2_instance_b" {
    ami                     = var.ami_instance
    instance_type           = var.instance_type
    key_name                = aws_key_pair.my_key_pair.key_name
    user_data               = var.ec2_std_data
    vpc_security_group_ids  = [aws_security_group.ec2_sg.id]
    subnet_id               = aws_subnet.private_subnet.id
  
    metadata_options {
      http_tokens          = "required"
    }
  
    # Tags
    tags = {
      Name          = "${var.project}-priv2-ec2"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  */
  
  # Create a second EC2 instance in pubsub
  resource "aws_instance" "my_ec2_instance_c" {
    ami                     = var.ami_instance
    instance_type           = var.instance_type
    key_name                = aws_key_pair.my_key_pair.key_name  # Reference the key name from the aws_key_pair 
    user_data               = var.ec2_webserver_data
    vpc_security_group_ids  = [aws_security_group.ec2_sg.id]
    subnet_id               = aws_subnet.public_subnet.id
  
    metadata_options {
      http_tokens          = "required"
    }
  
    # Tags
    tags = {
      Name          = "${var.project}-pub1-ec2"
      Environment   = var.environment
      Project       = var.project
      Owner         = var.owner
    }
  }
  
  ```
  
  **Tags:** amazon-web-services
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2024-02-29. Score: 0
  
  So, for anyone else who stumbles across this, the ACLs don't know that the SYN-ACK packets coming back from a connection initiated from within an EC2 is traffic that is related to that connection (stateless).
  
  This means you can't just `apt update && apt dist-upgrade -y` without first opening `0/0` on the inbound side of the ACL.
  
  > **Comments:**
  > **username_1**: Security groups are supposed to be statefull (cf https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html). So I guess your problem is more about an asymetric routing.  
  
  ---
  
  