Skip to content

Commit

Permalink
Fix PR
Browse files Browse the repository at this point in the history
  • Loading branch information
kobrikx committed Jul 30, 2021
1 parent b81cb57 commit ad3a539
Show file tree
Hide file tree
Showing 12 changed files with 779 additions and 96 deletions.
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

674 changes: 674 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

42 changes: 27 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
# Terraform AWS Wireguard
# Terraform AWS WireGuard

This module creates EC2 instance with Wireguard inside.
A Terraform module to deploy a WireGuard VPN server on AWS.

### Prerequisites
Before using this module, you'll need to:

How to use:
1. Install the [WireGuard tools](https://www.wireguard.com/install/) for your OS.

2. Generate a key pair for each client:
```bash
wg genkey | tee client1-privatekey | wg pubkey > client1-publickey
```

3. Generate a key pair for the server
```bash
wg genkey | tee server-privatekey | wg pubkey > server-publickey
```
4. Add each client's public key, along with the next available IP address to the `wg_clients` list.

5. Add server's private key to the `wg_server_private_key` variable. You can use AWS SSM Parameter store to store and read server private key.


<!-- BEGINNING OF GENERATED BY TERRAFORM-DOCS -->

## Requirements

Expand Down Expand Up @@ -48,29 +64,25 @@ No modules.

| 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_env"></a> [env](#input\_env) | The name of environment for WireGuard. Used to differentiate multiple deployments. | `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` | `"t3.nano"` | no |
| <a name="input_region"></a> [region](#input\_region) | n/a | `string` | n/a | yes |
| <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_use_route53"></a> [use\_route53](#input\_use\_route53) | Whether to use Route53 | `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_clients"></a> [wg\_clients](#input\_wg\_clients) | List of client objects with IP and public key. See Usage in README for details. | `list(object({ client_friendly_name = string, client_public_key = string, client_allowed_cidr = 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 |
| <a name="input_wg_server_private_key"></a> [wg\_server\_private\_key](#input\_wg\_server\_private\_key) | WG server private key. | `string` | n/a | yes |

## Outputs

No outputs
No outputs.
<!-- END OF GENERATED BY TERRAFORM-DOCS -->
28 changes: 28 additions & 0 deletions examples/complete.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module "wireguard" {
source = "[email protected]:hazelops/terraform-aws-wireguard.git"
env = your-env
region = your-aws-region
use_eip = true
ssh_key_id = "your-ec2-key-id"
instance_type = "t3.nano"
wg_server_net = "10.0.0.1/24"
wg_server_port = 51820
wg_persistent_keepalive = 25
wg_server_interface ="eth0"
use_route53 = false
subnet_ids = ["your-vpc-subnets"]
vpc_id = "id-of-your-vpc"
wg_server_private_key = data.aws_ssm_parameter.wireguard_server_private_key.value
wg_clients = [
{ client_friendly_name = "user1"
client_allowed_cidr = "10.0.0.3/24"
client_public_key= "user1-public-key" },
{ client_friendly_name = "user2"
client_allowed_cidr = "10.0.0.4/24"
client_public_key= "user2-public-key" }
]
}

data "aws_ssm_parameter" "wireguard_server_private_key" {
name = "/global/wg-server-private-key"
}
22 changes: 22 additions & 0 deletions examples/minimal.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module "wireguard" {
source = "[email protected]:hazelops/terraform-aws-wireguard.git"
env = your-env
region = your-aws-region
use_eip = true
ssh_key_id = "your-ec2-key-id"
subnet_ids = ["vpc-subnets"]
vpc_id = <"id-of-your-vpc">
wg_server_private_key = data.aws_ssm_parameter.wireguard_server_private_key.value
wg_clients = [
{ client_friendly_name = "user1"
client_allowed_cidr = "10.0.0.3/24"
client_public_key= "user1-public-key" },
{ client_friendly_name = "user2"
client_allowed_cidr = "10.0.0.4/24"
client_public_key= "user2-public-key" }
]
}

data "aws_ssm_parameter" "wireguard_server_private_key" {
name = "/global/wg-server-private-key"
}
6 changes: 3 additions & 3 deletions iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ data "aws_iam_policy_document" "wireguard_policy_doc" {
data "aws_caller_identity" "current" {}

resource "aws_iam_policy" "wireguard_policy" {
name = "${var.env}-${var.aws_region}-tf-wireguard"
name = "${var.env}-${var.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"
name = "${var.env}-${var.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
Expand All @@ -46,7 +46,7 @@ resource "aws_iam_role_policy_attachment" "wireguard_roleattach" {
}

resource "aws_iam_instance_profile" "wireguard_profile" {
name = "${var.env}-${var.aws_region}-tf-wireguard"
name = "${var.env}-${var.region}-tf-wireguard"
role = aws_iam_role.wireguard_role[0].name
count = (var.use_eip ? 1 : 0) # only used for EIP mode
}
24 changes: 8 additions & 16 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,22 @@ resource "aws_eip" "wireguard" {
resource "aws_route53_record" "wireguard" {
count = var.use_route53 ? 1 : 0
allow_overwrite = true
set_identifier = "${var.env}-${var.aws_region}-wireguard"
set_identifier = "${var.env}-${var.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
client_friendly_name = var.wg_clients[count.index].client_friendly_name
client_public_key = var.wg_clients[count.index].client_public_key
client_allowed_cidr = var.wg_clients[count.index].client_allowed_cidr
persistent_keepalive = var.wg_persistent_keepalive
}
}
Expand All @@ -51,7 +43,7 @@ data "aws_ami" "ubuntu" {

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
image_id = data.aws_ami.ubuntu.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)
Expand All @@ -75,9 +67,9 @@ resource "aws_launch_configuration" "wireguard_launch_config" {
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
min_size = 1
desired_capacity = 1
max_size = 1
vpc_zone_identifier = var.subnet_ids
health_check_type = "EC2"
termination_policies = ["OldestLaunchConfiguration", "OldestInstance"]
Expand Down
4 changes: 2 additions & 2 deletions sg.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
resource "aws_security_group" "sg_wireguard" {
name = "${var.env}-${var.aws_region}-wireguard"
name = "${var.env}-${var.region}-wireguard"
description = "Terraform Managed. Allow Wireguard client traffic from internet."
vpc_id = var.vpc_id

tags = {
Name = "${var.env}-${var.aws_region}-wireguard"
Name = "${var.env}-${var.region}-wireguard"
Project = "wireguard"
tf-managed = "True"
env = var.env
Expand Down
6 changes: 3 additions & 3 deletions templates/client-data.tpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Peer]
# friendly_name = ${friendly_name}
PublicKey = ${client_pub_key}
AllowedIPs = ${client_ip}
# client_friendly_name = ${client_friendly_name}
PublicKey = ${client_public_key}
AllowedIPs = ${client_allowed_cidr}
PersistentKeepalive = ${persistent_keepalive}
5 changes: 5 additions & 0 deletions templates/user-data.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ rm -f awscliv2.zip && \
./aws/install

cat > /etc/wireguard/wg0.conf <<- EOF
# Managed by Terraform
[Interface]
Address = ${wg_server_net}
PrivateKey = ${wg_server_private_key}
Expand Down Expand Up @@ -59,6 +60,10 @@ do
sleep 1
done

sysctl -w net.ipv6.conf.all.disable_ipv6=1
sysctl -w net.ipv6.conf.default.disable_ipv6=1
sysctl -w net.ipv6.conf.lo.disable_ipv6=1

ufw allow ssh
ufw allow ${wg_server_port}/udp
ufw --force enable
39 changes: 6 additions & 33 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,35 +1,20 @@
variable "aws_region" {
variable "region" {
type = string
}

variable "env" {
description = "The name of environment for Wireguard."
description = "The name of environment for WireGuard. Used to differentiate multiple deployments."
}

variable "ssh_key_id" {
description = "A SSH public key ID to add to the VPN instance."
}

variable "instance_type" {
default = "t2.micro"
default = "t3.nano"
description = "The machine type to launch, some machines may offer higher throughput for higher use cases."
}

variable "asg_min_size" {
default = 1
description = "We may want more than one machine in a scaling group, but 1 is recommended."
}

variable "asg_desired_capacity" {
default = 1
description = "We may want more than one machine in a scaling group, but 1 is recommended."
}

variable "asg_max_size" {
default = 1
description = "We may want more than one machine in a scaling group, but 1 is recommended."
}

variable "vpc_id" {
description = "The VPC ID in which Terraform will launch the resources."
}
Expand All @@ -40,7 +25,7 @@ variable "subnet_ids" {
}

variable "wg_clients" {
type = list(object({ friendly_name = string, public_key = string, client_ip = string }))
type = list(object({ client_friendly_name = string, client_public_key = string, client_allowed_cidr = string }))
description = "List of client objects with IP and public key. See Usage in README for details."
}

Expand Down Expand Up @@ -73,13 +58,7 @@ variable "target_group_arns" {

variable "wg_server_private_key" {
type = string
default = null
description = "Wireguard server private key."
}

variable "ami_id" {
default = null # we check for this and use a data provider since we can't use it here
description = "The AWS AMI to use for the Wireguard server, defaults to the latest Ubuntu 20.04 AMI if not specified."
description = "WG server private key."
}

variable "wg_server_interface" {
Expand All @@ -90,7 +69,7 @@ variable "wg_server_interface" {
variable "use_route53" {
type = bool
default = false
description = "Whether to use SSM to store Wireguard Server private key."
description = "Whether to use Route53"
}

variable "route53_hosted_zone_id" {
Expand All @@ -104,9 +83,3 @@ variable "route53_record_name" {
default = null
description = "Route53 Record name."
}

variable "route53_geo" {
type = any
default = null
description = "Route53 Geolocation config."
}
4 changes: 1 addition & 3 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
terraform {
required_version = ">= 0.13.5"

backend "s3" {}

required_providers {
aws = {
source = "hashicorp/aws"
Expand All @@ -12,5 +10,5 @@ terraform {
}

provider "aws" {
region = var.aws_region
region = var.region
}

0 comments on commit ad3a539

Please sign in to comment.