Skip to content
This repository was archived by the owner on Jul 20, 2024. It is now read-only.

Commit de153d3

Browse files
authored
Fix to enable snat after reboot (#18)
1 parent 35047c5 commit de153d3

File tree

8 files changed

+66
-92
lines changed

8 files changed

+66
-92
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.terraform/
22
.terraform.*
33
*.tfstate
4+
*.tfstate.backup

README.md

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -75,55 +75,6 @@ The instance will run [init.sh](data/init.sh) to enable NAT as follows:
7575

7676
## Configuration
7777

78-
### Set extra IAM policies
79-
80-
You can attach an extra policy to the IAM role of the NAT instance. For example,
81-
82-
```tf
83-
resource "aws_iam_role_policy" "nat_iam_ec2" {
84-
role = module.nat.iam_role_name
85-
policy = <<EOF
86-
{
87-
"Version": "2012-10-17",
88-
"Statement": [
89-
{
90-
"Effect": "Allow",
91-
"Action": [
92-
"ec2:DescribeInstances"
93-
],
94-
"Resource": "*"
95-
}
96-
]
97-
}
98-
EOF
99-
}
100-
```
101-
102-
### Run a script
103-
104-
You can set an extra script to run in the NAT instance.
105-
The current region is exported as `AWS_DEFAULT_REGION` and you can use awscli without a region option.
106-
107-
For example, you can expose port 8080 of the NAT instance using DNAT:
108-
109-
```tf
110-
module "nat" {
111-
extra_user_data = templatefile("${path.module}/data/nat-port-forward.sh", {
112-
eni_private_ip = module.nat.eni_private_ip
113-
})
114-
}
115-
```
116-
117-
```sh
118-
# Look up the target instance
119-
tag_name="TARGET_TAG"
120-
target_private_ip="$(aws ec2 describe-instances --filters "Name=tag:Name,Values=$tag_name" | jq -r .Reservations[0].Instances[0].PrivateIpAddress)"
121-
122-
# Expose the port of the NAT instance.
123-
iptables -t nat -A PREROUTING -m tcp -p tcp --dst "${eni_private_ip}" --dport 8080 -j DNAT --to-destination "$target_private_ip:8080"
124-
```
125-
126-
12778
### Allow SSH access
12879

12980
You can log in to the NAT instance from [AWS Systems Manager Session Manager](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html).
@@ -167,7 +118,6 @@ No requirements.
167118
| Name | Description | Type | Default | Required |
168119
|------|-------------|------|---------|:--------:|
169120
| enabled | Enable or not costly resources | `bool` | `true` | no |
170-
| extra\_user\_data | Extra script to run in the NAT instance | `string` | `""` | no |
171121
| image\_id | AMI of the NAT instance. Default to the latest Amazon Linux 2 | `string` | `""` | no |
172122
| instance\_types | Candidates of spot instance type for the NAT instance. This is used in the mixed instances policy | `list` | <pre>[<br> "t3.nano",<br> "t3a.nano"<br>]</pre> | no |
173123
| key\_name | Name of the key pair for the NAT instance. You can set this to assign the key pair to the NAT instance | `string` | `""` | no |

data/init.sh

Lines changed: 0 additions & 31 deletions
This file was deleted.

main.tf

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,31 @@ resource "aws_launch_template" "this" {
8585
delete_on_termination = true
8686
}
8787

88-
user_data = base64encode(
89-
templatefile("${path.module}/data/init.sh", {
90-
eni_id = aws_network_interface.this.id
91-
extra_user_data = var.extra_user_data
88+
user_data = base64encode(join("\n", [
89+
"#cloud-config",
90+
yamlencode({
91+
# https://cloudinit.readthedocs.io/en/latest/topics/modules.html
92+
write_files : [
93+
{
94+
path : "/opt/nat/runonce.sh",
95+
content : templatefile("${path.module}/runonce.sh", { eni_id = aws_network_interface.this.id }),
96+
permissions : "0755",
97+
},
98+
{
99+
path : "/opt/nat/snat.sh",
100+
content : file("${path.module}/snat.sh"),
101+
permissions : "0755",
102+
},
103+
{
104+
path : "/etc/systemd/system/snat.service",
105+
content : file("${path.module}/snat.service"),
106+
},
107+
],
108+
runcmd : [
109+
["/opt/nat/runonce.sh"],
110+
],
92111
})
93-
)
112+
]))
94113

95114
description = "Launch template for NAT instance ${var.name}"
96115
tags = {

runonce.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash -x
2+
3+
# attach the ENI
4+
aws ec2 attach-network-interface \
5+
--region "$(/opt/aws/bin/ec2-metadata -z | sed 's/placement: \(.*\).$/\1/')" \
6+
--instance-id "$(/opt/aws/bin/ec2-metadata -i | cut -d' ' -f2)" \
7+
--device-index 1 \
8+
--network-interface-id "${eni_id}"
9+
10+
# start SNAT
11+
systemctl enable snat
12+
systemctl start snat

snat.service

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[Unit]
2+
Description = SNAT via ENI eth1
3+
4+
[Service]
5+
ExecStart = /opt/nat/snat.sh
6+
Type = oneshot
7+
8+
[Install]
9+
WantedBy = multi-user.target

snat.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash -x
2+
3+
# wait for eth1
4+
while ! ip link show dev eth1; do
5+
sleep 1
6+
done
7+
8+
# enable IP forwarding and NAT
9+
sysctl -q -w net.ipv4.ip_forward=1
10+
sysctl -q -w net.ipv4.conf.eth1.send_redirects=0
11+
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
12+
13+
# switch the default route to eth1
14+
ip route del default dev eth0
15+
16+
# wait for network connection
17+
curl --retry 10 http://www.example.com
18+
19+
# reestablish connections
20+
systemctl restart amazon-ssm-agent.service

variables.tf

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ variable "private_route_table_ids" {
3030
default = []
3131
}
3232

33-
variable "extra_user_data" {
34-
description = "Extra script to run in the NAT instance"
35-
type = string
36-
default = ""
37-
}
38-
3933
variable "image_id" {
4034
description = "AMI of the NAT instance. Default to the latest Amazon Linux 2"
4135
type = string

0 commit comments

Comments
 (0)