Giter VIP home page Giter VIP logo

wireguard-private-networking's Introduction

Private server to server network with ansible and wireguard

Ansible Role

This role allowes you to deploy a fast, secure and provider agnostic private network between multiple servers. This is usefull for providers that do not provide you with a private network or if you want to connect servers that are spread over multiple regions and providers.

How

The role installs wireguard on Debian or Ubuntu, creates a mesh between all servers by adding them all as peers and configures the wg-quick systemd service.

Installation

Installation can be done using ansible galaxy:

$ ansible-galaxy install mawalu.wireguard_private_networking

Setup

Install this role, assign a vpn_ip variable to every host that should be part of the network and run the role. Plese make sure to allow the VPN port (default is 5888) in your firewall. Here is a small example configuration:

Optionally, you can set a public_addr on each host. This address will be used to connect to the wireguard peer instead of the address in the inventory. Useful if you are configuring over a different network than wireguard is using. e.g. ansible connects over a LAN to your peer.

# inventory host file

wireguard:
  hosts:
    1.1.1.1:
      vpn_ip: 10.1.0.1/32
      public_addr: "example.com" # optional
    2.2.2.2:
      vpn_ip: 10.1.0.2/32
# playbook

- name: Configure wireguard mesh
  hosts: wireguard
  remote_user: root
  roles:
    - mawalu.wireguard_private_networking
# playbook (with client config)
- name: Configure wireguard mesh
  hosts: wireguard
  remote_user: root
  vars:
    client_vpn_ip: 10.1.0.100
    client_wireguard_path: "~/my-client-config.conf"
  roles:
    - mawalu.wireguard_private_networking

Additional configuration

There are a small number of role variables that can be overwritten.

wireguard_port: "5888" # the port to use for server to server connections
wireguard_path: "/etc/wireguard" # location of all wireguard configurations

wireguard_network_name: "private" # the name to use for the config file and wg-quick

wireguard_mtu: 1500 # Optionally a MTU to set in the wg-quick file. Not set by default. Can also be set per host

debian_enable_backports: true # if the debian backports repos should be added on debian machines

# Raspberry Pi Zero support
# Needs kernel headers and manual compilation of wireguard, opt in via flag, install `community.general` collection
# Caution: Might trigger a reboot.
allow_build_from_source: true

wireguard_sources_path: "/var/cache" # Location to clone the WireGuard sources if manual build is required

client_vpn_ip: "" # if set an additional wireguard config file will be generated at the specified path on localhost
client_wireguard_path: "~/wg.conf" # path on localhost to write client config, if client_vpn_ip is set

# a list of additional peers that will be added to each server
wireguard_additional_peers:
  - comment: martin
    ip: 10.2.3.4
    key: your_wireguard_public_key
  - comment: other_network
    ip: 10.32.0.0/16
    key: their_wireguard_public_key
    keepalive: 20 
    endpoint: some.endpoint:2230 

wireguard_post_up: "iptables ..." # PostUp hook command
wireguard_post_down: "iptables"   # PostDown hook command

Testing

This role has a small test setup that is created using molecule. To run the tests follow the molecule install guide, ensure that a docker daemon runs on your machine and execute molecule test.

Contributing

Feel free to open issues or MRs if you find problems or have ideas for improvements. I'm especially open for MRs that add support for additional operating systems and more tests.

wireguard-private-networking's People

Contributors

dsofeir avatar fgierlinger avatar jmlx42 avatar mawalu avatar radek-sprta avatar rngkll avatar thaasoph avatar timdev avatar tobiasdierich avatar vdksystem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wireguard-private-networking's Issues

Missing resolvconf dependency

Hi,

On Ubuntu 20.04 (and Debian ?), the wg-quick requires resolvconf to run. But for some reason, apt does not install it as a dependency.

We're using the following workaround:

  pre_tasks:
    - name: Install Wireguard dependencies
      apt:
        name: resolvconf
  roles:
    - mawalu.wireguard_private_networking

I think we should add this to this role for now and create an upstream issue on the wg-quick bug tracker regarding the missing dependency to resolvconf.

Add support for the Ansible --check option

Hi,

I looks like the Read private key task fails in check mode (ansible-playbook --check). Presumably because the private key is not actually created in the first place in check mode:

TASK [mawalu.wireguard_private_networking : Read private key] ******************
ok: [vpn-server]
fatal: [minecraft]: FAILED! => {"changed": false, "msg": "file not found: /etc/wireguard/privatekey"}

The task is ok for the vpn-server host because it was already provisioned and the /etc/wireguard/privatekey file does exist. Which is not the case for the minecraft host: it's a new machine.

I'll open a PR to fix this.

Client-config stuff appears broken

The idea behind PR#7 seems nice, but it appears to be pretty broken. Adding client_wireguard_path to vars causes the playbook to fail, complaining that:

FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'client_vpn_ip' is undefined"}

And indeed, client_vpn_ip is indeed referenced in the templates:

$ git grep client_vpn_ip
templates/client.conf.j2:Address = {{ client_vpn_ip }}
templates/interface.conf.j2:AllowedIPs = {{ client_vpn_ip }}

... but isn't set or documented anywhere.

Since there's no sane default for client_vpn_ip, I'll make a PR that introduces an empty default for client_vpn_ip, and reverts to the previous default of client_wireguard_path: ~/wg.conf. Tasks that are currently conditional on client_wireguard_path having a non-zero length will become conditional on client_vpn_ip having a non-zero length.

Allow to define the AllowedIPs field globally or for each peer

Hello,

Here is the setup we need:

  • A remote Wireguard VPN mesh hosted in the cloud.
  • Some clients (laptops for example) connecting to the VPN and access all the nodes in the mesh.

Here is an example config:

vpn:
  hosts:
    vpn-server:
      vpn_ip: 10.1.0.1/32
    minecraft:
      vpn_ip: 10.1.0.253/32

and the playbook:

- name: Configure VPN network
  hosts: vpn
  remote_user: root
  roles:
    - mawalu.wireguard_private_networking

For a laptop to connect to the network, we use the following Interface config:

[Interface]
PrivateKey = {private_key}
Address = {address}/24
DNS = 10.1.0.1

[Peer]
PublicKey = {WIREGUARD_SERVER_PUBLIC_KEY}
Endpoint = vpn.hostname.com:5888
PersistentKeepalive = 15
AllowedIPs = 0.0.0.0/0, ::/0

But the result is as follow:

  • The nodes of the VPN mesh listed above in the VPN group can connect to to each other, including to the VPN server.
  • But the laptops using the interface above cannot connect to the other nodes in the mesh. Yet they can connect to each other.

As of today, here is what the template contains:

{% for node in play_hosts %}
[Peer]
PublicKey = {{ hostvars[node].public.content | b64decode | trim }}
AllowedIPs = {{ hostvars[node].vpn_ip }}
Endpoint = {{ hostvars[node]['public_addr'] | default(hostvars[node]['ansible_host']) | default(hostvars[node]['inventory_hostname']) }}:{{ wireguard_port }}
PersistentKeepalive = 25

{% endfor %}

I suspect that AllowedIPs = {{ hostvars[node].vpn_ip }} restricts peers to connect to the other listed peers in the conf file. So all the peers must be listed in the conf file. Which is unpractical.

Wouldn't it better to allow for a global/per-host wireguard_alled_ips variable? This way it could be set to 0.0.0.0/0, ::/0 and allow any node to connect to any node.

Install on debian fails after new proxmox update

Getting error message after new update
{"msg": "The conditional check 'is_proxmox.stat.exists' failed. The error was: error while evaluating conditional (is_proxmox.stat.exists): 'dict object' has no attribute 'stat'\n\nThe error appears to be in '/home/<user>/.ansible/roles/mawalu.wireguard_private_networking/tasks/main.yml': line 24, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Install linux headers when debian proxmox\n ^ here\n"}

Error encountered with "Generate configs" task when default "client_wireguard_path" value is used

Issue

I have encountered the following error when applying the role using the default value for variable client_wireguard_path:

TASK [mawalu.wireguard-private-networking : Generate configs] *************************
fatal: [host.example.com]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'content'"}

Cause

The default value for client_wireguard_path is "~/wg.conf" which is set in defaults/main.yml. I believe the error occurs because the test in the template interface.conf.j2 (client_wireguard_path | length > 0) never evaluates to false because the variable client_wireguard_path will never have a zero length.

Solution

Setting variable client_wireguard_path = "" in defaults/main.yml resolves the issue

Add support for the DNS field in the Interface section

Hello,

Thank you for the great work!
I would like to open a PR to add the possibility to customize the DNS field of the Interface section of the interface.conf.j2 template with a wireguard_dns Ansible var.

Would you accept and merge such PR?

Right now I'm using the following task as a workaround:

- lineinfile:
    line: "DNS = {{ vpn_ip | ipaddr('address') }}"
    state: present
    insertafter: "PrivateKey = .*"
    path: "{{ client_wireguard_path }}"
  vars:
    ansible_connection: local
  become: no
  run_once: true
  when:
    - client_vpn_ip is defined
    - client_vpn_ip | length > 0
  delegate_to: localhost

Regards,

Remove dependency to community.general when allow_build_from_source: false

Hello,

As of today, the community.general collection is required whether allow_build_from_source is true or false. In order to avoid broken dependencies, we download and store the roles/collections in our git repository. And community.general is a pretty big dependency.

I was wondering if there was a way to eliminate the requirement for this collection when allow_build_from_source is false.

Regards,

lsb-release and ca-certificates are Prerequisites

Hi,

i noticed that this role fails when the packages lsb-release and ca-certificates are not installed for obvious reasons.
Not exactly sure how i ended up with those missing but if you could add those as prerequisites maybe somebody else using a weird installation method might appreciate it.

kind regards,

Stefan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.