Security-Onion-Solutions / securityonion-cloud

GNU Affero General Public License v3.0
32 stars 16 forks source link

Security Onion instance does not get a new public IPv4 address if AWS ec2 instance is stopped #27

Open SuiNom opened 3 years ago

SuiNom commented 3 years ago

When stopping and starting a pre-existing instance previously created with terraform, the security onion appliance does not pick up a new public IPv4 address: 2021-08-13_11-50

Seen above both a windows and ubuntu instance pick up new IPv4 addresses as expected from the vpc.tf subnet creation:

# subnet creation
resource "aws_subnet" "default" {
  vpc_id                  = aws_vpc.terraform.id
  cidr_block              = "172.16.163.0/24"
  availability_zone       = var.availability_zone
  *map_public_ip_on_launch = true*
}

As a testing step I added associate_public_ip_address = true to so.tf but the instance still does not get a new public IPv4 address on stopping and starting the instance.

resource "aws_instance" "securityonion" {
  depends_on = [ aws_internet_gateway.default ]
  count         = var.onions
  instance_type = var.instance_type
  ami           = data.aws_ami.latest_so.id != "" ? data.aws_ami.latest_so.id : var.ami

  tags = {
    Name = "security-onion-${count.index}"
    so-lab = "True"
  }

  subnet_id              = aws_subnet.default.id
  vpc_security_group_ids = [aws_security_group.securityonion.id]
  key_name               = aws_key_pair.auth.key_name
  private_ip             = "172.16.163.1${count.index}"
  **associate_public_ip_address = true**

  root_block_device {
    delete_on_termination = true
    volume_size           = 250
  }
}

The reason for stopping instances is cost savings in a lab environment, without having to run through so-setup each time it's required.

Steps to reproduce:

  1. terraform apply --auto-approve
  2. Connect to instance as usual and run through so-setup
  3. Stop instances via ec2 dashboard
  4. Start instances via ec2 dashboard
SuiNom commented 3 years ago

Currently working around this by assigning an Elastic IP to Security Onion with the following additions/changes:

so.tf:

resource "aws_eip" "onion-pub" {
  vpc = true
  count = var.onions
  instance = aws_instance.securityonion[count.index].id
  associate_with_private_ip = aws_instance.securityonion[count.index].private_ip
  depends_on = [aws_internet_gateway.default]
}

The above assigns an eip to each onion instance, I tried to follow the current conventions for count, etc.

outputs.tf

output "securityonion_public_ips" {
  description = "Security Onion Public IP Address(es)"
  value = aws_eip.onion-pub[*].public_ip
}

The above changes the output to that of the EIP assigned to the Onion instance.

While I've tested this for my use case, I believe the default behaviour should be that the Onion instance picks up anther Public IPv4 address in the same way as the Windows and Ubuntu instances do.

weslambert commented 3 years ago

You'll want to use an EIP if you want it to be persistent after stopping/starting. If you are going to stop/start anyway, and don't want to pay for the maintenance of an Elastic IP (when it's not attached to a running instance), you may consider associating an Elastic IP to the management interface at the time you want to start it again, then de-associate/destroy it after that, so you are not continually charged for it.

With regard to renewing a public IP, please see the following:

If the public IP address of your instance in a VPC has been released, it will not receive a new one if there is more than one network interface attached to your instance.

This is from the AWS documentation, located here: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html

Because the Security Onion instance has two network interfaces (one for management, one for sniffing), it cannot be automatically assigned a public IP after starting (from being stopped).

I tested similar EIP configuration shortly after you posted the initial issue, and it seems to have been working okay for me so far. I'm thinking it would be a good idea to have a flag in the terraform.tfvars file to determine whether or not an EIP should be used, as some folks (like myself, frequently) are spinning up and tearing down very quickly and do not necessarily need to stop the instance. I'm considering the following changes:

terraform.tfvars:

eip = false (false by default, change to true for EIP)

so.tf:

resource "aws_eip" "so-elastic-ip" {
  depends_on = [ aws_instance.securityonion, aws_internet_gateway.default ]
  count         = var.eip == true ? var.onions : 0
  vpc                       = true
  instance                  = aws_instance.securityonion[count.index].id
  associate_with_private_ip = aws_instance.securityonion[count.index].private_ip
}

outputs.tf:

output "securityonion_public_ips" {
  description = "Security Onion Public IP Address(es)"
  value = var.eip == true ? aws_eip.so-elastic-ip[*].public_ip : aws_instance.securityonion[*].public_ip
}

variables.tf

variable "eip" {
  description = "If set to true, Elastic IP will be associated with instance"
  type  = bool
}
SuiNom commented 3 years ago

That looks like a solid solution and would help for longer running lab/dev environments like mine.

PS. Thank you for the EC2 documentation link, I had an inkling that it was down to multiple NICs, but I couldn't confirm. A lesson in RTFM for me.

weslambert commented 3 years ago

No problem, and no worries! I will push those changes to the codebase soon.