Задать вопрос
@Sandr0oo

DOCKER + VLESS + NGINX. Как настроить сайт и VLESS на одном порту?

Я пытаюсь настроить nginx так, чтобы по одному порту был доступен VLESS И тестовый сайт. Запускаю я всё в docker compose:
services:
  helloworld:
    container_name: helloworld-2
    image: crccheck/hello-world
    expose:
      - 8000
  nginx:
    image: nginx-stream
    container_name: nginx-stream
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./http.conf.d:/opt/nginx/http.conf.d
      - ./stream.conf.d:/opt/nginx/stream.conf.d
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    restart: unless-stopped
  cerbot: 
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    command: certonly --webroot -w /var/www/certbot --keep-until-expiring --email test@test.ru --domain exemple.com --agree-tos
  x-ray:
    image: teddysun/xray  
    container_name: x-ray-nginx
    volumes:
      - /etc/xray2:/etc/xray
      - ./certbot/conf:/etc/letsencrypt
    expose:
      - 8443
    restart: always

Еще для этого я пересобрал контейнер nginx, чтобы подключить stream:
FROM debian:bookworm

RUN apt-get update && apt-get -y upgrade && \
    apt-get install -y wget libpcre3-dev build-essential libssl-dev zlib1g-dev && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /opt

RUN wget http://nginx.org/download/nginx-1.27.3.tar.gz && \
    tar -zxvf nginx-1.*.tar.gz && \
    cd nginx-1.* && \
    ./configure --prefix=/opt/nginx --user=nginx --group=nginx --with-http_ssl_module --with-ipv6 --with-threads --with-stream --with-stream_ssl_module --with-http_v2_module --with-stream_ssl_preread_module --with-http_realip_module && \
    make && make install && \
    cd .. && rm -rf nginx-1.*

# nginx user
RUN adduser --system --no-create-home --disabled-login --disabled-password --group nginx

# config dirs
RUN mkdir /opt/nginx/http.conf.d && mkdir /opt/nginx/stream.conf.d

ADD nginx.conf /opt/nginx/conf/nginx.conf
ADD zero_downtime_reload.sh /opt/nginx/sbin/zero_downtime_reload.sh

WORKDIR /

EXPOSE 80 443

CMD ["/opt/nginx/sbin/nginx", "-g", "daemon off;"]

Вот так выглядит мой /opt/nginx/stream.conf.d/*.conf:
log_format stream_access '$remote_addr - [$time_local] "$ssl_preread_server_name" $status $bytes_sent';

access_log /opt/nginx/logs/stream_access.log stream_access;

map $ssl_preread_server_name $sni_name {
    hostnames;
    www.google.com      xray;
    exemple.com           www;
    *.exemple.com         www;
    default              xray;
}

upstream xray {
    server x-ray:8443;
}

upstream www {
    server 127.0.0.1:7443;
}

server {
    listen            443;
    proxy_pass        $sni_name;
    ssl_preread       on;
    proxy_protocol    on;
}

А вот мой /opt/nginx/http.conf.d/*.conf:
server_tokens off;
charset utf-8;
server {
    listen 80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}
server {
    listen 7443 ssl proxy_protocol;
    set_real_ip_from 127.0.0.1;
    real_ip_header proxy_protocol;
    http2 on;
    ssl_certificate     /etc/letsencrypt/live/exemple.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exemple.com/privkey.pem;
    server_name exemple.com;
    root /var/www/html;
    index index.php index.html index.htm;
    location ~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    location /test {
        proxy_pass http://helloworld:8000/;
    }
}


x-ray config:
{
  "log": {
    "loglevel": "warning"
  },
  "routing": {
    "rules": [],
    "domainStrategy": "AsIs"
  },
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "port": 8443,
      "protocol": "vless",
      "tag": "vless_tls",
      "settings": {
        "clients": [
          {
            "id": "zzz",
            "email": "test@test.ru",
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "show": false,
          "dest": "www.google.com:443",
          "xver": 0,
          "serverNames": ["www.google.com"],
          "privateKey": "xxx",
          "minClientVer": "",
          "maxClientVer": "",
          "maxTimeDiff": 0,
          "shortIds": ["yyy"]
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls", "quic"]
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "tag": "direct"
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ]
}

Подскажите, пожалуйста, что здесь не так? Что нужно исправить. Ни тестовый сайт, ни VLESS не работают.

UPD:
Обновил код в во вопросе. Теперь тестовый сервис helloworld открывается в браузере.

UPD2:
В docker compose в контейнере x-ray в volumes была ошибка, заменил `/etc/xray2:/etc/xray2` на `/etc/xray2:/etc/xray`. Но по прежнему не работает. В логе stream во такое:
93.x.x.x (мой ip) - [23/Jan/2025:14:11:22 +0000] "exemple.com" 200 3856
93.x.x.x (мой ip) - [23/Jan/2025:14:11:55 +0000] "www.google.com" 200 7
93.x.x.x (мой ip) - [23/Jan/2025:14:11:55 +0000] "www.google.com" 200 7
93.x.x.x (мой ip) - [23/Jan/2025:14:11:55 +0000] "www.google.com" 200 7
93.x.x.x (мой ip) - [23/Jan/2025:14:11:55 +0000] "www.google.com" 200 7

Первая строчка это запрос моего тестового сайта и он открывается. Дальше это запросы к xray и насколько я понимаю он отвечает с кодом 200 (ОК).
В логах xray ошибок нет, но сыпет вот такое информационное сообщение:
67928889b13a5420987718.jpeg
Единственное место где хоть где-то пишет ошибку - это клиент, но непонятно что с этим делать.
679288ffb6af0171315854.png
  • Вопрос задан
  • 571 просмотр
Подписаться 1 Средний 6 комментариев
Решения вопроса 1
@Sandr0oo Автор вопроса
В итоге нашел в чем была проблема - proxy_protocol.
Чтобы заработало нужно из /opt/nginx/stream.conf.d/*.conf удалить строчку:
proxy_protocol on;
А из /opt/nginx/http.conf.d/*.conf удалить всё что связано с proxy_protocol (для наглядности закомментировал ненужное):
server_tokens off;
charset utf-8;
server {
    listen 80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}
server {
    listen 7443 ssl;
    # listen 7443 ssl proxy_protocol;
    # set_real_ip_from 127.0.0.1;
    # real_ip_header proxy_protocol;
    http2 on;
    ssl_certificate     /etc/letsencrypt/live/exemple.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exemple.com/privkey.pem;
    server_name sandro.run;
    root /var/www/html;
    index index.php index.html index.htm;
    location ~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    location /test {
        proxy_pass http://helloworld:8000/;
    }
}

После этого заработал, но есть и проблема. Из-за отключения proxy_protocol в логах обращений к сайту IP посетителей пишутся как 127.0.0.1. Пример решения этой проблемы, вроде, есть, но буду заниматься этим чуть позже и если решу проблему, то дополню ответ.

P.S.
Спасибо автору статьи https://coyotle.ru/posts/xray-and-nginx/ из которой были взяты конфиги nginx, xray.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@bekoev
Привет, спасибо за материал!

Еще для этого я пересобрал контейнер nginx, чтобы подключить stream

docker-образы nginx включают stream (https://github.com/nginxinc/docker-nginx/issues/83...)
Я настроил описанный Вами конфиг на основе официального образа nginx. Ещё раз спасибо.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы