- Вопрос или проблема
- Архитектура
- Проблема
- Конфигурация
- Wireguard
- Caddy
- Sysctl
- Устранение неисправностей
- Соединение Wireguard
- IP Tables
- Ping
- Curl
- Ответ или решение
- Решение проблемы доступа к локальным сервисам через Wireguard с использованием Caddy и Docker
- Введение
- Архитектура
- Анализ конфигурации
- Подключение Wireguard
- Настройки Caddy
- Тестирование
- Заключение
Вопрос или проблема
Архитектура
Проблема
Я хочу получить доступ к своим сервисам, размещенным в моей локальной сети (192.168.1.0/24), через мой домен (example.com). В данный момент я могу получить доступ к сервису Wireguard UI, размещенному на VPS (wgui.example.com), но не могу получить доступ к ни одному из моих сервисов, находящихся в локальной сети.
Если это не обязательно, например, для Vaultwarden, я бы хотел завершить TLS на VPS и общаться по HTTP через туннель Wireguard до шлюзевой машины.
Конфигурация
Wireguard
# VPS Wireguard Server wg0.conf
[Interface]
Address = 10.1.10.1/24
ListenPort = 51820
PrivateKey = (Приватный ключ сервера)
MTU = 1450
PostUp = /opt/wireguard-ui/postup.sh
PreDown =
PostDown = /opt/wireguard-ui/postdown.sh
Table = auto
[Peer]
PublicKey = (Публичный ключ клиента)
PresharedKey = (Клиентский PSK)
AllowedIPs = 10.1.10.3/32
PersistentKeepalive = 15
# Wireguard UI postup.sh
!/usr/bin/bash
# /opt/wireguard-ui/postup.sh
sysctl -w net.ipv4.ip_forward=1
ufw route allow in on wg0 out on enp1s0
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
iptables -t nat -I POSTROUTING -o enp1s0 -j MASQUERADE
# Wireguard UI postdown.sh
#!/usr/bin/bash
# /opt/wireguard-ui/postdown.sh
sysctl -w net.ipv4.ip_forward=0
ufw route delete allow in on wg0 out on enp1s0
iptables -D FORWARD -i wg0 -j ACCEPT
iptables -D FORWARD -o wg0 -j ACCEPT
iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE
# Gateway Wireguard Client wg0.conf
[Interface]
Address = 10.1.10.3/24
PrivateKey = (Приватный ключ клиента)
MTU = 1450
[Peer]
PublicKey = (Публичный ключ сервера)
PresharedKey = (Клиентский PSK)
AllowedIPs = 0.0.0.0/0
Endpoint = 123.456.7.890:51820
PersistentKeepalive = 15
Caddy
# VPS Caddyfile
example.com {
root * /usr/share/caddy
}
import sites-enabled/*
# VPS Caddy wgui config
wgui.example.com {
reverse_proxy :5000
handle_errors {
respond "{err.status_code} {err.status_text}"
}
}
www.wgui.example.com {
redir https://wgui.example.com{uri}
}
# VPS Caddy pihole config
pihole.example.com {
reverse_proxy 10.1.10.3
}
www.pihole.example.com {
redir https://pihole.example.com{uri}
}
# Gateway Caddy pihole config
pihole.example.com {
reverse_proxy 192.168.1.20:1010
}
Sysctl
# Gateway sysctl.conf
# Раскомментируйте следующую строку, чтобы включить пересылку пакетов для IPv4
net.ipv4.ip_forward=1
Устранение неисправностей
Когда я пытаюсь получить доступ к pihole.example.com, я получаю ошибку 403 Forbidden
.
Соединение Wireguard
# VPS wg show
interface: wg0
public key: (Публичный ключ сервера)
private key: (скрыто)
listening port: 51820
peer: 59mOhf8SBmD3tZFDUescxXRu219NP2kkpBY92Bk/XHo=
preshared key: (скрыто)
endpoint: (Публичный IP клиента):7615
allowed ips: 10.1.10.3/32
latest handshake: 1 minute, 38 seconds ago
transfer: 2.33 MiB received, 7.20 MiB sent
persistent keepalive: every 15 seconds
IP Tables
# VPS iptables -L -n
цепочка INPUT (policy DROP)
target prot opt source destination
ufw-before-logging-input all -- 0.0.0.0/0 0.0.0.0/0
ufw-before-input all -- 0.0.0.0/0 0.0.0.0/0
ufw-after-input all -- 0.0.0.0/0 0.0.0.0/0
ufw-after-logging-input all -- 0.0.0.0/0 0.0.0.0/0
ufw-reject-input all -- 0.0.0.0/0 0.0.0.0/0
ufw-track-input all -- 0.0.0.0/0 0.0.0.0/0
Цепочка FORWARD (policy DROP)
target prot opt source destination
ufw-before-logging-forward all -- 0.0.0.0/0 0.0.0.0/0
ufw-before-forward all -- 0.0.0.0/0 0.0.0.0/0
ufw-after-forward all -- 0.0.0.0/0 0.0.0.0/0
ufw-after-logging-forward all -- 0.0.0.0/0 0.0.0.0/0
ufw-reject-forward all -- 0.0.0.0/0 0.0.0.0/0
ufw-track-forward all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Цепочка OUTPUT (policy ACCEPT)
target prot opt source destination
ufw-before-logging-output all -- 0.0.0.0/0 0.0.0.0/0
ufw-before-output all -- 0.0.0.0/0 0.0.0.0/0
ufw-after-output all -- 0.0.0.0/0 0.0.0.0/0
ufw-after-logging-output all -- 0.0.0.0/0 0.0.0.0/0
ufw-reject-output all -- 0.0.0.0/0 0.0.0.0/0
ufw-track-output all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-after-forward (1 ссылка)
target prot opt source destination
Цепочка ufw-after-input (1 ссылка)
target prot opt source destination
ufw-skip-to-policy-input udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:137
ufw-skip-to-policy-input udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:138
ufw-skip-to-policy-input tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:139
ufw-skip-to-policy-input tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:445
ufw-skip-to-policy-input udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:67
ufw-skip-to-policy-input udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:68
ufw-skip-to-policy-input all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type BROADCAST
Цепочка ufw-after-logging-forward (1 ссылка)
target prot opt source destination
LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 3/min burst 10 LOG flags 0 level 4 prefix "[UFW BLOCK] "
Цепочка ufw-after-logging-input (1 ссылка)
target prot opt source destination
LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 3/min burst 10 LOG flags 0 level 4 prefix "[UFW BLOCK] "
Цепочка ufw-after-logging-output (1 ссылка)
target prot opt source destination
Цепочка ufw-after-output (1 ссылка)
target prot opt source destination
Цепочка ufw-before-forward (1 ссылка)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 3
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 11
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 12
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
ufw-user-forward all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-before-input (1 ссылка)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ufw-logging-deny all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
DROP all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 3
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 11
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 12
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp spt:67 dpt:68
ufw-not-local all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT udp -- 0.0.0.0/0 224.0.0.251 udp dpt:5353
ACCEPT udp -- 0.0.0.0/0 239.255.255.250 udp dpt:1900
ufw-user-input all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-before-logging-forward (1 ссылка)
target prot opt source destination
Цепочка ufw-before-logging-input (1 ссылка)
target prot opt source destination
Цепочка ufw-before-logging-output (1 ссылка)
target prot opt source destination
Цепочка ufw-before-output (1 ссылка)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ufw-user-output all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-logging-allow (0 ссылок)
target prot opt source destination
LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 3/min burst 10 LOG flags 0 level 4 prefix "[UFW ALLOW] "
Цепочка ufw-logging-deny (2 ссылки)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID limit: avg 3/min burst 10
LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 3/min burst 10 LOG flags 0 level 4 prefix "[UFW BLOCK] "
Цепочка ufw-not-local (1 ссылка)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
RETURN all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type MULTICAST
RETURN all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type BROADCAST
ufw-logging-deny all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 3/min burst 10
DROP all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-reject-forward (1 ссылка)
target prot opt source destination
Цепочка ufw-reject-input (1 ссылка)
target prot opt source destination
Цепочка ufw-reject-output (1 ссылка)
target prot opt source destination
Цепочка ufw-skip-to-policy-forward (0 ссылок)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-skip-to-policy-input (7 ссылок)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-skip-to-policy-output (0 ссылок)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-track-forward (1 ссылка)
target prot opt source destination
Цепочка ufw-track-input (1 ссылка)
target prot opt source destination
Цепочка ufw-track-output (1 ссылка)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 ctstate NEW
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 ctstate NEW
Цепочка ufw-user-forward (1 ссылка)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-user-input (1 ссылка)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:51820
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 /* 'dapp_OpenSSH' */
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:80
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:443
Цепочка ufw-user-limit (0 ссылок)
target prot opt source destination
LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 3/min burst 5 LOG flags 0 level 4 prefix "[UFW LIMIT BLOCK] "
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Цепочка ufw-user-limit-accept (0 ссылок)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Цепочка ufw-user-logging-forward (0 ссылок)
target prot opt source destination
Цепочка ufw-user-logging-input (0 ссылок)
target prot opt source destination
Цепочка ufw-user-logging-output (0 ссылок)
target prot opt source destination
Цепочка ufw-user-output (1 ссылка)
target prot opt source destination
# Gateway iptables -L -n
цепочка INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
ACCEPT 1 -- 0.0.0.0/0 0.0.0.0/0
Цепочка FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0
ACCEPT 0 -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
ACCEPT 1 -- 0.0.0.0/0 0.0.0.0/0
Цепочка OUTPUT (policy ACCEPT)
target prot opt source destination
Ping
- Я могу
ping 10.1.10.3
с машины VPS. - Я могу
ping 192.168.20
на шлюзевой машине, но не с машины VPS.
Curl
Если я запускаю curl -I http://192.168.1.20/admin
на шлюзевой машине, я получаю:
HTTP/1.1 308 Permanent Redirect
Connection: close
Location: https://192.168.1.20/admin
Server: Caddy
Date: Mon, 25 Nov 2024 05:55:33 GMT
Не могли бы вы помочь мне понять, где я ошибаюсь?
Во-первых, в конфигурации вашего сервера вам необходимо включить 192.168.1.0/24
дополнительно в AllowedIPs=
в секции [Peer]
для Pi.
Кроме того, на вашем Pi также должно быть включено перенаправление IP (sysctl) и разрешено (файрвол) соответственно.
И последнее, но не менее важное, ваши устройства в локальной сети должны иметь маршрут, который использует Pi в качестве шлюза для вашей подсети VPN (например, 10.1.10.0/24 via 192.168.1.10
). В противном случае, Pi придется делать маскарад / исходный NAT для подсети VPN (так чтобы трафик оттуда выглядел так, будто он исходит от Pi к устройствам в локальной сети).
Ответ или решение
Решение проблемы доступа к локальным сервисам через Wireguard с использованием Caddy и Docker
Введение
Ваша конфигурация сети включает в себя использование Wireguard для создания защищенного VPN-туннеля между вашим VPS и локальной сетью. Ваша основная проблема заключается в невозможности доступа к локальным сервисам (192.168.1.0/24) через домен, что приводит к ошибкам, таким как 403 Forbidden. Давайте подробно рассмотрим архитектуру системы и выявим возможные недостатки в конфигурации.
Архитектура
Ваше решение состоит из следующих компонентов:
- VPS с Wireguard и Caddy – обеспечивает проксирование запросов к локальным сервисам.
- Локальная сеть – включает в себя различные сервисы, такие как Pi-hole и другие, и настроена на работу по адресу 192.168.1.0/24.
- Клиент Wireguard на шлюзе – используется для подключения к Wireguard-серверу.
Анализ конфигурации
Подключение Wireguard
Ваши конфигурации Wireguard на VPS и локальном шлюзе могут не обеспечивать необходимую маршрутизацию:
-
AllowedIPs в конфигурации VPS:
- В секции
[Peer]
, где указаны допустимые IP-адреса для клиента, вам нужно добавить диапазон192.168.1.0/24
. Это позволит маршрутизировать трафик из вашей локальной сети через VPN:AllowedIPs = 10.1.10.3/32, 192.168.1.0/24
- В секции
-
Включение перенаправления IP:
- Убедитесь, что в ваших системных настройках (sysctl) на шлюзе разрешено перенаправление IP:
net.ipv4.ip_forward=1
- На VPS это уже настроено в скрипте
postup.sh
.
- Убедитесь, что в ваших системных настройках (sysctl) на шлюзе разрешено перенаправление IP:
-
Фильтрация и маскарад:
- Убедитесь, что маскарад (source NAT) настроен правильно. Это позволит трафику из вашего VPN выглядеть так, как будто он идет с IP-адреса вашего шлюза. В вашем
iptables
правилах на VPS вы уже добавили маскарад, но следует проверить, правильно ли он подходит для ожидаемого трафика.
- Убедитесь, что маскарад (source NAT) настроен правильно. Это позволит трафику из вашего VPN выглядеть так, как будто он идет с IP-адреса вашего шлюза. В вашем
Настройки Caddy
Правила для Caddy на VPS и шлюзе имеют значение:
-
Конфигурация Caddy на VPS:
- Проверьте, что ваши блоки конфигурации содержат правильные целевые URL-адреса. Убедитесь, что адреса, на которые вы ссылаетесь, соответствуют IP-адресам, предоставляемым вашим шлюзом.
- В секции для Pi-hole попробуйте изменить
reverse_proxy 10.1.10.3
наreverse_proxy 192.168.1.20:1010
, если Pi-hole развернут на этом IP-адресе.
-
Гateway Caddy:
- Убедитесь, что Caddy на шлюзе правильно проксирует запросы на IP адреса ваших сервисов. Например, проверьте, что прокси блок для Pi-hole правильно обрабатывает переходы на
192.168.1.20:1010
.
- Убедитесь, что Caddy на шлюзе правильно проксирует запросы на IP адреса ваших сервисов. Например, проверьте, что прокси блок для Pi-hole правильно обрабатывает переходы на
Тестирование
-
Проверка соединений:
- Ваши тесты с
ping
иcurl
показывают, что соединение между VPS и шлюзом работает, но трафик между VPS и локальными сервисами не проходит. Проверьте, что локальные сервисы действительно доступны по указанным IP. - Выполните
curl -I http://192.168.1.20/admin
на шлюзе, как вы уже делали. Получение ответа 308 говорит о том, что запрос редиректится на HTTPS. Если ваше окружение не поддерживает HTTPS на этом сервисе, временно отключите его для диагностики.
- Ваши тесты с
-
Маршрутизирование локальных адресов:
- Проверьте маршруты маршрутизаторов вашей локальной сети. Если хосты в локальной сети не знают, как добраться до вашей VPN-сети, вам понадобится настроить маршрут на каждом из них, чтобы они «знали», что трафик к 10.1.10.0/24 должен проходить через адрес 192.168.1.10 (адрес шлюза).
Заключение
После внесения описанных изменений вы должны добиться улучшения доступа к услугам на локальной сети через ваш VPS. Следите за маршрутами и правилами брандмауэра, проверяйте протоколы IP и убедитесь, что ваши локальные сервисы настроены для обработки HTTPS и HTTP звонков корректно. Помните, успешная настройка требует тестирования, поэтому не стесняйтесь пробовать различные конфигурации до достижения результатов.