init_guac
This commit is contained in:
185
guacamole_test_11_26/nginx/mc.exbytestudios.com.conf
Executable file
185
guacamole_test_11_26/nginx/mc.exbytestudios.com.conf
Executable file
@ -0,0 +1,185 @@
|
||||
# Docker Nginx конфигурация для mc.exbytestudios.com
|
||||
# Внутренний nginx в Docker контейнере
|
||||
# Принимает HTTP от внешнего nginx, проксирует в сервисы
|
||||
|
||||
# WebSocket upgrade mapping
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
# Upstream definitions (using Docker service names)
|
||||
upstream remote_access_api {
|
||||
server remote_access_api:8000;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream guacamole_web {
|
||||
server guacamole:8080;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
# Main server block - слушает на порту 8443 для внешнего nginx
|
||||
server {
|
||||
listen 8443;
|
||||
server_name _; # Принимаем любой Host от внешнего nginx
|
||||
|
||||
# Logging (внутренние логи Docker)
|
||||
access_log /var/log/nginx/docker.access.log;
|
||||
error_log /var/log/nginx/docker.error.log;
|
||||
|
||||
# General settings
|
||||
client_max_body_size 10M;
|
||||
client_body_timeout 60s;
|
||||
client_header_timeout 60s;
|
||||
keepalive_timeout 65s;
|
||||
|
||||
# Root location - redirect to API docs
|
||||
location = / {
|
||||
return 302 /api/docs;
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# API Endpoints - Все бизнес-эндпоинты с префиксом /api/
|
||||
# =========================================================================
|
||||
# FastAPI endpoints: /api/auth/*, /api/connections, /api/machines/*,
|
||||
# /api/bulk/*, /api/security/*
|
||||
# CORS headers добавляются в Gateway nginx для избежания дубликатов
|
||||
location /api/ {
|
||||
proxy_pass http://remote_access_api;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $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_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# Передача Content-Type и Content-Length для POST/PUT
|
||||
proxy_set_header Content-Type $content_type;
|
||||
proxy_set_header Content-Length $content_length;
|
||||
|
||||
# Timeouts
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 120s;
|
||||
proxy_read_timeout 120s;
|
||||
|
||||
# Buffering для POST body
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
client_max_body_size 10M;
|
||||
|
||||
# Cache control
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
add_header Pragma "no-cache" always;
|
||||
add_header Expires "0" always;
|
||||
}
|
||||
|
||||
# ✅ WebSocket Notifications - специальная обработка для WebSocket
|
||||
# КРИТИЧНО: Длинные таймауты и отключение буферизации для WebSocket
|
||||
location /ws/ {
|
||||
proxy_pass http://remote_access_api;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# ✅ WebSocket upgrade headers
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
# Standard proxy headers
|
||||
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_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# ✅ КРИТИЧНО: Длинные таймауты для WebSocket (до 2 часов)
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 7200s;
|
||||
proxy_read_timeout 7200s;
|
||||
|
||||
# ✅ КРИТИЧНО: Отключаем буферизацию для WebSocket
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Cache control
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
}
|
||||
|
||||
|
||||
# Guacamole Web Application
|
||||
location /guacamole/ {
|
||||
proxy_pass http://guacamole_web/guacamole/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $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_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket support for Guacamole
|
||||
proxy_read_timeout 7200s;
|
||||
proxy_send_timeout 7200s;
|
||||
|
||||
# Buffer settings for WebSocket
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Allow iframe embedding for Guacamole client (desktop/electron apps)
|
||||
proxy_hide_header X-Frame-Options;
|
||||
proxy_hide_header Content-Security-Policy;
|
||||
|
||||
# Cache control
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
}
|
||||
|
||||
# Guacamole WebSocket tunnel
|
||||
location /guacamole/websocket-tunnel {
|
||||
proxy_pass http://guacamole_web/guacamole/websocket-tunnel;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $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_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket specific settings
|
||||
proxy_read_timeout 7200s;
|
||||
proxy_send_timeout 7200s;
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Allow iframe embedding and WebSocket in iframe
|
||||
proxy_hide_header X-Frame-Options;
|
||||
proxy_hide_header Content-Security-Policy;
|
||||
}
|
||||
|
||||
# Guacamole static assets
|
||||
location ~ ^/guacamole/(.*\.(js|css|json|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot))$ {
|
||||
proxy_pass http://guacamole_web/guacamole/$1;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
# Cache static assets for 1 hour
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
expires 1h;
|
||||
}
|
||||
|
||||
# Custom error pages
|
||||
error_page 404 /404.html;
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
location = /404.html {
|
||||
return 404 '{"error": "Not Found", "message": "The requested resource was not found"}';
|
||||
add_header Content-Type application/json always;
|
||||
}
|
||||
|
||||
location = /50x.html {
|
||||
return 500 '{"error": "Internal Server Error", "message": "Please try again later"}';
|
||||
add_header Content-Type application/json always;
|
||||
}
|
||||
}
|
||||
329
guacamole_test_11_26/nginx/mc.exbytestudios_gate.com
Executable file
329
guacamole_test_11_26/nginx/mc.exbytestudios_gate.com
Executable file
@ -0,0 +1,329 @@
|
||||
# =============================================================================
|
||||
# Gateway Nginx Configuration for mc.exbytestudios.com
|
||||
#
|
||||
# Архитектура:
|
||||
# Internet -> Gateway Nginx (этот сервер) -> Docker Server (192.168.200.10:8443)
|
||||
#
|
||||
# Gateway: SSL termination, DDoS protection, Rate limiting, Security headers
|
||||
# Docker: Internal nginx -> FastAPI + Guacamole
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# CORS Allowed Origins
|
||||
# 🔒 ВАЖНО: Добавьте сюда только доверенные домены!
|
||||
# =============================================================================
|
||||
map $http_origin $cors_origin {
|
||||
default "";
|
||||
"~^https://mc\.exbytestudios\.com$" $http_origin;
|
||||
"~^https://test\.exbytestudios\.com$" $http_origin;
|
||||
"~^http://localhost:5173$" $http_origin;
|
||||
"~^http://127\.0\.0\.1:5173$" $http_origin;
|
||||
}
|
||||
|
||||
# Rate limiting для защиты от DDoS
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
|
||||
limit_req_zone $binary_remote_addr zone=guacamole:10m rate=50r/s;
|
||||
|
||||
# Upstream для Docker сервера (внутренняя сеть)
|
||||
upstream docker_server {
|
||||
server 192.168.200.10:8443;
|
||||
keepalive 32;
|
||||
keepalive_requests 100;
|
||||
keepalive_timeout 60s;
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# HTTP Server - Redirect to HTTPS
|
||||
# =============================================================================
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name mc.exbytestudios.com;
|
||||
|
||||
# Let's Encrypt ACME challenge
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/html;
|
||||
}
|
||||
|
||||
# Redirect all other traffic to HTTPS
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# HTTPS Server - Main Gateway
|
||||
# =============================================================================
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name mc.exbytestudios.com;
|
||||
|
||||
# SSL Configuration
|
||||
# ⚠️ Эти пути будут автоматически настроены certbot
|
||||
# Если certbot не используется, замените на свои сертификаты
|
||||
ssl_certificate /etc/letsencrypt/live/mc.exbytestudios.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/mc.exbytestudios.com/privkey.pem;
|
||||
|
||||
# Modern SSL configuration (Mozilla Intermediate)
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_tickets off;
|
||||
|
||||
# OCSP Stapling
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/mc.exbytestudios.com/chain.pem;
|
||||
resolver 8.8.8.8 8.8.4.4 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
|
||||
# Security Headers
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/mc.exbytestudios.com.access.log;
|
||||
error_log /var/log/nginx/mc.exbytestudios.com.error.log warn;
|
||||
|
||||
# General settings
|
||||
client_max_body_size 100M;
|
||||
client_body_timeout 120s;
|
||||
client_header_timeout 120s;
|
||||
keepalive_timeout 65s;
|
||||
|
||||
# =========================================================================
|
||||
# Root - Redirect to API docs
|
||||
# =========================================================================
|
||||
location = / {
|
||||
return 302 /api/docs;
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# API Endpoints - Rate limiting
|
||||
# =========================================================================
|
||||
location /api/ {
|
||||
limit_req zone=api burst=20 nodelay;
|
||||
|
||||
# ✅ CORS Headers для /api/machines/saved и других /api/* endpoints
|
||||
# Используем $cors_origin из map для проверки разрешенных доменов
|
||||
add_header 'Access-Control-Allow-Origin' '$cors_origin' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
|
||||
# Handle preflight requests
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' '$cors_origin' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
proxy_pass http://docker_server;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $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_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# ✅ КРИТИЧНО: Скрываем CORS заголовки от backend чтобы избежать дубликатов
|
||||
proxy_hide_header Access-Control-Allow-Origin;
|
||||
proxy_hide_header Access-Control-Allow-Methods;
|
||||
proxy_hide_header Access-Control-Allow-Headers;
|
||||
proxy_hide_header Access-Control-Allow-Credentials;
|
||||
|
||||
# Timeouts
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 120s;
|
||||
proxy_read_timeout 120s;
|
||||
|
||||
# Buffering
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 8k;
|
||||
proxy_buffers 8 8k;
|
||||
proxy_busy_buffers_size 16k;
|
||||
|
||||
# Cache control
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
add_header Pragma "no-cache" always;
|
||||
add_header Expires "0" always;
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# WebSocket Notifications - специальная обработка для WebSocket
|
||||
# КРИТИЧНО: Длинные таймауты и отключение буферизации
|
||||
# =========================================================================
|
||||
location /ws/ {
|
||||
# Легкий rate limiting для WebSocket (меньше чем для API)
|
||||
limit_req zone=api burst=5 nodelay;
|
||||
|
||||
# ✅ CORS Headers для WebSocket подключений
|
||||
add_header 'Access-Control-Allow-Origin' '$cors_origin' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Sec-WebSocket-Protocol, Sec-WebSocket-Extensions, Sec-WebSocket-Key, Sec-WebSocket-Version' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
|
||||
# Handle preflight requests (хотя для WebSocket обычно не нужны)
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' '$cors_origin' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Sec-WebSocket-Protocol, Sec-WebSocket-Extensions, Sec-WebSocket-Key, Sec-WebSocket-Version' always;
|
||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
|
||||
proxy_pass http://docker_server;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
# ✅ КРИТИЧНО: WebSocket upgrade headers
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
# Standard proxy headers
|
||||
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_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# ✅ КРИТИЧНО: Скрываем CORS заголовки от backend
|
||||
proxy_hide_header Access-Control-Allow-Origin;
|
||||
proxy_hide_header Access-Control-Allow-Methods;
|
||||
proxy_hide_header Access-Control-Allow-Headers;
|
||||
proxy_hide_header Access-Control-Allow-Credentials;
|
||||
|
||||
# ✅ КРИТИЧНО: Длинные таймауты для WebSocket (до 2 часов)
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 7200s;
|
||||
proxy_read_timeout 7200s;
|
||||
|
||||
# ✅ КРИТИЧНО: Отключаем буферизацию для WebSocket
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Cache control
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# Guacamole Web Application - Rate limiting
|
||||
# =========================================================================
|
||||
location /guacamole/ {
|
||||
limit_req zone=guacamole burst=10 nodelay;
|
||||
|
||||
proxy_pass http://docker_server/guacamole/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $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_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket support - long timeouts for remote sessions
|
||||
proxy_read_timeout 7200s;
|
||||
proxy_send_timeout 7200s;
|
||||
|
||||
# Disable buffering for WebSocket
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Allow iframe embedding for Guacamole client (desktop/electron apps)
|
||||
proxy_hide_header X-Frame-Options;
|
||||
proxy_hide_header Content-Security-Policy;
|
||||
|
||||
# Cache control
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
}
|
||||
|
||||
# Guacamole WebSocket Tunnel
|
||||
location /guacamole/websocket-tunnel {
|
||||
limit_req zone=guacamole burst=5 nodelay;
|
||||
|
||||
proxy_pass http://docker_server/guacamole/websocket-tunnel;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $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_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket specific settings
|
||||
proxy_read_timeout 7200s;
|
||||
proxy_send_timeout 7200s;
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Allow iframe embedding and WebSocket in iframe
|
||||
proxy_hide_header X-Frame-Options;
|
||||
proxy_hide_header Content-Security-Policy;
|
||||
}
|
||||
|
||||
# Guacamole Static Assets - Caching
|
||||
location ~ ^/guacamole/(.*\.(js|css|json|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot))$ {
|
||||
proxy_pass http://docker_server/guacamole/$1;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
# Cache static assets for 1 hour
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
expires 1h;
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# Security - Block sensitive paths
|
||||
# =========================================================================
|
||||
location ~ ^/(\.env|\.git|docker-compose|Dockerfile|\.htaccess|\.htpasswd) {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# Error Pages
|
||||
# =========================================================================
|
||||
error_page 404 /404.html;
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
location = /404.html {
|
||||
return 404 '{"error": "Not Found", "message": "The requested resource was not found"}';
|
||||
add_header Content-Type application/json always;
|
||||
}
|
||||
|
||||
location = /50x.html {
|
||||
return 500 '{"error": "Internal Server Error", "message": "Service temporarily unavailable"}';
|
||||
add_header Content-Type application/json always;
|
||||
}
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# WebSocket Upgrade Mapping
|
||||
# =============================================================================
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
Reference in New Issue
Block a user