Skip to content

Commit

Permalink
Updates Alternat to use Amazon Linux 2023 (#116)
Browse files Browse the repository at this point in the history
* Updates Alternat to use Amazon Linux 2023

* remove out of date comment and now unused workflow

* install terraform

* fix test

* retries

* use assert

* sudo make me

* newline

* whitespace
  • Loading branch information
bwhaley authored Dec 19, 2024
1 parent 894b256 commit 5e0a8ba
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 51 deletions.
27 changes: 0 additions & 27 deletions .github/workflows/main.yaml

This file was deleted.

3 changes: 3 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Install Terraform
uses: hashicorp/setup-terraform@v3

- name: Install Go
uses: actions/setup-go@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Features:

* Self-provisioned NAT instances in Auto Scaling Groups
* Standby NAT Gateways with health checks and automated failover, facilitated by a Lambda function
* Vanilla Amazon Linux 2 AMI (no AMI management requirement)
* Vanilla Amazon Linux 2023 AMI (no AMI management requirement)
* Optional use of SSM for connecting to the NAT instances
* Max instance lifetimes (no long-lived instances!) with automated failover
* A Terraform module to set everything up
Expand Down
6 changes: 3 additions & 3 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ resource "aws_iam_role_policy" "alternat_lifecycle_hook" {
}


data "aws_ami" "amazon_linux_2" {
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]

Expand All @@ -151,7 +151,7 @@ data "aws_ami" "amazon_linux_2" {

filter {
name = "name"
values = ["amzn2-ami-hvm*"]
values = ["al2023-ami-2023*"]
}
}

Expand Down Expand Up @@ -218,7 +218,7 @@ resource "aws_launch_template" "nat_instance_template" {
name = aws_iam_instance_profile.nat_instance.name
}

image_id = var.nat_ami == "" ? data.aws_ami.amazon_linux_2.id : var.nat_ami
image_id = var.nat_ami == "" ? data.aws_ami.amazon_linux_2023.id : var.nat_ami

instance_type = var.nat_instance_type

Expand Down
28 changes: 15 additions & 13 deletions scripts/alternat.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ validate_var() {
# configure_nat() sets up Linux to act as a NAT device.
# See https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html#NATInstance
configure_nat() {
echo "Beginning NAT configuration"
dnf -y install nftables

echo "Determining the MAC address on eth0"
local eth0_mac="$(cat /sys/class/net/eth0/address)" || panic "Unable to determine MAC address on eth0."
echo "Found MAC $eth0_mac for eth0."
local nic_name="$(ip route show | grep default | sed -n 's/.*dev \([^\ ]*\).*/\1/p')"
echo "Found interface name ${nic_name}"

local vpc_cidr_uri="http://169.254.169.254/latest/meta-data/network/interfaces/macs/$eth0_mac/vpc-ipv4-cidr-blocks"
echo "Determining the MAC address on ${nic_name}"
local nic_mac="$(cat /sys/class/net/${nic_name}/address)" || panic "Unable to determine MAC address on ${nic_name}."
echo "Found MAC ${nic_mac} for ${nic_name}."

local vpc_cidr_uri="http://169.254.169.254/latest/meta-data/network/interfaces/macs/${nic_mac}/vpc-ipv4-cidr-blocks"
echo "Metadata location for vpc ipv4 ranges: $vpc_cidr_uri"

local vpc_cidr_ranges=$(CURL_WITH_TOKEN "$vpc_cidr_uri")
Expand All @@ -56,18 +59,19 @@ configure_nat() {
echo "Enabling NAT..."
# Read more about these settings here: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

sysctl -q -w net.ipv4.ip_forward=1 net.ipv4.conf.eth0.send_redirects=0 net.ipv4.ip_local_port_range="1024 65535" ||
sysctl -q -w "net.ipv4.ip_forward"=1 "net.ipv4.conf.$nic_name.send_redirects"=0 "net.ipv4.ip_local_port_range"="1024 65535" ||
panic

nft add table ip nat
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }

for cidr in "${vpc_cidrs[@]}";
do
(iptables -t nat -C POSTROUTING -o eth0 -s "$cidr" -j MASQUERADE 2> /dev/null ||
iptables -t nat -A POSTROUTING -o eth0 -s "$cidr" -j MASQUERADE) ||
panic
nft add rule ip nat postrouting ip saddr "$cidr" oif "$nic_name" masquerade
done

sysctl net.ipv4.ip_forward net.ipv4.conf.eth0.send_redirects net.ipv4.ip_local_port_range
iptables -n -t nat -L POSTROUTING
sysctl "net.ipv4.ip_forward" "net.ipv4.conf.${nic_name}.send_redirects" "net.ipv4.ip_local_port_range"
nft list ruleset

echo "NAT configuration complete"
}
Expand Down Expand Up @@ -172,8 +176,6 @@ export AWS_DEFAULT_OUTPUT="text"

# Disable pager output
# https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-pagination.html#cli-usage-pagination-clientside
# This is not needed in aws cli v1 which is installed on the current version of Amazon Linux 2.
# However, it may be needed to prevent breakage if they update to cli v2 in the future.
export AWS_PAGER=""

# Set Instance Identity URI
Expand Down
18 changes: 11 additions & 7 deletions test/alternat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,22 @@ func TestAlternat(t *testing.T) {
retry.DoWithRetry(t, fmt.Sprintf("Check SSH connection to %s", ip), maxRetries, waitTime, func() (string, error) {
return "", ssh.CheckSshConnectionE(t, natInstance)
})
command := "/usr/sbin/sysctl net.ipv4.ip_forward net.ipv4.conf.eth0.send_redirects net.ipv4.ip_local_port_range"

expectedText := `net.ipv4.ip_forward = 1
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.ip_local_port_range = 1024 65535
command := "sudo /usr/sbin/nft list ruleset"

expectedText := `table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.10.0.0/16 oif "ens5" masquerade
}
}
`

maxRetries = 1
maxRetries = 5
waitTime = 10 * time.Second
retry.DoWithRetry(t, fmt.Sprintf("SSH to NAT instance at IP %s", ip), maxRetries, waitTime, func() (string, error) {
actualText, err := ssh.CheckSshCommandE(t, natInstance, command)
require.NoError(t, err)
assert.NoError(t, err)
if actualText != expectedText {
return "", fmt.Errorf("Expected SSH command to return '%s' but got '%s'", expectedText, actualText)
}
Expand Down Expand Up @@ -188,7 +192,7 @@ net.ipv4.ip_local_port_range = 1024 65535
return "All private route tables route through NAT Gateway", nil
})
logger := logger.Logger{}
logger.Logf(t, output)
logger.Logf(t, output)
updateEgress(t, ec2Client, sgId, false)
})
}
Expand Down

0 comments on commit 5e0a8ba

Please sign in to comment.