First commit

This commit is contained in:
Héctor Molinero Fernández 2020-01-26 11:59:13 +01:00
commit 3fcd038fdf
17 changed files with 377 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
**/packer_cache/*
**/packer_output/*
**/.terraform/*
*.tfstate
*.tfstate.*
override.tf
override.tf.json
*_override.tf
*_override.tf.json
crash.log

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.associations": {
"meta-data": "yaml",
"user-data": "yaml"
}
}

22
LICENSE.md Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
=====================
Copyright © 2020 Héctor Molinero Fernández
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

5
README.md Normal file
View File

@ -0,0 +1,5 @@
# WireGuard + Unbound
[WireGuard](https://www.wireguard.com) and [Unbound](https://unbound.net) setup with
[Packer](https://www.packer.io) and [Terraform](https://www.terraform.io) ready for deployment in
[Hetzner Cloud](https://www.hetzner.com).

2
http/seed/meta-data Normal file
View File

@ -0,0 +1,2 @@
instance-id: "instance0"
local-hostname: "localhost"

9
http/seed/user-data Normal file
View File

@ -0,0 +1,9 @@
#cloud-config
ssh_pwauth: true
disable_root: false
chpasswd: { list: ["root:toor"], expire: false }
runcmd:
- printf '%s\n' 'PermitRootLogin yes' >> /etc/ssh/sshd_config
- systemctl restart ssh.service

View File

@ -0,0 +1,4 @@
APT::Periodic::Enable "1";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";

View File

@ -0,0 +1,9 @@
Unattended-Upgrade::Origins-Pattern { "origin=*"; };
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::InstallOnShutdown "false";
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::MailOnlyOnError "false";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "05:30";

View File

@ -0,0 +1,9 @@
[sshd]
enabled = true
filter = sshd
banaction = ufw
backend = systemd
maxretry = 5
findtime = 10m
bantime = 10m
ignoreip = 127.0.0.1/8 ::1

View File

@ -0,0 +1,26 @@
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
ListenAddress 0.0.0.0
Port 22
UseDNS no
UsePAM yes
X11Forwarding no
AllowTcpForwarding yes
AllowGroups ssh-user
PermitRootLogin without-password
PermitEmptyPasswords no
PermitUserEnvironment no
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
GSSAPIAuthentication no
Subsystem sftp internal-sftp
LoginGraceTime 30
TCPKeepAlive yes
ClientAliveInterval 60
ClientAliveCountMax 5
PrintMotd yes
PrintLastLog yes
SyslogFacility AUTH
LogLevel INFO

View File

@ -0,0 +1,38 @@
server:
interface: 0.0.0.0
port: 53
root-hints: "/usr/share/dns/root.hints"
auto-trust-anchor-file: "/var/lib/unbound/root.key"
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: 10.10.10.0/24 allow
private-address: 0.0.0.0/8
private-address: ::ffff:0.0.0.0/104
private-address: 10.0.0.0/8
private-address: ::ffff:10.0.0.0/104
private-address: 100.64.0.0/10
private-address: ::ffff:100.64.0.0/106
private-address: 127.0.0.0/8
private-address: ::ffff:127.0.0.0/104
private-address: 169.254.0.0/16
private-address: ::ffff:169.254.0.0/112
private-address: 172.16.0.0/12
private-address: ::ffff:172.16.0.0/108
private-address: 192.168.0.0/16
private-address: ::ffff:192.168.0.0/112
private-address: ::/128
private-address: ::1/128
private-address: fc00::/7
private-address: fd00::/8
private-address: fe80::/10
hide-identity: yes
hide-version: yes
qname-minimisation: yes
cache-min-ttl: 60
cache-max-ttl: 3600
prefetch: yes
prefetch-key: yes
verbosity: 1
val-log-level: 1
#include: "/etc/unbound/unbound.conf.d/*.conf"

View File

@ -0,0 +1,9 @@
[Interface]
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Address = 10.10.10.2/32
DNS = 10.10.10.1
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = XXX.XXX.XXX.XXX:80

View File

@ -0,0 +1,3 @@
#[Peer]
#PublicKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#AllowedIPs = 10.10.10.2/32

View File

@ -0,0 +1,25 @@
[Interface]
Address = 10.10.10.1/24
ListenPort = 80
# Load keys
PostUp = [ -e '/etc/wireguard/%i-privatekey' ] || (umask 077 && wg genkey > '/etc/wireguard/%i-privatekey')
PostUp = [ -e '/etc/wireguard/%i-publickey' ] || (umask 022 && wg pubkey < '/etc/wireguard/%i-privatekey' > '/etc/wireguard/%i-publickey')
PostUp = wg set '%i' private-key '/etc/wireguard/%i-privatekey'
# Load peers
PostUp = [ -e '/etc/wireguard/%i-peers.conf' ] && wg addconf '%i' '/etc/wireguard/%i-peers.conf'
# Store the internet-facing interface in a file for later use
PostUp = ip route show default | awk '/^default/{print $5}' > '/etc/wireguard/%i-iface'
# Enable IPv4/IPv6 forwarding
PostUp = grep -Fxq '1' /proc/sys/net/ipv4/ip_forward || printf 1 > /proc/sys/net/ipv4/ip_forward
PostUp = grep -Fxq '1' /proc/sys/net/ipv6/conf/all/forwarding || printf 1 > /proc/sys/net/ipv6/conf/all/forwarding
PostUp = grep -Fxq '1' /proc/sys/net/ipv6/conf/default/forwarding || printf 1 > /proc/sys/net/ipv6/conf/default/forwarding
# Allow packet forwarding on the WireGuard interface
PostUp = iptables -A FORWARD -i '%i' -j ACCEPT && iptables -t nat -A POSTROUTING -o "$(cat '/etc/wireguard/%i-iface')" -j MASQUERADE
PostUp = ip6tables -A FORWARD -i '%i' -j ACCEPT && ip6tables -t nat -A POSTROUTING -o "$(cat '/etc/wireguard/%i-iface')" -j MASQUERADE
PostDown = iptables -D FORWARD -i '%i' -j ACCEPT && iptables -t nat -D POSTROUTING -o "$(cat '/etc/wireguard/%i-iface')" -j MASQUERADE
PostDown = ip6tables -D FORWARD -i '%i' -j ACCEPT && ip6tables -t nat -D POSTROUTING -o "$(cat '/etc/wireguard/%i-iface')" -j MASQUERADE
# Allow access to the local DNS server on the WireGuard interface
PostUp = iptables -A INPUT -i '%i' -p tcp --dport 53 -j ACCEPT && iptables -A INPUT -i '%i' -p udp --dport 53 -j ACCEPT
PostUp = ip6tables -A INPUT -i '%i' -p tcp --dport 53 -j ACCEPT && ip6tables -A INPUT -i '%i' -p udp --dport 53 -j ACCEPT
PostDown = iptables -D INPUT -i '%i' -p tcp --dport 53 -j ACCEPT && iptables -D INPUT -i '%i' -p udp --dport 53 -j ACCEPT
PostDown = ip6tables -D INPUT -i '%i' -p tcp --dport 53 -j ACCEPT && ip6tables -D INPUT -i '%i' -p udp --dport 53 -j ACCEPT

34
start-qemu.sh Executable file
View File

@ -0,0 +1,34 @@
#!/bin/sh
set -eu
export LC_ALL=C
SRC_DIR=$(dirname "$(readlink -f "$0")")
TMP_DIR=$(mktemp -d)
trap 'rm -rf "${TMP_DIR:?}"' EXIT
CLOUDIMG_DISK=${SRC_DIR:?}/packer_output/wireguard.qcow2
SNAPSHOT_DISK=${TMP_DIR:?}/cloudinit-snapshot.qcow2
USERDATA_DISK=${TMP_DIR:?}/cloudinit-seed.img
USERDATA_YAML=${TMP_DIR:?}/user-data
# Create a snapshot image to preserve the original cloud-image
qemu-img create -b "${CLOUDIMG_DISK:?}" -f qcow2 "${SNAPSHOT_DISK:?}"
qemu-img resize "${SNAPSHOT_DISK:?}" +2G
# Create a seed image with metadata using cloud-localds
printf '%s\n' '#cloud-config' 'runcmd: ["ssh-import-id gh:hectorm"]' > "${USERDATA_YAML:?}"
cloud-localds "${USERDATA_DISK:?}" "${USERDATA_YAML:?}"
# Remove keys from the known_hosts file
ssh-keygen -R '[127.0.0.1]:2222'
ssh-keygen -R '[localhost]:2222'
# Launch VM
kvm \
-smp 1 -m 512 \
-nographic -serial mon:stdio \
-device e1000,netdev=n0 \
-netdev user,id=n0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-drive file="${SNAPSHOT_DISK:?}",if=virtio,format=qcow2 \
-drive file="${USERDATA_DISK:?}",if=virtio,format=raw

131
wireguard.pkr.hcl Normal file
View File

@ -0,0 +1,131 @@
source "hcloud" "main" {
image = "ubuntu-18.04"
server_type = "cx11"
location = "fsn1"
server_name = "wireguard-{{timestamp}}"
snapshot_name = "wireguard-{{timestamp}}"
snapshot_labels {
service = "wireguard"
}
ssh_port = "22"
ssh_username = "root"
ssh_timeout = "10m"
}
source "qemu" "main" {
iso_url = "https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img"
iso_checksum_url = "https://cloud-images.ubuntu.com/bionic/current/SHA256SUMS"
iso_checksum_type = "sha256"
disk_image = true
vm_name = "wireguard.qcow2"
http_directory = "./http/"
output_directory = "./packer_output/"
accelerator = "kvm"
cpus = 1
memory = 512
headless = true
qemuargs {
qemuargs = ["-smbios", "type=1,serial=ds=nocloud-net;s=http://{{.HTTPIP}}:{{.HTTPPort}}/seed/"]
}
net_device = "virtio-net"
format = "qcow2"
disk_size = "4G"
disk_interface = "virtio"
disk_compression = false
ssh_port = "22"
ssh_username = "root"
ssh_password = "toor"
ssh_timeout = "10m"
shutdown_command = "shutdown -P now"
}
build {
sources = [
"source.hcloud.main"
]
provisioner "file" {
direction = "upload"
source = "./rootfs/"
destination = "/"
}
provisioner "shell" {
inline = [
"chmod 644 /etc/apt/apt.conf.d/20auto-upgrades",
"chmod 644 /etc/apt/apt.conf.d/50unattended-upgrades",
"chmod 644 /etc/fail2ban/jail.d/sshd.conf",
"chmod 644 /etc/ssh/sshd_config",
"chmod 644 /etc/unbound/unbound.conf",
"chmod 644 /etc/wireguard/client-sample.conf",
"chmod 644 /etc/wireguard/wg0-peers.conf",
"chmod 600 /etc/wireguard/wg0.conf"
]
}
provisioner "shell" {
environment_vars = [
"DEBIAN_FRONTEND=noninteractive"
]
inline = [
"printf 'deb http://ppa.launchpad.net/wireguard/wireguard/ubuntu/ bionic main\n' > /etc/apt/sources.list.d/wireguard.list",
"apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E1B39B6EF6DDB96564797591AE33835F504A1A25",
"apt-get update",
"apt-get upgrade -yo DPkg::options::=--force-confold",
"apt-get install -yo DPkg::options::=--force-confold dns-root-data fail2ban ufw unattended-upgrades unbound",
"apt-get install -yo DPkg::options::=--force-confold linux-headers-$(uname -r) openresolv wireguard",
"apt-get install -yo DPkg::options::=--force-confold htop iperf3 qrencode nano ssh-import-id",
"apt-get autoremove -y"
]
}
provisioner "shell" {
inline = [
"systemctl disable --now systemd-resolved.service",
"unlink /etc/resolv.conf && printf 'nameserver 127.0.0.1\n' > /etc/resolv.conf",
"systemctl enable --now unbound.service unbound-resolvconf.service",
]
}
provisioner "shell" {
inline = [
"systemctl enable --now fail2ban.service ufw.service unattended-upgrades.service",
"systemctl enable --now wg-quick@wg0.service"
]
}
provisioner "shell" {
inline = [
"ufw --force enable",
"ufw default deny incoming",
"ufw default allow outgoing",
"ufw allow from any to any port 22 proto tcp",
"ufw allow from any to any port 80 proto udp"
]
}
provisioner "shell" {
inline = [
"groupadd -r ssh-user",
"usermod -aG ssh-user root",
"passwd -d root"
]
}
provisioner "shell" {
inline = [
"rm -f /etc/ssh/ssh_host_*key*",
"rm -f /etc/wireguard/*-*key",
"rm -f /etc/wireguard/*-iface",
"rm -rf /var/lib/apt/lists/*"
]
}
}

35
wireguard.tf Normal file
View File

@ -0,0 +1,35 @@
variable "hcloud_token" {
type = string
}
provider "hcloud" {
token = var.hcloud_token
}
data "hcloud_image" "wireguard" {
with_selector = "service=wireguard"
most_recent = true
}
data "hcloud_ssh_key" "hectorm" {
fingerprint = "a1:92:f2:2b:57:5e:cc:9c:5a:0c:f4:33:79:db:b6:56"
}
resource "hcloud_server" "wireguard" {
name = "wireguard"
image = data.hcloud_image.wireguard.id
server_type = "cx11"
location = "fsn1"
keep_disk = true
backups = false
labels = {
service = "wireguard"
}
ssh_keys = [
data.hcloud_ssh_key.hectorm.id
]
}
output "wireguard_server_ipv4_address" {
value = hcloud_server.wireguard.ipv4_address
}