Просто в секцию стрима не прописать, что-то хочет от меня:
nginx: [emerg] duplicate listen options for 0.0.0.0:443 in /etc/nginx/nginx.conf:57
nginx: configuration file /etc/nginx/nginx.conf test failed
Наверное мне стоило расписать подробнее.
Добавляешь в секцию стрима
log_format custom_stream_log 'proxy: $status $protocol remote_addr $remote_addr, sent_to $upstream_addr';
А ниже есть подсекция server, где происходит проксирование на бэкенды, туда нужно добавить строку
access_log syslog:server=unix:/dev/log custom_stream_log;
дабы логи писались.
т.е. не добавляем еще один server, а добавляем логирование в имеющийся.
Сделал, ругается на логи:
nginx: [emerg] unknown log format “custom_stream_log” in /etc/nginx/nginx.conf:53
nginx: configuration file /etc/nginx/nginx.conf test failed
А можно на nginx.conf взглянуть?
Естественно:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
stream {
map $ssl_preread_server_name $backend {
XXXXX.com reality;
XXXXX.XXXXX.com local;
default reality;
}
upstream reality {
server 127.0.0.1:8443;
}
upstream local {
server 127.0.0.1:8444;
}
server {
listen 443 reuseport so_keepalive=on;
ssl_preread on;
proxy_pass $backend;
access_log syslog:server=unix:/dev/log custom_stream_log;
}
log_format custom_stream_log 'proxy: $status $protocol remote_addr $remote_addr, sent_to $upstream_addr';
}
}
Нужно сначала объявить лог.
т.е. нужно строку
log_format custom_stream_log ...
поместить перед
server {
listen 443 reuseport so_keepalive=on;
del
Да, теперь стало писаться в access.log:
127.0.0.1 - - [13/May/2024:01:23:27 +0300] "\x16\x03\x01\x018\x01\x00\x014\x03\x03\x89\xEF\x9A\xD1\xC8\x8C6\x11\xFB\xE6(s!\x8D=\x90y\x07\x15q\xF1\x04\xE3\xED\xFB\xF1(\xC1{K\x80@ jY\x89\x03\xE3\xFE,\x13\x0C\x1Ek9\x86\xF1\xD9\x85~\xB7\xB0" 400 157 "-" "-" "-"
127.0.0.1 - - [13/May/2024:01:23:40 +0300] "\x16\x03\x01\x018\x01\x00\x014\x03\x03&\xE1\x84\xDFHOhR\xE5H\xB1(\xE7e\xFF\xD0\x8D\xD7\xFE'J\x22\x19\x7FHd\xFA\xEB\xE9[~* \xE5fW%\x04h\x8D" 400 157 "-" "-" "-"
127.0.0.1 - - [13/May/2024:01:24:13 +0300] "\x16\x03\x01\x018\x01\x00\x014\x03\x03D\x8Du\x83\x10\x19\xCB\xCF\x16\xF1z\x1D\x10b\xB2q\x1D\x95\x93Ap\xF0 \x0E$<\x131\x99\x87\xA7m \xAF-T +\xEBS\xEF\x872\xD6\xE8\x8C\xA3\x91\xBAn\xF08\xC6\x1AB\xBC\x0C@\xD4M\x94\xC3\xB3j\xED\x00>\x13\x02\x13\x03\x13\x01\xC0,\xC00\x00\x9F\xCC\xA9\xCC\xA8\xCC\xAA\xC0+\xC0/\x00\x9E\xC0$\xC0(\x00k\xC0#\xC0'\x00g\xC0" 400 157 "-" "-" "-"
127.0.0.1 - - [13/May/2024:01:24:32 +0300] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03M\xF4;(u\x1C\x96\xF2|C\x08M\xC4\xCA\x14\x8B\x03F\xDBT\x98\x10\xB9\x03y\x85U\xC0\xAE\x90<o De\xCB\x06\x9DZ\xF3\x91\xC86Z\xFAt\xBA8*\x04\xEFI_\x83\xF1\x01\xBC\xDF1\xFB\xE9\x96j\x85(\x00 \xEA\xEA\x13\x01\x13\x02\x13\x03\xC0+\xC0/\xC0,\xC00\xCC\xA9\xCC\xA8\xC0\x13\xC0\x14\x00\x9C\x00\x9D\x00/\x005\x01\x00\x01\x93jj\x00\x00\xFF\x01\x00\x01\x00\x00\x10\x00\x0B\x00\x09\x08http/1.1\x00\x17\x00\x00\x00+\x00\x07\x06**\x03\x04\x03\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00" 400 157 "-" "-" "-"
Логов самой прокси не видно, они должны начинаться с “proxy:”.
Можно, например, в терминале набрать journalctl -u nginx -f
И просто в браузере открыть свой сайт XXXXX.XXXXX.com, потыкать Ctrl+f5 (обновить с чисткой кэша), и смотреть, появятся ли записи типа:
proxy: 200 5653 TCP remote_addr 123.123.123.123, sent_to 127.0.0.1:8444
Таким образом убедившись, что запросы со своего внешнего адреса remote_addr улетают на слушателя nginx 127.0.0.1:8444, который, в свою очередь, может при знании нужного URL апгрейднуть соединение до ws и послать его в xray.
Первая строчка подключение по реалити, вторая - через CDN, третья - напрямую.
May 13 02:43:15 nginx: proxy: 200 TCP remote_addr XX.XX.109.166, sent_to 127.0.0.1:8443
May 13 02:43:26 nginx: proxy: 200 TCP remote_addr XX.XXX.113.11, sent_to 127.0.0.1:8444
May 13 02:44:02 nginx: proxy: 200 TCP remote_addr XX.XX.109.166, sent_to 127.0.0.1:8444
Ну пока все выглядит хорошо. В конфиге nginx, приведенном выше, тоже проблем не вижу.
Опять же, для верности, можно посмотреть, есть ли обмен с xray, хоть какой-то.
sudo tcpdump -i lo port 8889
И, если обмен есть, то смотреть логи xray, если обмена нет, то смотреть в nginx
Обмена никакого нет, когда я присоединяюсь на прямую или через CDN. Может в этом файле что-то не так, других-то я и не изменял /etc/nginx/conf.d/default.conf
server {
listen 127.0.0.1:8444 so_keepalive=on;
http2 on;
# ваш домен
server_name XXX.XXX.com;
#access_log /var/log/nginx/host.access.log main;
# сюда можно положить какие-нибудь странички фейкового сайта, или использовать proxy_pass чтобы переадресовать запрос на другой сервер
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/html;
#}
# путь к сертификатам, самоподписанным либо от Cloudflare
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
client_header_timeout 52w;
keepalive_timeout 52w;
# замените TestChatGRPC на какую-нибудь секретную строку
location /XXXXX {
if ($content_type !~ "application/grpc") {
return 404;
}
client_max_body_size 0;
client_body_buffer_size 512k;
grpc_set_header X-Real-IP $remote_addr;
client_body_timeout 52w;
grpc_read_timeout 52w;
grpc_pass grpc://127.0.0.1:8888;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
# аналогично замените TestChatWS на какую-нибудь другую секретную строку
location /XXXXX {
if ($http_upgrade != "websocket") {
return 404;
}
proxy_pass http://127.0.0.1:8889;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 52w;
}
}
Ну каких-то особых проблем я не вижу.
Но, во-первых, советую добавить ssl в заголовок, он вроде нужен, если идет работа с сертификатами.
У меня, например, так:
server {
listen 127.0.0.1:8444 ssl http2 so_keepalive=on;
Во-вторых, интересно было бы посмотреть, что там nginx выдает при попытке соединения.
Предположим, что ws URL - 12345.
location /12345 {
if ($http_upgrade != "websocket") {
return 404;
}
...
Тогда ищем в журнале
journalctl -u nginx -r
Что-то вроде
nginx: 101 4076 "GET /12345 HTTP/1.1" "-" "Go-http-client/1.1"
Не обязательно именно такую строку, т.к. у меня формат логов изменен. Но обращать внимание на путь /12345 и статус. 101 - изменение протокола, т.к. http меняется на ws
DEL
Немного чище конфиг
server {
listen 127.0.0.1:8444 ssl so_keepalive=on;
http2 on;
server_name XXX.XXX.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# путь к сертификатам, самоподписанным либо от Cloudflare
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
location /XXXXX {
if ($content_type !~ "application/grpc") {
return 404;
}
client_max_body_size 0;
client_body_buffer_size 512k;
grpc_set_header X-Real-IP $remote_addr;
client_body_timeout 52w;
grpc_read_timeout 52w;
grpc_pass grpc://127.0.0.1:8888;
}
location /XXXXX {
if ($http_upgrade != "websocket") {
return 404;
}
proxy_pass http://127.0.0.1:8889;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 52w;
}
Кстати, у автора статьи он тоже отсутствует в конфиге. Я добавил ssl в заголовок, получаю следующее сообщение:
ошибка теста: Get "http://cp.cloudflare.com/": x509: certificate signed by unknown authority
Если разрешить небезопасное соединение TLS в nekobox:
ошибка теста: Get "http://cp.cloudflare.com/": context deadline exceeded
Получал ли ты сертификат для XXX.XXX.com? Сертификат от того же let’s encrypt, насколько я помню, распространяется только на домены и поддомены, которые явно указаны при запросе.
Ну и логи nginx бы посмотреть. В зависимости от настроек они падают либо в системный журнал, либо в /var/log/nginx
Мне let’s encrypt выписал Gcore, но кнопки скачать его нет.
Появилась такая запись при подключении с небезопасным TLS:
/var/log/nginx/access.log
127.0.0.1 - - [14/May/2024:00:43:45 +0300] "GET /XXXXX HTTP/1.1" 101 4 "-" "Go-http-client/1.1" "-"
Кстати, в журнале проскакивает какая то строчка, если что:
systemd[1]: nginx.service: Can't open PID file /run/nginx.pid (yet?) after start: Operation not permitted
Мне let’s encrypt выписал Gcore, но кнопки скачать его нет.
А это что за сертификаты тогда?
/etc/nginx/conf.d/default.conf
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
Самоподписанные?
У меня нет опыта работы с сертификатами, выданными cdn провайдерами. Но как вариант, попробуй настраивать всё на тот домен, который указал при настройке GCore. Если вводил не XXX.XXX.com, а XXX.com, то его и нужно прописать и в настройках nginx - server_name XXX.com;
и в настройках Nekoray тоже
127.0.0.1 - - [14/May/2024:00:43:45 +0300] “GET /XXXXX HTTP/1.1” 101 4 “-” “Go-http-client/1.1” “-”
Это хороший знак, осталось разобраться с сертификатами
Да, на XXX.XXX.com. Уже прописан у меня и в server_name и в nekobox.
Из статьи:
Также нам понадобится TLS‑сертификат, если у вас его еще нет. Как я уже говорил, при работе через CDN хватит самоподписанного сертификата (все равно его не будет видно снаружи, он используется только для связи между фронтендом CDN и вашим сервером), либо «внутреннего» сертификата от Cloudflare.
Выходит, эти сертификаты для сервера и CDN, а про прямое подключение ничего не говорится. В nekobox есть такое окошко, может туда чего прописать? Просто скопировать ключ из самоподписного сертификата завершается множественными ошибками.