Купил я значит себе домой Raspberri Pi 4B и думаю, что бы с ней такого сделать.
Первым делом настроил блокировщик рекламы по DNS для домашней сети, но это совсем просто, даже описывать не буду, просто оставлю ссылку на проект: https://github.com/0xERR0R/blocky, рекомендую, гораздо лучше, чем Pi-Hole в плане производительности.
Но этого мне показалось мало для девайса стоимостью $100. Да-да, со всеми комплектующими: корпусом, зарядкой, переходником micro HDMI -> HDMI, SD картой и радиаторами это не так дешево, как казалось мне изначально.
Мне пришла мысль настроить домашний VPN, чтоб в путешествиях можно было подключаться к домашней сети, ну и использовать домашний интернет как прокси. Сначала подумал взять старый добрый IPSec, но с его настройкой как-то много возни, нормальных готовых ansible ролей я не нашел, плюс захотелось попробовать новомодный Wireguard.
Но для того, чтобы подключиться к домашнему интернету, нужно знать внешний IP, у меня все-таки серый IP за NAT, а внешний IP постоянно меняется.
Решение — Dynamic DNS. Мой роутер совсем тупой простой и не поддерживает Dynamic DNS в своей прошивке, поэтому я решил настроить его самостоятельно на Raspberry PI.
Т.к. я начал учить язык программирования Rust, то выбор пал именно на него. Для начала я пошел на Github в поисках готового проекта. Неудивительно, что проектов оказалось довольно много. Выбрав самый простой и элегантный (нам мой вкус), я решил немного модифицировать его под свои нужды. Критерий выбора был: минимум зависимостей, никаких баз данных или кэшей, маленькая кодовая база.
Для начала, что представляем из себя этот проект? Он узнает внешний ipv4 и ipv6 адреса с помощью DNS Cloudflare, кстати, я даже не знал, что так вообще можно было.
Пример команды:
dig @1.1.1.1 ch txt whoami.cloudflare +short
Потом эти IP адреса записываются, как A и AAA DNS адреса указанного домена, управляемого опять же Cloudlare. Да, у Cloudflare есть бесплатный DNS хостинг, если кто не знал.
Что я изменил?
Во-первых, в изначальном решении обновлялся коренной домен, например, example.com
. Мне это не подходило, я хотел использовать домен вида vpn.example.com
Во-вторых, мне не нравилось, что не было предусмотрено никакого кеширования. Даже если IP адрес не изменился, все равно делались запросы в API Cloudflare.
Мои изменения можете посмотреть здесь. Я изменил логику записи DNS домена и добавил кеширование в файл. Также я скомпилировал код под aarch64 (arm64), чтоб он запускался на Raspberry Pi.
Простой пример использования этого скрипта в кроне:
*/5 * * * * API_TOKEN=<YOUR-CLOUDFLARE-TOKEN> DOMAIN=vpn.example.com /usr/local/bin/ddns-cloudflare >> /var/log/ddns-cloudflare.log 2>&1
Еще я сделал примитивную ansible роль для автоматизации установки этого Dynamic DNS решения.
Итак, динамический DNS настроен и теперь можно приступать к настройке VPN. Сначала, было бы неплохо ознакомиться с самим Wireguard, как он работает, почему набирает популярность и пр.
Почитав некоторое количество статей я вынес для себя следующие тезисы:
- кодовая база wireguard минимальна, около 4000 строк (на момент написания статьи), по сравнению со StrongSwan, где их около 400000. Это впечатляет.
- wireguard использует UDP протокол
- за счет использования определенных техник шифрования он быстрее других VPN протоколов
- каждый клиент должен быть явно разрешен на сервере
- авторизация происходит только по приватным ключам, уникальным для каждого узла сети (клиента), никаких паролей и сертификатов
- клиентские приложения есть для любых устройств, в частности, я установил его на свой iPhone
- настройка довольно простая и удобная, особенно на клиенте — отсканировал QR код и готово
Более подробно про сам протокол и его реализацию вы можете прочитать на сайте Wireguard. Если лень читать, то вот разъяснительное видео от автора (на английском языке): https://www.youtube.com/watch?v=88GyLoZbDNw
Перед установкой я, как обычно, сначала прошерстил ansible galaxy на наличие готовых ролей, взял понравившуюся и адаптировал под себя. Результат можете найти здесь: https://github.com/kshcherban/ansible-role-wireguard.
Что там происходит под капотом?
- Устанавливается пакет wireguard на сервере.
- Там же генерируются конфиги для сервера и клиента.
- Клиентский конфиг копируется на локальный компьютер, который вызывает ansible.
Если не знаете, как использовать роли ansible, то можете почитать тут. Для установки сделайте следующее:
- Добавьте следующее в файл requirements.yml в своей директории с ansible кодом:
roles:
- name: kshcherban.ddns_cloudflare
src: https://github.com/kshcherban/ansible-role-ddns-cloudflare
- name: kshcherban.wireguard
src: https://github.com/kshcherban/ansible-role-wireguard
- Выполните команду:
ansible-galaxy role install -r requirements.yml
После того, как вы применили ansible роль wireguard, вы можете сгенерировать QR код из конфига. Конфиг можно найти в ~/wireguard-<client-name>.conf
qrencode -t ansiutf8 < ~/wireguard-<client-name>.conf
Полученный конфиг можно отсканировать в приложении на мобильном телефоне, так настройка будет мгновенной.
Вот и всё! Несколько нехитрых манипуляций и вы имеете свой быстрый VPN сервер с блокировкой рекламы на борту.