-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
499 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Local .terraform directories | ||
**/.terraform/* | ||
|
||
# Terraform lockfile | ||
.terraform.lock.hcl | ||
|
||
# .tfstate files | ||
*.tfstate | ||
*.tfstate.* | ||
|
||
# Crash log files | ||
crash.log | ||
|
||
# Exclude all .tfvars files, which are likely to contain sentitive data, such as | ||
# password, private keys, and other secrets. These should not be part of version | ||
# control as they are data points which are potentially sensitive and subject | ||
# to change depending on the environment. | ||
*.tfvars | ||
|
||
# Ignore override files as they are usually used to override resources locally and so | ||
# are not checked in | ||
override.tf | ||
override.tf.json | ||
*_override.tf | ||
*_override.tf.json | ||
|
||
# Ignore CLI configuration files | ||
.terraformrc | ||
terraform.rc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,76 @@ | ||
# terraform-aws-wireguard | ||
# Terraform AWS Wireguard | ||
|
||
This module creates EC2 instance with Wireguard inside. | ||
|
||
|
||
How to use: | ||
|
||
|
||
|
||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.5 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 3.0 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 3.0 | | ||
| <a name="provider_template"></a> [template](#provider\_template) | n/a | | ||
|
||
## Modules | ||
|
||
No modules. | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [aws_autoscaling_group.wireguard_asg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_group) | resource | | ||
| [aws_eip.wireguard](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | | ||
| [aws_iam_instance_profile.wireguard_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | | ||
| [aws_iam_policy.wireguard_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | ||
| [aws_iam_role.wireguard_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | ||
| [aws_iam_role_policy_attachment.wireguard_roleattach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | ||
| [aws_launch_configuration.wireguard_launch_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration) | resource | | ||
| [aws_route53_record.wireguard](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | | ||
| [aws_security_group.sg_wireguard](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | ||
| [aws_ami.ubuntu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | | ||
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | ||
| [aws_iam_policy_document.ec2_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | ||
| [aws_iam_policy_document.wireguard_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | ||
| [template_file.wg_client_data_json](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_ami_id"></a> [ami\_id](#input\_ami\_id) | The AWS AMI to use for the Wireguard server, defaults to the latest Ubuntu 20.04 AMI if not specified. | `any` | `null` | no | | ||
| <a name="input_asg_desired_capacity"></a> [asg\_desired\_capacity](#input\_asg\_desired\_capacity) | We may want more than one machine in a scaling group, but 1 is recommended. | `number` | `1` | no | | ||
| <a name="input_asg_max_size"></a> [asg\_max\_size](#input\_asg\_max\_size) | We may want more than one machine in a scaling group, but 1 is recommended. | `number` | `1` | no | | ||
| <a name="input_asg_min_size"></a> [asg\_min\_size](#input\_asg\_min\_size) | We may want more than one machine in a scaling group, but 1 is recommended. | `number` | `1` | no | | ||
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | n/a | `string` | n/a | yes | | ||
| <a name="input_env"></a> [env](#input\_env) | The name of environment for Wireguard. | `any` | n/a | yes | | ||
| <a name="input_instance_type"></a> [instance\_type](#input\_instance\_type) | The machine type to launch, some machines may offer higher throughput for higher use cases. | `string` | `"t2.micro"` | no | | ||
| <a name="input_route53_geo"></a> [route53\_geo](#input\_route53\_geo) | Route53 Geolocation config. | `any` | `null` | no | | ||
| <a name="input_route53_hosted_zone_id"></a> [route53\_hosted\_zone\_id](#input\_route53\_hosted\_zone\_id) | Route53 Hosted zone ID. | `string` | `null` | no | | ||
| <a name="input_route53_record_name"></a> [route53\_record\_name](#input\_route53\_record\_name) | Route53 Record name. | `string` | `null` | no | | ||
| <a name="input_ssh_key_id"></a> [ssh\_key\_id](#input\_ssh\_key\_id) | A SSH public key ID to add to the VPN instance. | `any` | n/a | yes | | ||
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | A list of subnets for the Autoscaling Group to use for launching instances. May be a single subnet, but it must be an element in a list. | `list(string)` | n/a | yes | | ||
| <a name="input_target_group_arns"></a> [target\_group\_arns](#input\_target\_group\_arns) | Running a scaling group behind an LB requires this variable, default null means it won't be included if not set. | `list(string)` | `null` | no | | ||
| <a name="input_use_eip"></a> [use\_eip](#input\_use\_eip) | Whether to enable Elastic IP switching code in user-data on wg server startup. If true, eip\_id must also be set to the ID of the Elastic IP. | `bool` | `false` | no | | ||
| <a name="input_use_route53"></a> [use\_route53](#input\_use\_route53) | Whether to use SSM to store Wireguard Server private key. | `bool` | `false` | no | | ||
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | The VPC ID in which Terraform will launch the resources. | `any` | n/a | yes | | ||
| <a name="input_wg_clients"></a> [wg\_clients](#input\_wg\_clients) | List of client objects with IP and public key. See Usage in README for details. | `list(object({ friendly_name = string, public_key = string, client_ip = string }))` | n/a | yes | | ||
| <a name="input_wg_persistent_keepalive"></a> [wg\_persistent\_keepalive](#input\_wg\_persistent\_keepalive) | Persistent Keepalive - useful for helping connection stability over NATs. | `number` | `25` | no | | ||
| <a name="input_wg_server_interface"></a> [wg\_server\_interface](#input\_wg\_server\_interface) | The default interface to forward network traffic to. | `string` | `"eth0"` | no | | ||
| <a name="input_wg_server_net"></a> [wg\_server\_net](#input\_wg\_server\_net) | IP range for vpn server - make sure your Client ips are in this range but not the specific ip i.e. not .1 | `string` | `"10.0.0.1/24"` | no | | ||
| <a name="input_wg_server_port"></a> [wg\_server\_port](#input\_wg\_server\_port) | Port for the vpn server. | `number` | `51820` | no | | ||
| <a name="input_wg_server_private_key"></a> [wg\_server\_private\_key](#input\_wg\_server\_private\_key) | Wireguard server private key. | `string` | `null` | no | | ||
|
||
## Outputs | ||
|
||
No outputs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
data "aws_iam_policy_document" "ec2_assume_role" { | ||
statement { | ||
actions = [ | ||
"sts:AssumeRole" | ||
] | ||
|
||
principals { | ||
type = "Service" | ||
identifiers = ["ec2.amazonaws.com"] | ||
} | ||
} | ||
} | ||
|
||
data "aws_iam_policy_document" "wireguard_policy_doc" { | ||
statement { | ||
actions = [ | ||
"ec2:AssociateAddress", | ||
"ssm:GetParameter" | ||
] | ||
|
||
resources = ["*"] | ||
} | ||
} | ||
|
||
data "aws_caller_identity" "current" {} | ||
|
||
resource "aws_iam_policy" "wireguard_policy" { | ||
name = "${var.env}-${var.aws_region}-tf-wireguard" | ||
description = "Terraform Managed. Allows Wireguard instance to attach EIP." | ||
policy = data.aws_iam_policy_document.wireguard_policy_doc.json | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} | ||
|
||
resource "aws_iam_role" "wireguard_role" { | ||
name = "${var.env}-${var.aws_region}-tf-wireguard" | ||
description = "Terraform Managed. Role to allow Wireguard instance to attach EIP." | ||
path = "/" | ||
assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} | ||
|
||
resource "aws_iam_role_policy_attachment" "wireguard_roleattach" { | ||
role = aws_iam_role.wireguard_role[0].name | ||
policy_arn = aws_iam_policy.wireguard_policy[0].arn | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} | ||
|
||
resource "aws_iam_instance_profile" "wireguard_profile" { | ||
name = "${var.env}-${var.aws_region}-tf-wireguard" | ||
role = aws_iam_role.wireguard_role[0].name | ||
count = (var.use_eip ? 1 : 0) # only used for EIP mode | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
resource "aws_eip" "wireguard" { | ||
vpc = true | ||
tags = { | ||
Name = "${var.env}-wireguard" | ||
} | ||
} | ||
|
||
resource "aws_route53_record" "wireguard" { | ||
count = var.use_route53 ? 1 : 0 | ||
allow_overwrite = true | ||
set_identifier = "${var.env}-${var.aws_region}-wireguard" | ||
zone_id = var.route53_hosted_zone_id | ||
name = var.route53_record_name | ||
type = "A" | ||
ttl = "60" | ||
records = [aws_eip.wireguard.public_ip] | ||
|
||
dynamic "geolocation_routing_policy" { | ||
for_each = try(length(var.route53_geo.policy) > 0 ? var.route53_geo.policy : tomap(false), {}) | ||
|
||
content { | ||
continent = geolocation_routing_policy.value.continent | ||
} | ||
} | ||
} | ||
|
||
data "template_file" "wg_client_data_json" { | ||
template = file("${path.module}/templates/client-data.tpl") | ||
count = length(var.wg_clients) | ||
|
||
vars = { | ||
friendly_name = var.wg_clients[count.index].friendly_name | ||
client_pub_key = var.wg_clients[count.index].public_key | ||
client_ip = var.wg_clients[count.index].client_ip | ||
persistent_keepalive = var.wg_persistent_keepalive | ||
} | ||
} | ||
|
||
data "aws_ami" "ubuntu" { | ||
most_recent = true | ||
filter { | ||
name = "name" | ||
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] | ||
} | ||
filter { | ||
name = "virtualization-type" | ||
values = ["hvm"] | ||
} | ||
owners = ["099720109477"] # Canonical | ||
} | ||
|
||
resource "aws_launch_configuration" "wireguard_launch_config" { | ||
name_prefix = "${var.env}-wireguard-" | ||
image_id = var.ami_id == null ? data.aws_ami.ubuntu.id : var.ami_id | ||
instance_type = var.instance_type | ||
key_name = var.ssh_key_id | ||
iam_instance_profile = (var.use_eip ? aws_iam_instance_profile.wireguard_profile[0].name : null) | ||
user_data = templatefile("${path.module}/templates/user-data.txt", { | ||
wg_server_private_key = var.wg_server_private_key, | ||
wg_server_net = var.wg_server_net, | ||
wg_server_port = var.wg_server_port, | ||
peers = join("\n", data.template_file.wg_client_data_json.*.rendered), | ||
use_eip = var.use_eip ? "enabled" : "disabled", | ||
eip_id = aws_eip.wireguard.id, | ||
wg_server_interface = var.wg_server_interface | ||
}) | ||
security_groups = [aws_security_group.sg_wireguard.id] | ||
associate_public_ip_address = var.use_eip | ||
|
||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
} | ||
|
||
resource "aws_autoscaling_group" "wireguard_asg" { | ||
name = aws_launch_configuration.wireguard_launch_config.name | ||
launch_configuration = aws_launch_configuration.wireguard_launch_config.name | ||
min_size = var.asg_min_size | ||
desired_capacity = var.asg_desired_capacity | ||
max_size = var.asg_max_size | ||
vpc_zone_identifier = var.subnet_ids | ||
health_check_type = "EC2" | ||
termination_policies = ["OldestLaunchConfiguration", "OldestInstance"] | ||
target_group_arns = var.target_group_arns | ||
|
||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
|
||
tags = [ | ||
{ | ||
key = "Name" | ||
value = aws_launch_configuration.wireguard_launch_config.name | ||
propagate_at_launch = true | ||
}, | ||
{ | ||
key = "Project" | ||
value = "wireguard" | ||
propagate_at_launch = true | ||
}, | ||
{ | ||
key = "env" | ||
value = var.env | ||
propagate_at_launch = true | ||
}, | ||
{ | ||
key = "tf-managed" | ||
value = "True" | ||
propagate_at_launch = true | ||
}, | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
resource "aws_security_group" "sg_wireguard" { | ||
name = "${var.env}-${var.aws_region}-wireguard" | ||
description = "Terraform Managed. Allow Wireguard client traffic from internet." | ||
vpc_id = var.vpc_id | ||
|
||
tags = { | ||
Name = "${var.env}-${var.aws_region}-wireguard" | ||
Project = "wireguard" | ||
tf-managed = "True" | ||
env = var.env | ||
} | ||
|
||
ingress { | ||
from_port = var.wg_server_port | ||
to_port = var.wg_server_port | ||
protocol = "udp" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
ingress { | ||
from_port = 22 | ||
to_port = 22 | ||
protocol = "tcp" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
|
||
egress { | ||
from_port = 0 | ||
to_port = 0 | ||
protocol = "-1" | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[Peer] | ||
# friendly_name = ${friendly_name} | ||
PublicKey = ${client_pub_key} | ||
AllowedIPs = ${client_ip} | ||
PersistentKeepalive = ${persistent_keepalive} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/bin/bash -v | ||
apt-get update | ||
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -o Dpkg::Options::="--force-confnew" | ||
apt-get install -y \ | ||
apt-transport-https \ | ||
ca-certificates \ | ||
build-essential \ | ||
software-properties-common \ | ||
unzip \ | ||
curl \ | ||
wget \ | ||
gnupg \ | ||
net-tools \ | ||
jq \ | ||
wireguard-dkms \ | ||
wireguard-tools && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ | ||
unzip awscliv2.zip && \ | ||
rm -f awscliv2.zip && \ | ||
./aws/install | ||
|
||
cat > /etc/wireguard/wg0.conf <<- EOF | ||
[Interface] | ||
Address = ${wg_server_net} | ||
PrivateKey = ${wg_server_private_key} | ||
ListenPort = ${wg_server_port} | ||
PostUp = sysctl -w -q net.ipv4.ip_forward=1 | ||
PostUp = iptables -P FORWARD DROP | ||
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT | ||
PostUp = iptables -t nat -A POSTROUTING -o ENI -j MASQUERADE | ||
PostDown = sysctl -w -q net.ipv4.ip_forward=0 | ||
PostDown = iptables -P FORWARD ACCEPT | ||
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT | ||
PostDown = iptables -t nat -D POSTROUTING -o ENI -j MASQUERADE | ||
${peers} | ||
EOF | ||
|
||
export ENI=$(ip route get 8.8.8.8 | grep 8.8.8.8 | awk '{print $5}') | ||
sed -i "s/ENI/$ENI/g" /etc/wireguard/wg0.conf | ||
|
||
# Use EIP if it is provided | ||
if [ "${use_eip}" != "disabled" ]; then | ||
export INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) | ||
export REGION=$(curl -fsq http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/[a-z]$//') | ||
aws --region $${REGION} ec2 associate-address --allocation-id ${eip_id} --instance-id $${INSTANCE_ID} | ||
fi | ||
|
||
chown -R root:root /etc/wireguard/ | ||
chmod -R og-rwx /etc/wireguard/* | ||
sysctl -p | ||
systemctl enable [email protected] | ||
systemctl start [email protected] | ||
|
||
until systemctl is-active --quiet [email protected] | ||
do | ||
sleep 1 | ||
done | ||
|
||
ufw allow ssh | ||
ufw allow ${wg_server_port}/udp | ||
ufw --force enable |
Oops, something went wrong.