mirror of
https://github.com/StepanovPlaton/HomeServerServices.git
synced 2026-10-31 06:28:30 +04:00
Add xray
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -18,6 +18,9 @@ gitea/config/*
|
|||||||
matrix/data/*
|
matrix/data/*
|
||||||
matrix/db
|
matrix/db
|
||||||
|
|
||||||
|
xray/config/config.json
|
||||||
|
xray/config/*.tmp
|
||||||
|
|
||||||
cloud/db
|
cloud/db
|
||||||
cloud/data
|
cloud/data
|
||||||
cloud/config
|
cloud/config
|
||||||
|
|||||||
@@ -41,6 +41,8 @@
|
|||||||
- **BitTorrent клиент Transmission** с веб-интерфейсом
|
- **BitTorrent клиент Transmission** с веб-интерфейсом
|
||||||
- **SSH туннелирование через AutoSSH**
|
- **SSH туннелирование через AutoSSH**
|
||||||
- Можно пробросить порт на удалённый VPS, автоматически переподключается при потере соединения
|
- Можно пробросить порт на удалённый VPS, автоматически переподключается при потере соединения
|
||||||
|
- **VPN-сервер Xray (VLESS + Reality)** для безопасного доступа к домашней сети извне
|
||||||
|
- Трафик маскируется под обычный HTTPS, не требует отдельного домена и сертификата
|
||||||
- **Nginx reverse proxy** для маршрутизации трафика к сервисам
|
- **Nginx reverse proxy** для маршрутизации трафика к сервисам
|
||||||
- Автоматическое получение и обновление SSL сертификатов через Let's Encrypt
|
- Автоматическое получение и обновление SSL сертификатов через Let's Encrypt
|
||||||
- Автоматическое обновление DNS записей у регистратора [рег.ру](https://www.reg.ru)
|
- Автоматическое обновление DNS записей у регистратора [рег.ру](https://www.reg.ru)
|
||||||
@@ -121,3 +123,7 @@
|
|||||||
#### NextCloud
|
#### NextCloud
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
### Xray VPN
|
||||||
|
|
||||||
|
Сервис не имеет веб-интерфейса. После запуска `xray/setup.sh` выведет ссылку `vless://...` для подключения из клиента (v2rayN, NekoBox, Hiddify, sing-box и т.п.). Порт по умолчанию — `2053`.
|
||||||
|
|||||||
83
Services.md
83
Services.md
@@ -254,4 +254,85 @@ vim default.conf
|
|||||||
```bash
|
```bash
|
||||||
podman-compose -f init-compose.yml down
|
podman-compose -f init-compose.yml down
|
||||||
podman-compose up -d --build
|
podman-compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1️⃣3️⃣ Xray — VPN-доступ к домашней сети (VLESS + Reality)
|
||||||
|
|
||||||
|
> VLESS + Reality маскирует трафик под обычный HTTPS. Отдельный домен и SSL-сертификат не нужны, а порт можно пробросить снаружи. Подходит для доступа к домашней сети и как личный VPN.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd xray
|
||||||
|
cp .env.example .env && vim .env
|
||||||
|
chmod +x setup.sh
|
||||||
|
./setup.sh
|
||||||
|
podman-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
`setup.sh` автоматически:
|
||||||
|
|
||||||
|
- генерирует UUID, ключевую пару X25519 и Short ID;
|
||||||
|
- создаёт `config/config.json` из шаблона;
|
||||||
|
- проверяет конфигурацию через `xray run -test`;
|
||||||
|
- выводит готовую ссылку `vless://...` для клиента.
|
||||||
|
|
||||||
|
> ⚠️ Файлы `.env` и `config/config.json` содержат секреты и исключены из Git. Ссылка подключения тоже является секретом — не публикуйте её.
|
||||||
|
|
||||||
|
> После изменения `XRAY_PORT`, `XRAY_DEST` или `XRAY_SERVER_NAME` в `.env` запустите `./setup.sh` заново — он пересоберёт `config/config.json` и проверит его. Секреты при этом сохраняются.
|
||||||
|
|
||||||
|
### Проброс порта
|
||||||
|
|
||||||
|
В OPNsense: **Межсетевой экран > NAT > Переадресация портов**
|
||||||
|
|
||||||
|
- **Interface:** WAN
|
||||||
|
- **Protocol:** TCP
|
||||||
|
- **Destination:** WAN address
|
||||||
|
- **Destination port range:** `2053` (или ваш `XRAY_PORT`)
|
||||||
|
- **Redirect target IP:** IP вашего сервера с Podman
|
||||||
|
- **Redirect target port:** `2053` (или ваш `XRAY_PORT`)
|
||||||
|
- **Filter rule association:** Add associated filter rule
|
||||||
|
|
||||||
|
> В rootless Podman нельзя слушать порты ниже 1024, поэтому по умолчанию используется `2053`. Не занимайте `8443` — он уже используется nginx-proxy. При необходимости внешний порт можно сделать другим, но тогда клиент должен подключаться именно к внешнему порту.
|
||||||
|
|
||||||
|
> Предупреждение Xray о порте не-443 и выбранном `dest` относится к блокировкам GFW (Китай). Для домашнего сервера в России это не критично, но `dest` лучше выбирать из доступных вам крупных сайтов с TLS 1.3.
|
||||||
|
|
||||||
|
Если нужен стабильный адрес вместо IP, добавьте поддомен `vpn` в `proxy/ddns/domains.txt` и укажите в `.env`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
XRAY_PUBLIC_HOST=vpn.domain.ru
|
||||||
|
```
|
||||||
|
|
||||||
|
### Доступ к домашней сети
|
||||||
|
|
||||||
|
Сервер Xray не навязывает маршруты клиенту — маршрутизацию настраиваем в клиенте:
|
||||||
|
|
||||||
|
- **Только домашняя сеть:** оставьте интернет напрямую, а подсеть `192.168.0.0/16` (или `geoip:private`) направьте в proxy.
|
||||||
|
- **Полный туннель:** весь трафик (`0.0.0.0/0`) направьте в proxy.
|
||||||
|
|
||||||
|
Для доступа по именам добавьте локальные записи в клиент или используйте DNS домашней сети (например, AdGuard/OPNsense), направив DNS-запросы через туннель.
|
||||||
|
|
||||||
|
### Добавление устройства
|
||||||
|
|
||||||
|
Для каждого устройства лучше использовать отдельный UUID. Добавьте свой объект в `clients` внутри `config/config.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "новый-uuid",
|
||||||
|
"flow": "xtls-rprx-vision"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
После изменения перезапустите контейнер:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
podman-compose restart xray
|
||||||
|
```
|
||||||
|
|
||||||
|
Сгенерировать новый UUID можно командой:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
podman run --rm ghcr.io/xtls/xray-core:latest uuid
|
||||||
|
```
|
||||||
|
|
||||||
|
Ссылка для нового устройства строится по той же схеме, что вывел `setup.sh`: меняется только UUID в начале ссылки.
|
||||||
@@ -7,3 +7,4 @@ matrix
|
|||||||
chat
|
chat
|
||||||
todo
|
todo
|
||||||
download
|
download
|
||||||
|
vpn
|
||||||
|
|||||||
20
xray/.env.example
Normal file
20
xray/.env.example
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Порт Xray на хосте и в контейнере (для rootless Podman должен быть > 1024).
|
||||||
|
# По умолчанию 2053, потому что 443/8443 уже заняты nginx-proxy.
|
||||||
|
XRAY_PORT=2053
|
||||||
|
|
||||||
|
# Уровень логирования Xray: debug, info, warning, error
|
||||||
|
XRAY_LOG_LEVEL=warning
|
||||||
|
|
||||||
|
# Маскировочный сайт (dest) и SNI. Должны совпадать.
|
||||||
|
# Выбирайте крупный сайт с TLS 1.3, доступный с вашего сервера.
|
||||||
|
XRAY_DEST=www.cloudflare.com:443
|
||||||
|
XRAY_SERVER_NAME=www.cloudflare.com
|
||||||
|
|
||||||
|
# Внешний адрес сервера для ссылки подключения: белый IP или домен (без https:// и без порта)
|
||||||
|
XRAY_PUBLIC_HOST=vpn.example.com
|
||||||
|
|
||||||
|
# Генерируются автоматически командой ./setup.sh — не редактируйте вручную
|
||||||
|
XRAY_UUID=
|
||||||
|
XRAY_PRIVATE_KEY=
|
||||||
|
XRAY_PUBLIC_KEY=
|
||||||
|
XRAY_SHORT_ID=
|
||||||
70
xray/config/config.json.example
Normal file
70
xray/config/config.json.example
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"loglevel": "__LOG_LEVEL__",
|
||||||
|
"access": "none"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"tag": "vless-reality-in",
|
||||||
|
"listen": "0.0.0.0",
|
||||||
|
"port": __PORT__,
|
||||||
|
"protocol": "vless",
|
||||||
|
"settings": {
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": "__UUID__",
|
||||||
|
"flow": "xtls-rprx-vision"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"decryption": "none"
|
||||||
|
},
|
||||||
|
"streamSettings": {
|
||||||
|
"network": "tcp",
|
||||||
|
"security": "reality",
|
||||||
|
"realitySettings": {
|
||||||
|
"show": false,
|
||||||
|
"dest": "__DEST__",
|
||||||
|
"xver": 0,
|
||||||
|
"serverNames": [
|
||||||
|
"__SERVER_NAME__"
|
||||||
|
],
|
||||||
|
"privateKey": "__PRIVATE_KEY__",
|
||||||
|
"shortIds": [
|
||||||
|
"__SHORT_ID__"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sniffing": {
|
||||||
|
"enabled": true,
|
||||||
|
"destOverride": [
|
||||||
|
"http",
|
||||||
|
"tls",
|
||||||
|
"quic"
|
||||||
|
],
|
||||||
|
"routeOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"tag": "direct",
|
||||||
|
"protocol": "freedom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "block",
|
||||||
|
"protocol": "blackhole"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"routing": {
|
||||||
|
"domainStrategy": "AsIs",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"type": "field",
|
||||||
|
"ip": [
|
||||||
|
"geoip:private"
|
||||||
|
],
|
||||||
|
"outboundTag": "direct"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
27
xray/docker-compose.yml
Normal file
27
xray/docker-compose.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
services:
|
||||||
|
xray:
|
||||||
|
image: ghcr.io/xtls/xray-core:latest
|
||||||
|
container_name: xray
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
# Порт должен совпадать с XRAY_PORT в config/config.json (генерируется setup.sh)
|
||||||
|
- "${XRAY_PORT:?}:${XRAY_PORT:?}/tcp"
|
||||||
|
volumes:
|
||||||
|
# Монтируем каталог целиком, чтобы не использовать конфиги по умолчанию из образа
|
||||||
|
- ./config:/usr/local/etc/xray:ro,Z
|
||||||
|
environment:
|
||||||
|
- TZ=${TZ:-Europe/Samara}
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 128M
|
||||||
|
reservations:
|
||||||
|
memory: 64M
|
||||||
|
networks:
|
||||||
|
- xray_network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
xray_network:
|
||||||
|
name: xray_network
|
||||||
|
driver: bridge
|
||||||
128
xray/setup.sh
Normal file
128
xray/setup.sh
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
ENGINE="${CONTAINER_ENGINE:-podman}"
|
||||||
|
IMAGE="${XRAY_IMAGE:-ghcr.io/xtls/xray-core:latest}"
|
||||||
|
|
||||||
|
if ! command -v "$ENGINE" >/dev/null 2>&1; then
|
||||||
|
echo "Ошибка: не найден $ENGINE. Установите Podman или задайте CONTAINER_ENGINE=docker." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f .env ]; then
|
||||||
|
cp .env.example .env
|
||||||
|
echo "Создан .env из .env.example"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Убираем CRLF, если файл редактировали в Windows
|
||||||
|
sed -i 's/\r$//' .env 2>/dev/null || true
|
||||||
|
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. ./.env
|
||||||
|
|
||||||
|
: "${XRAY_PORT:?Укажите XRAY_PORT в .env}"
|
||||||
|
: "${XRAY_DEST:?Укажите XRAY_DEST в .env}"
|
||||||
|
: "${XRAY_SERVER_NAME:?Укажите XRAY_SERVER_NAME в .env}"
|
||||||
|
|
||||||
|
LOG_LEVEL="${XRAY_LOG_LEVEL:-warning}"
|
||||||
|
PUBLIC_HOST="${XRAY_PUBLIC_HOST:-YOUR_SERVER_IP}"
|
||||||
|
|
||||||
|
set_env() {
|
||||||
|
key="$1"
|
||||||
|
value="$2"
|
||||||
|
awk -v k="$key" -v v="$value" '
|
||||||
|
BEGIN { FS = "="; OFS = "=" }
|
||||||
|
$1 == k { print k, v; next }
|
||||||
|
{ print }
|
||||||
|
' .env > .env.tmp
|
||||||
|
mv .env.tmp .env
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_uuid() {
|
||||||
|
out="$("$ENGINE" run --rm "$IMAGE" uuid)" || return 1
|
||||||
|
printf '%s' "$out" | tr -d '\r\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_x25519() {
|
||||||
|
out="$("$ENGINE" run --rm "$IMAGE" x25519)" || return 1
|
||||||
|
printf '%s' "$out" | tr -d '\r'
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_short_id() {
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
openssl rand -hex 8 | tr -d '\r\n'
|
||||||
|
else
|
||||||
|
od -An -N8 -tx1 /dev/urandom | tr -d ' \n'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "${XRAY_UUID:-}" ]; then
|
||||||
|
echo "Генерация UUID..."
|
||||||
|
XRAY_UUID="$(gen_uuid)"
|
||||||
|
set_env XRAY_UUID "$XRAY_UUID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${XRAY_PRIVATE_KEY:-}" ]; then
|
||||||
|
echo "Генерация ключевой пары X25519..."
|
||||||
|
KEYS="$(gen_x25519)"
|
||||||
|
XRAY_PRIVATE_KEY="$(printf '%s\n' "$KEYS" | sed -n -E 's/^(PrivateKey|Private key):[[:space:]]*//p' | head -n 1)"
|
||||||
|
XRAY_PUBLIC_KEY="$(printf '%s\n' "$KEYS" | sed -n -E 's/^(Password \(PublicKey\)|PublicKey|Public key):[[:space:]]*//p' | head -n 1)"
|
||||||
|
if [ -z "$XRAY_PRIVATE_KEY" ] || [ -z "$XRAY_PUBLIC_KEY" ]; then
|
||||||
|
echo "Не удалось разобрать вывод xray x25519:" >&2
|
||||||
|
printf '%s\n' "$KEYS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
set_env XRAY_PRIVATE_KEY "$XRAY_PRIVATE_KEY"
|
||||||
|
set_env XRAY_PUBLIC_KEY "$XRAY_PUBLIC_KEY"
|
||||||
|
elif [ -z "${XRAY_PUBLIC_KEY:-}" ]; then
|
||||||
|
echo "Вычисление публичного ключа..."
|
||||||
|
KEYS="$("$ENGINE" run --rm "$IMAGE" x25519 -i "$XRAY_PRIVATE_KEY")" || {
|
||||||
|
echo "Не удалось вычислить публичный ключ из XRAY_PRIVATE_KEY." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
KEYS="$(printf '%s' "$KEYS" | tr -d '\r')"
|
||||||
|
XRAY_PUBLIC_KEY="$(printf '%s\n' "$KEYS" | sed -n -E 's/^(Password \(PublicKey\)|PublicKey|Public key):[[:space:]]*//p' | head -n 1)"
|
||||||
|
if [ -z "$XRAY_PUBLIC_KEY" ]; then
|
||||||
|
echo "Не удалось вычислить публичный ключ из XRAY_PRIVATE_KEY." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
set_env XRAY_PUBLIC_KEY "$XRAY_PUBLIC_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${XRAY_SHORT_ID:-}" ]; then
|
||||||
|
echo "Генерация Short ID..."
|
||||||
|
XRAY_SHORT_ID="$(gen_short_id)"
|
||||||
|
set_env XRAY_SHORT_ID "$XRAY_SHORT_ID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p config
|
||||||
|
sed \
|
||||||
|
-e "s|__LOG_LEVEL__|$LOG_LEVEL|g" \
|
||||||
|
-e "s|__PORT__|$XRAY_PORT|g" \
|
||||||
|
-e "s|__UUID__|$XRAY_UUID|g" \
|
||||||
|
-e "s|__DEST__|$XRAY_DEST|g" \
|
||||||
|
-e "s|__SERVER_NAME__|$XRAY_SERVER_NAME|g" \
|
||||||
|
-e "s|__PRIVATE_KEY__|$XRAY_PRIVATE_KEY|g" \
|
||||||
|
-e "s|__SHORT_ID__|$XRAY_SHORT_ID|g" \
|
||||||
|
config/config.json.example > config/config.json.tmp
|
||||||
|
mv config/config.json.tmp config/config.json
|
||||||
|
|
||||||
|
echo "Проверка конфигурации..."
|
||||||
|
"$ENGINE" run --rm -v "$(pwd)/config:/usr/local/etc/xray:ro,Z" "$IMAGE" run -test -confdir /usr/local/etc/xray
|
||||||
|
|
||||||
|
LINK="vless://${XRAY_UUID}@${PUBLIC_HOST}:${XRAY_PORT}?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${XRAY_SERVER_NAME}&fp=chrome&pbk=${XRAY_PUBLIC_KEY}&sid=${XRAY_SHORT_ID}&type=tcp&headerType=none&spx=%2F#Xray-Home"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Готово.
|
||||||
|
Конфиг: config/config.json
|
||||||
|
Публичный ключ: $XRAY_PUBLIC_KEY
|
||||||
|
Short ID: $XRAY_SHORT_ID
|
||||||
|
|
||||||
|
Ссылка для клиента (замените $PUBLIC_HOST на реальный адрес, если нужно):
|
||||||
|
$LINK
|
||||||
|
|
||||||
|
Не публикуйте эту ссылку: она даёт доступ к вашему серверу.
|
||||||
|
EOF
|
||||||
Reference in New Issue
Block a user