Понадобилось вот разместить сайт и Xray. На одном хостинге. На одном порту. И чтобы ещё SSL работал.
Итак, мы имеем:
Данная проблема зачастую решается модулем stream для nginx примерно так:
stream {
map $ssl_preread_server_name $sni_name {
google.com xray;
myblog12345.ru www;
default xray;
}
upstream xray {
server 127.0.0.1:8443; # слушает xray
}
upstream www {
server 127.0.0.1:7443; # слушает nginx
}
server {
listen 443; # отдаём наружу
proxy_pass $sni_name;
ssl_preread on;
}
}
server {
listen 80;
server_name myblog12345.ru;
return 301 https://$host$request_uri;
}
server {
listen 7443 ssl;
server_name myblog12345.ru;
# ... настройки SSL
root /var/www/myblog12345.ru;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}Я тоже настроил всё таким способом, но радовался недолго - в access log nginx попадают не реальные IP пользователей, а 127.0.0.1. Соответственно, какие-либо правила фильтрации/безопасности не настроить.
Проблема передачи адреса обычно решается директивой proxy_protocol в блоке stream.server. Только вот есть нюанс - эта директива не поддерживает динамическое переключение. То есть, мы или весь трафик оборачиваем в прокси, или отключаем это. Для Xray такое не прокатит.
Проблему я решил отказом от nginx stream в пользу haproxy.
Итак, меньше слов - больше дела.
"listen": "0.0.0.0",
"port": 8443,global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
mode tcp
timeout connect 5s
timeout client 60s
timeout server 60s
log global
option tcplog
frontend tls_frontend
bind *:443
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content capture req.ssl_sni len 50
use_backend xray_backend if { req.ssl_sni -i -m end google.com }
use_backend www_backend if { req.ssl_sni -i -m end myblog12345.ru }
default_backend xray_backend
backend xray_backend
mode tcp
server xray_server 127.0.0.1:8443
backend www_backend
mode tcp
server www_server 127.0.0.1:7443 send-proxyserver {
listen 80;
server_name myblog12345.ru;
return 301 https://$host$request_uri;
}
server {
listen 7443 ssl proxy_protocol; # <- Важно добавить proxy_protocol, иначе получим ошибку SSL
server_name myblog12345.ru;
# ловим IP пользователя от haproxy
real_ip_header proxy_protocol;
set_real_ip_from 127.0.0.1;
# ... настройки SSL
root /var/www/myblog12345.ru;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}Теперь такая связка позволяет работать с реальным IP пользователя.