first pass at a wireguard-as vpn module
parent
6cf51ee982
commit
d6a0a96841
@ -0,0 +1,7 @@
|
||||
# WireGuard Access Server
|
||||
|
||||
TODO
|
||||
|
||||
## Helpful links
|
||||
|
||||
https://fabianlee.org/2017/05/21/golang-running-a-go-binary-as-a-systemd-service-on-ubuntu-16-04/
|
@ -0,0 +1,35 @@
|
||||
module "vpn_asg" {
|
||||
source = "terraform-aws-modules/autoscaling/aws"
|
||||
|
||||
name = "${var.prefix}-vpn"
|
||||
image_id = data.aws_ami.ubuntu.image_id
|
||||
instance_type = var.instance_type
|
||||
security_groups = [aws_security_group.vpn.id]
|
||||
iam_instance_profile = aws_iam_instance_profile.vpn.name
|
||||
asg_name = "${var.prefix}-vpn"
|
||||
lc_name = "${var.prefix}-vpn"
|
||||
health_check_type = "EC2"
|
||||
vpc_zone_identifier = var.public_subnets
|
||||
min_size = 1
|
||||
max_size = 1
|
||||
desired_capacity = 1
|
||||
wait_for_capacity_timeout = 0
|
||||
default_cooldown = 120
|
||||
health_check_grace_period = 120
|
||||
key_name = var.key_name
|
||||
|
||||
|
||||
user_data = templatefile("${path.module}/files/vpn_user_data.sh", {
|
||||
EIP_ID = aws_eip.vpn.id
|
||||
REGION = data.aws_region.current.name
|
||||
CONFIG_BUCKET = aws_s3_bucket.configs.id
|
||||
WIREGUARD_INTERFACE = var.wireguard_interface
|
||||
WIREGUARD_PORT = var.wireguard_vpn_port
|
||||
})
|
||||
|
||||
tags_as_map = {
|
||||
"Name" = "${var.prefix}-vpn"
|
||||
"App" = "WireGuard"
|
||||
"Terraform" = "true"
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
# Elastic IP attachment
|
||||
INSTANCE_ID=$(curl -s 169.254.169.254/latest/meta-data/instance-id)
|
||||
aws ec2 associate-address --allocation-id ${EIP_ID} --instance-id $INSTANCE_ID --region ${REGION}
|
||||
|
||||
|
||||
# Install WireGuard and other dependencies
|
||||
apt-get install -y software-properties-common
|
||||
add-apt-repository -y ppa:wireguard/wireguard
|
||||
apt-get update
|
||||
apt-get install -y "linux-headers-$(uname -r)"
|
||||
apt-get install -y wireguard iptables resolvconf awscli git sudo
|
||||
|
||||
# Initialization WireGuard configs
|
||||
aws s3api head-object --bucket ${CONFIG_BUCKET} --key wg0.conf
|
||||
if [[ "$?" -eq 0 ]]; then
|
||||
echo "[+] Copying existing WireGuard config to system from s3://${CONFIG_BUCKET}"
|
||||
aws s3 cp s3://${CONFIG_BUCKET}/wg0.conf /etc/wireguard/wg0.conf
|
||||
else
|
||||
echo "[+] Generating new WireGuard config"
|
||||
wg genkey | tee /opt/privkey | wg pubkey > /opt/pubkey
|
||||
cat << EOF > /etc/wireguard/wg0.conf
|
||||
[Interface]
|
||||
Address = ${WIREGUARD_INTERFACE}
|
||||
ListenPort = ${WIREGUARD_PORT}
|
||||
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;
|
||||
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE;
|
||||
PrivateKey = $(cat /opt/privkey)
|
||||
SaveConfig = true
|
||||
EOF
|
||||
aws s3 cp /etc/wireguard/wg0.conf s3://${CONFIG_BUCKET}/wg0.conf
|
||||
fi
|
||||
|
||||
|
||||
# Install Rust and app as a systemd service
|
||||
sudo apt install build-essential -y
|
||||
|
||||
cat << EOF > /opt/install_app.sh
|
||||
#!/bin/bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | RUSTUP_HOME=~/.rustup sh -s -- -y
|
||||
source ~/.cargo/env
|
||||
git clone https://github.com/lalanza808/wgas-rs ~/wgas-rs
|
||||
cd ~/wgas-rs
|
||||
rustup override set nightly
|
||||
cargo build --release
|
||||
EOF
|
||||
chmod +x /opt/install_app.sh
|
||||
sudo -u ubuntu /opt/install_app.sh
|
||||
useradd wgas-rs -s /sbin/nologin -M
|
||||
cat << EOF > /lib/systemd/system/wgas-rs.service
|
||||
[Unit]
|
||||
Description=WireGuard Access Server Service
|
||||
ConditionPathExists=/home/ubuntu/wgas-rs/target/release/wgas-rs
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=wgas-rs
|
||||
Group=wgas-rs
|
||||
LimitNOFILE=1024
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
startLimitIntervalSec=60
|
||||
|
||||
WorkingDirectory=/home/ubuntu/wgas-rs
|
||||
ExecStart=/home/ubuntu/wgas-rs/target/release/wgas-rs
|
||||
|
||||
# make sure log directory exists and owned by syslog
|
||||
PermissionsStartOnly=true
|
||||
ExecStartPre=/bin/mkdir -p /var/log/wgas-rs
|
||||
ExecStartPre=/bin/chown syslog:adm /var/log/wgas-rs
|
||||
ExecStartPre=/bin/chmod 755 /var/log/wgas-rs
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=wgas-rs
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
chmod 755 /lib/systemd/system/wgas-rs.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable wgas-rs
|
||||
systemctl start wgas-rs
|
@ -0,0 +1,77 @@
|
||||
data "aws_iam_policy_document" "vpn_assume_role" {
|
||||
statement {
|
||||
actions = ["sts:AssumeRole"]
|
||||
|
||||
principals {
|
||||
type = "Service"
|
||||
identifiers = [
|
||||
"ec2.amazonaws.com"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "vpn" {
|
||||
statement {
|
||||
actions = [
|
||||
"route53:ListHostedZones",
|
||||
"route53:GetChange"
|
||||
]
|
||||
resources = [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
statement {
|
||||
actions = [
|
||||
"route53:ChangeResourceRecordSets"
|
||||
]
|
||||
resources = [
|
||||
"arn:aws:route53:::hostedzone/${data.aws_route53_zone.domain.zone_id}"
|
||||
]
|
||||
}
|
||||
statement {
|
||||
actions = [
|
||||
"ec2:AssociateAddress",
|
||||
"ec2:DescribeInstances",
|
||||
"ec2:DescribeNetworkInterfaces"
|
||||
]
|
||||
resources = [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
statement {
|
||||
actions = [
|
||||
"s3:Put*",
|
||||
"s3:Get*"
|
||||
]
|
||||
resources = [
|
||||
"${aws_s3_bucket.configs.arn}/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_policy" "vpn" {
|
||||
name_prefix = aws_iam_role.vpn.name
|
||||
description = "WireGuard VPN server policy for managing resources on AWS"
|
||||
policy = data.aws_iam_policy_document.vpn.json
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "vpn" {
|
||||
name_prefix = "${var.prefix}-vpn-"
|
||||
assume_role_policy = data.aws_iam_policy_document.vpn_assume_role.json
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "vpn" {
|
||||
role = aws_iam_role.vpn.name
|
||||
policy_arn = aws_iam_policy.vpn.arn
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "ssm" {
|
||||
role = aws_iam_role.vpn.name
|
||||
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
|
||||
}
|
||||
|
||||
resource "aws_iam_instance_profile" "vpn" {
|
||||
name = aws_iam_role.vpn.name
|
||||
role = aws_iam_role.vpn.name
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
data "aws_route53_zone" "domain" {
|
||||
name = var.domain_name
|
||||
}
|
||||
|
||||
data "aws_region" "current" {}
|
||||
|
||||
data "aws_caller_identity" "current" {}
|
||||
|
||||
data "aws_ami" "ubuntu" {
|
||||
most_recent = true
|
||||
|
||||
filter {
|
||||
name = "name"
|
||||
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
|
||||
}
|
||||
|
||||
filter {
|
||||
name = "virtualization-type"
|
||||
values = ["hvm"]
|
||||
}
|
||||
|
||||
owners = ["099720109477"] # Canonical
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
resource "aws_security_group" "vpn" {
|
||||
name_prefix = "${var.prefix}-vpn-"
|
||||
description = "Allow connectivity to and from the WireGuard VPN instance."
|
||||
vpc_id = var.vpc_id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "vpn_access" {
|
||||
type = "ingress"
|
||||
from_port = var.wireguard_vpn_port
|
||||
to_port = var.wireguard_vpn_port
|
||||
protocol = "udp"
|
||||
cidr_blocks = var.vpn_access_cidrs
|
||||
security_group_id = aws_security_group.vpn.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "management_access_80" {
|
||||
type = "ingress"
|
||||
from_port = 80
|
||||
to_port = 80
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.management_access_cidrs
|
||||
security_group_id = aws_security_group.vpn.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "management_access_8000" {
|
||||
type = "ingress"
|
||||
from_port = 8000
|
||||
to_port = 8000
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.management_access_cidrs
|
||||
security_group_id = aws_security_group.vpn.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "management_access_443" {
|
||||
type = "ingress"
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.management_access_cidrs
|
||||
security_group_id = aws_security_group.vpn.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "management_access_22" {
|
||||
type = "ingress"
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.management_access_cidrs
|
||||
security_group_id = aws_security_group.vpn.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "vpn_egress" {
|
||||
type = "egress"
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
security_group_id = aws_security_group.vpn.id
|
||||
}
|
||||
|
||||
resource "aws_eip" "vpn" {
|
||||
vpc = true
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
resource "aws_s3_bucket" "configs" {
|
||||
bucket_prefix = "${var.prefix}-config-"
|
||||
acl = "private"
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "config_policy" {
|
||||
statement {
|
||||
actions = [
|
||||
"s3:*"
|
||||
]
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = [
|
||||
aws_iam_role.vpn.arn
|
||||
]
|
||||
}
|
||||
resources = [
|
||||
"${aws_s3_bucket.configs.arn}/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_policy" "configs" {
|
||||
bucket = aws_s3_bucket.configs.id
|
||||
policy = data.aws_iam_policy_document.config_policy.json
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
variable "prefix" {
|
||||
default = "wireguard"
|
||||
description = "String to use as a prefix when naming resources"
|
||||
}
|
||||
|
||||
variable "domain_name" {
|
||||
description = "Domain name to use for setting up Route 53 records"
|
||||
}
|
||||
|
||||
variable "instance_type" {
|
||||
default = "t3.small"
|
||||
description = "EC2 instance type to provision for VPN server"
|
||||
}
|
||||
|
||||
variable "key_name" {
|
||||
description = "Key pair to use for provisioning EC2 instance"
|
||||
}
|
||||
|
||||
variable "vpn_access_cidrs" {
|
||||
default = ["0.0.0.0/0"]
|
||||
description = "IP addresses which should be able to connect to the VPN"
|
||||
type = list
|
||||
}
|
||||
|
||||
variable "management_access_cidrs" {
|
||||
default = []
|
||||
description = "IP addresses which should be able to reach the administrative interfaces (web/ssh)"
|
||||
type = list
|
||||
}
|
||||
|
||||
variable "wireguard_vpn_port" {
|
||||
default = 51820
|
||||
description = "Port to use for WireGuard VPN (udp)"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "ID of the VPC to deploy network resources into"
|
||||
}
|
||||
|
||||
variable "public_subnets" {
|
||||
description = "List of subnets for deploying WireGuard VPN servers into"
|
||||
}
|
||||
|
||||
variable "wireguard_interface" {
|
||||
default = "10.66.66.1/24"
|
||||
description = "VPN tunnel interface IP and CIDR"
|
||||
}
|
Loading…
Reference in New Issue