Featured image of post Wireguard Ansible

Wireguard Ansible

Ansible плейбуки для развёртывания Wireguard

Введение

Wireguard – обалденный, простой VPN, который уже включён в состав ядра. Очень мощный и простой инструмент. Ставиться в разы проще чем OpenVPN.

Постановка задачи

  • Я живу в Украине и, к сожалению, у нас заблокированы некоторые Интернет ресурсы, а доступ иногда нужен.
  • Хочется иметь возможность достучаться по удалённому доступу с телефона или чужого компьютера до домашнего сервера.
  • Хочется, чтобы на ПК проксировался трафик только на домены из списка, а не вообще всё.

Вот с такими запросами я стал работать. Для себя, всё для себя. Больше пока никому не нужен, хотя на GitHub выложил. Выложил - это тоже громко сказано. Ни документации, ничего! Да! Лень просто написать… Ну да ладно.

Обзор решения

Использовал Ansible, который может настроить сразу сеть. Что умеет:

  1. Автоматическая генерация ключей
  2. Использование константного preshared ключа для всех соединений
  3. Возможность прописывать свои AllowedIPs
  4. Возможность добавлять пиров со статически прописанными ключами (на телефоне-то Ansible не запустить)
  5. Автоматический подбор свободных rt_table ID и fwmark-ов
  6. Возможность за один запуск поднимать больше одной сети на тех же машинах!

Чего не умеет.

  1. Отдельный запуск на одном или подгруппе хостов. Только на всём сразу.

Разбираем переменные Ansible

Пропишем подсети и их имена. Создадим две - одна для дома, вторая для проксирования трафика.

wireguard_networks:
  home: 10.0.0.0/24
  vpn: 10.0.1.0/24

У нас есть сервер с публичным IP и вот он-то послужит точкой подключения для всех. Топология - звезда.

# это переменнные для отдельно взятого хоста - сервера
wireguard_enabled: yes
# wireguard-tools поставили уже, по-этому тут это выключаем
wireguard_install_tools: no
# список пиров
wireguard_peers:
  # для домашней сети
  home:
    # пиров возьми из этого же инвентори
    inventory:
      # первый пир это тот, на котором мы Ansible запускаем
      - hostname: localhost
      # а второй, имеет inventory_hostname home_server
      - hostname: home_server
        # и поддерживай сеть, чтобы всегда можно было достучаться,
        # потому что сервер за NAT-ом
        keepalive_seconds: 25
  # вторую сеть только с телефона и ПК использовать будем
  vpn:
    inventory:
      # добавим в пиры ПК
      - hostname: localhost
    manual:
      # и телефон, но для него придётся всё прописать руками
      - name: Redmi Note 7
        public_key: e4Ryxp2/j0bPRZvCDhqZ+FHLf/XIsWMcodNPBOIuTwI=
        preshared_key: rnVugG3bCwPCyg73C9pavNQ/0B4I9gPnN1zD0Gd35zI=
        # телефон будет с адресом 10.0.0.10, по этому
        # добавим к нему route (по факту так, хоть и назвыается
        # allowed ips) чтобы все в сети знали, что по этому адресу к 
        # этому пиру идти
        allowed_ips:
          - 10.0.0.10/32
# пропишем адреса и подсети для сервака
# пусть он будет везде первым
wireguard_addresses:
  home: 10.0.0.1/24
  vpn: 10.0.1.1/24
# ну и выберем порты, по которым он должен слушать
# для остальных можно не указывать - не важно, а вот
# для сервера лучше всё сразу прописать статикой
# чтобы ничего не было перегенерено если что
# и не нужно было перенастраивать всех клиентов
# на новые креды сервера
wireguard_ports:
  home: 2000
  vpn: 3000
# включаем маскарад, чтобы сервер через себя в Интернет
# выпускал трафик пиров как gateway
wireguard_masquarade:
  vpn: auto
# и для сети VPN сразу прописываем ключи, опять же
# чтобы других клиентов не перенастраивать если что
wireguard_keys:
  vpn: 
    private: EHWmPnjglykitb51N3GKb55KdfRCSL/Cutx0dWa4h3g=
    public: X/RwXVxg7HkEK73icJwWOwT/K8CaKRyFNZqocM8ToAc=

А теперь укажем переменные домашнего ПК.

# и опять включем роль явным образом
wireguard_enabled: yes
wireguard_peers:
  vpn:
    inventory:
      # из пиров в сети VPN только наш публичный сервер
      - hostname: public_host
        # у нас есть домен, который указывает на сервер чтобы адрес не запоминать
        endpoint: vpn.example.com
        # направляем через VPN весь трафик, и тут важно понимать,
        # что мы не весь трафик системы пускаем через wireguard
        # мы говорим wireguard-у на хосте, что в эту сетку пускай
        # всё, что к тебе конкретно пришло на выход и не подходит
        # в другие сети по более узким правилам
        allowed_ips:
          - 0.0.0.0/0
          - ::0
        keepalive_seconds: 25
  home:
    inventory:
      # точкой связи для домашней сети является он же
      - hostname: public_host
        endpoint: home.example.com
        keepalive_seconds: 25
        allowed_ips:
          # а в путях прописываем только подсеть домашней сети
          - "{{ wireguard_networks.home }}"
# домашний ПК везде будет вторым
wireguard_addresses:
  home: 10.0.0.2/24
  vpn: 10.0.1.2/24
# и включаем проксирование отдельных доменов через сеть VPN
wireguard_proxy_domains:
  vpn:
    list:
    - site.we.want.access
    - another.one

Ну и домашний сервер, просто должен быть доступен. В VPN ему ни к чему.

# тут я надеюсь уже всё понятно
wireguard_enabled: yes
wireguard_peers:
  home:
    inventory:
      - hostname: public_host
        endpoint: home.example.com
        allowed_ips:
          - "{{ wireguard_networks.home }}"
        keepalive_seconds: 25
wireguard_addresses:
  home: 10.0.0.3/24

Итог

С любого пира на любой есть доступ в пределах сети. Трафик находит свой путь через публичный сервер. Всё работает. Померял iperf-ом, из 80 Мбит, Wireguard отдаёт ~60 - как по мне, так это блестящий результат!

Licensed under Apache License, Version 2.0
Обновлено Nov 16, 2021 20:14 +0200
comments powered by Disqus
All rights reserved
Создано при помощи Hugo
Тема Stack, дизайн Jimmy