diff --git a/article/article_draft.txt b/article/article_draft.txt index 6dbad81..1aa972a 100644 --- a/article/article_draft.txt +++ b/article/article_draft.txt @@ -36,6 +36,8 @@ IMG_1589.PNG Особенно для одинокого пользователя-хакера приятна работа с шифрованием: нет ни необходимости в сертификатах и удостоверяющих центрах, ни в логинах-паролях, все, что нужно — это с тем пиром, с которым хотите установить соедиение, передать друг другу публичные ключи вашего интерфейса WG. Для больших компаний, это, конечно, будет скорее минусом, как и то, что WG — это только базовая часть полноценной большой инфраструктуры VPN. Но, например, именно WireGuard использовали в Cloudflare для своего WARP (https://blog.cloudflare.com/announcing-warp-plus/, https://blog.cloudflare.com/warp-technical-challenges/), правда, написав его собственную реализацию — boringtun. +Еще одним минусом WG является то, что трафик не обфусцирован — DPI может обнаружить трафик WireGuard, так что его можно довольно легко заблокировать (не говоря уж о блокировке UDP совсем, что почти не мешает вебу, но гарантированно ломает работу WireGuard). Для скрытия трафика рекомендуется использовать специализированное ПО — Cloak, Obfsproxy, Shadowsocks, Stunnel, SoftEther, SSTP, в конце-концов, SSH. + Если очень упрощать, ключи работают следующим образом: у нас есть закрытый (приватный) ключ, из которого можно сгенерировать открытый, или публичный. Наоборот — нельзя, из открытого ключа мы получить закрытый никак не можем. После чего, мы можем зашифровать с помощью закрытого ключая какую-то строку, а при помощи открытого — расшифровать ее и тем самым убедиться, что у собеседника точно есть закрытый ключ, а значит, он тот, за кого себя выдает. Таким образом, мы можем без проблем публиковать открытый ключ — он всего лишь позволяет проверить подлинность автора, но не притвориться им. Это как в SSH — публичный ключ лежит на сервере, где его потеря небольшая беда: все что сможет сделать с ним злоумышленник это положить его на свой сервер, чтобы вы к нему могли подключиться с помощью закрытого ключа. Так вот, в WG первый этап подключения заключается в том, что каждая сторона с помощью зашифрованного приватным ключом сообщения доказывает собеседнику, что она именно она: это проверяется публичным ключом. @@ -56,8 +58,8 @@ echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf echo "net.ipv4.conf.all.forwarding=1" >> /etc/sysctl.conf sysctl -p /etc/sysctl.conf Опционально (но очень удобно) сразу поменять hostname обоих серверов, чтобы не запутаться, где какая консоль: -hostnamectl set-hostname internal.trickster -hostnamectl set-hostname external.trickster +hostnamectl set-hostname trickster-internal +hostnamectl set-hostname trickster-external #Шаг второй: настраиваем WireGuard для связи двух серверов: Для начала генерируем ключи. Запускаем два раза wg genkey и получаем два приватных ключа: @@ -66,7 +68,7 @@ kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8= root@trikster-internal:~# wg genkey 6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28= -Утилита wg genkey не делает никакой магии, это просто аналог чего-то типа "echo $RANDOM | md5sum | head -c 32 | base64", только наверняка более криптостойкое. +Утилита wg genkey не делает никакой магии, это просто аналог чего-то типа "echo $RANDOM | md5sum | head -c 32 | base64", только наверняка более криптостойкое: мы просто генерируем 32 байта случайных значений и представляем их в виде base64. Создаем два конфига: На internal: /etc/wireguard/wg-internal.conf @@ -97,7 +99,7 @@ Interface-Address — это IP текущего пира. Вся адерсац ListenPort — это UDP-порт для подключения извне. Если не указать, будет прослушивать 51820. Если этот пир будет только подключаться к другим клиентам, можно и не использовать. Interface-PostUp и PostDown — это скрипты, выполняющиеся после поднятия и после остановки интерфейса. Есть еще PreUP и PreDown. -Кроме публичных и приватных ключей есть еще опция PresharedKey, которая обеспечивает дополнительное шифрование симметричным ключом. Ключ генерируется командой wg genpsk и кладется в PresharedKey в секциях Peer на обоих пирах. Неиспользование этой опции не снижает нагрузку по шифровке-расшифровке: если ключ не указан, используется нулевое значение ключа. +Кроме публичных и приватных ключей есть еще опция PresharedKey, которая обеспечивает дополнительное шифрование симметричным шифром. Ключ генерируется командой wg genpsk и кладется в PresharedKey в секциях Peer на обоих пирах. Неиспользование этой опции не снижает нагрузку по шифровке-расшифровке: если ключ не указан, используется нулевое значение ключа. Для действительного обеспечения пост-квантовой безопасности (невозможности расшифровки данных квантовыми компьютерами) разработчики рекомендуют дополнительный внешний квантово-устойчивый механизм хендшека (например, Microsoft SIDH, который они пиарят именно в таком контексте), чей найденный общий ключ можно использовать в качестве PresharedKey. Заклинания в PostUp достаточно просты. `ip route | awk '/default/ {print $5; exit}'` — это команда для подстановки имени сетевого интерфейса, куда по-умолчанию выполняется маршрутизация: как правило, это тот интерфейс, в который воткнут провайдер или роутер. `ip route | awk '/default/ {print $3; exit}'` — тоже самое, но подставляет IP-адрес дефолтного маршрута. Таким образом, первая страшная команда упрощается и превращается в "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE", которая представляет собой вклчение NAT в режиме маскарада: сервер будет отправлять пришедшие ему пакеты пакеты во внешнюю сеть, подменяя в них адрес отправителя на свой, чтобы ответы на эти пакеты тоже приходили ему, а не исходному отправителю. Вторая страшная команда превращается в "ip rule add from 95.93.219.123 table main" — это необходимо для сервера internal, потому что иначе при активации маршрута 0.0.0.0/0 он начинает пересылать ответы на пакеты, приходящие ему на внешние адреса через туннель WG. Сервер на том конце, конечно, пересылает их по назначению, но тут уже не готов отправитель пакета: он присылает что-то на внешний адрес сервера internal, а ответ ему приходит с external. Естественно, при включенном rp_filter пакет отбрасывается. В этом случае сервер перестает быть доступен, например, по SSH снаружи, к нему надо коннектиться только по внутреннему IP wireguard-а. Отключать rp_filter у сервера это из пушки по воробьям, а вот дополнительное правило исправляет ситуацию. @@ -385,8 +387,20 @@ echo "Routes in routing table: $routes_count" Если вам принудительно надо маршрутизовать какую-то сеть через internal, то можно рядом со скриптом создать файлик subnets_user_list.txt в который поместить список подсетей, тогда они каждый раз будут добавляться к общему списку при обновлении, в bash-скрипте это есть. +# Шаг пятный: настраиваем фаервол -# Шаг пятый, бонусный и необязательный: кеширующий защищенный DNS over HTTPS + + + +PostUp = ufw route allow in on wg0 out on eth0 +PreDown = ufw route delete allow in on wg0 out on eth0 + +ufw allow 17968/udp +ufw allow OpenSSH +ufw disable +ufw enable + +# Шаг шестой, бонусный и необязательный: кеширующий защищенный DNS over HTTPS Теперь нам нужен еще один шаг: DNS. Можно, конечно, жить с DNS 1.1.1.1, но надо учитывать две вещи: Трафик на него пойдет через external, что автоматически означает задержку порядка 100мс при каждом запросе. Можно его добавить в subnets_user_list.txt, и тогда трафик пойдет через локальную ноду и локальный сервер 1.1.1.1, что уменьшит задержку до 10-20мс, но ваши DNS-запросы будет доступны вашему провайдеру, что в случае локальной ноды может быть для кого-то неприемлимо. Несколькими командами можно легко сделать кеширующий DNS, который еще и будет работать с DNS over HTTPS, а значит, провайдеру будет доступен только сам факт использовани DoH, но не сами запросы. Но это, конечно, не обязательно: у меня internal находится в домашней сети, и я просто использую DNS микротика, который находится в той же сети. Но если у вас internal сервер это VPS, то можно сделать там и DNS сервер. Использовать будем cloudflared. @@ -463,7 +477,6 @@ DNS = 10.20.30.1, 1.1.1.1 P.S. особые параноики могут запустить cloudflared на external, и скрыть от локального провайдера даже сам факт использования DoH. Для этого в proxy-dns-address в конфиге cloudflared и в dnsmasq.conf надо указать 10.20.30.2. - Пары ключей в статье — действующие, так что вы можете, ничего не исправляя в конфигах (только IP и имена адаптеров), залить их на два своих сервера и клиент и поиграться. Но для боевого применения ключи надо перегенерить, конечно. Так же, чтобы не усложнять статью, я не касался настройки файервола на серверах — если они торчат голой задницей в интернет, то это стоит сделать. О необходимости отключать авторизацию в ssh по паролю думаю, напоминать и так не надо. Если кто-то захочет это все красиво обернуть в два докера и прикрутить к этому веб-интерфейс (потому что конфиги клиентов все же удобнее создавать в нем) — добро пожаловать в issues на гитхабе.