diff --git a/rproxy b/rproxy index f4a0547..0f8c39c 100644 --- a/rproxy +++ b/rproxy @@ -1,9 +1,9 @@ -#!/bin/sh +#!/bin/sh # rProxy — Менеджер обратного прокси для роутеров Keenetic / Netcraze # Публикация локальных сервисов через SSH-туннели + nginx на VPS # https://github.com/l-ptrol/rProxy -VERSION="1.8.6" +VERSION="1.8.8" export PATH="/opt/bin:/opt/sbin:$PATH" CONF_DIR="/opt/etc/rproxy" CONF_FILE="$CONF_DIR/rproxy.conf" @@ -972,39 +972,51 @@ do_edit_interactive() { scp_cmd "$tmp" "$VPS_USER@$VPS_HOST:$remote_loc_dir/$name.conf" rm -f "$tmp" + # Теперь эта функция генерирует ТОЛЬКО блоки location + # Основной конфиг сервера будет собираться отдельно + cat > "$target_file" << NGINXEOF + # Редирект с пути без слеша на путь со слешем (чтобы браузер не терял контекст) + if (\$request_uri = $path) { + return 301 \$scheme://\$host$path/; + } - # Пересборка основного конфига - if [ -n "$SVC_DOMAIN" ]; then - rebuild_vhost_config "$SVC_DOMAIN" "$SVC_EXT_PORT" "$SVC_VPS" - else - rebuild_ip_config "$name" "$SVC_EXT_PORT" "$SVC_TUNNEL_PORT" "$SVC_VPS" - fi + location $location_path { + $auth_config + proxy_pass http://127.0.0.1:$tunnel_port/; + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host "$stealth_host"; + proxy_set_header Origin "http://$stealth_host"; + proxy_set_header Referer "http://$stealth_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-Server \$host; + proxy_set_header X-Forwarded-Path "$path"; + + proxy_cookie_domain "$t_host" "\$host"; + proxy_cookie_path / "$path"; + # Редиректы: если приложение шлет Location: /login, Nginx заменит на Location: $path/login + proxy_redirect / "$path/"; - # SSL если он был настроен или сертификат уже есть - if [ "$SVC_SSL" = "yes" ] || { [ -n "$SVC_DOMAIN" ] && ssh_cmd "[ -f /etc/letsencrypt/live/$SVC_DOMAIN/fullchain.pem ]"; }; then - # Если SVC_SSL была "no", но сертификат нашли — помечаем как "yes" - if [ "$SVC_SSL" = "no" ]; then - sed -i "s/SVC_SSL=.*/SVC_SSL=\"yes\"/" "$SERVICES_DIR/$name.conf" - # Пересобираем vhost чтобы включить SSL блок - rebuild_vhost_config "$SVC_DOMAIN" "$SVC_EXT_PORT" "$SVC_VPS" + # Экспериментальная замена ссылок в HTML/JS для работы в подпутях (v1.8.7) + if (\$path != "/") { + # Убираем сжатие от бэкенда, чтобы Nginx мог видеть текст + proxy_set_header Accept-Encoding ""; + sub_filter_once off; + sub_filter_types text/html text/css application/javascript application/json; + # Заменяем ссылки начинающиеся с / на /путь/ + sub_filter '="/' '="$path/'; + sub_filter '=\"/' '=\"$path/'; + # Попытка поймать JS редиректы и AJAX + sub_filter 'location.href = \"/' 'location.href = \"$path/'; + sub_filter 'url: \"/' 'url: \"$path/'; fi - fi - - # Обновление htpasswd на VPS если включено - if [ "$SVC_NDM_AUTH" = "yes" ]; then - ssh_cmd "printf '%s\n' '$SVC_HTPASSWD' > /etc/nginx/rproxy_$name.htpasswd" - fi - - # Перезапустить туннель если он был запущен - if [ "$was_running" -eq 1 ]; then - do_start_service "$name" - fi - - msg "Сервис '$name' успешно обновлён локально и на VPS!" - pause -} - -# ══════════════════════════════════════════════════════════════════════ + } +NGINXEOF +�══════ # ВЫБОР СЕРВИСА (общий) # ══════════════════════════════════════════════════════════════════════ select_service() { @@ -1298,7 +1310,15 @@ rebuild_vhost_config() { server { EOF # Не выводим обычный listen 443, если сейчас будет выведен listen 443 ssl - if [ "$ext_port" != "443" ] || [ "$has_ssl" -eq 0 ]; then + if [ "$has_ssl" -eq 1 ]; then + echo " listen $ext_port ssl;" >> "$tmp_vhost" + cat >> "$tmp_vhost" << EOF + ssl_certificate $cert_file; + ssl_certificate_key $key_file; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; +EOF + else echo " listen $ext_port;" >> "$tmp_vhost" fi @@ -1308,32 +1328,21 @@ EOF proxy_request_buffering off; include $REMOTE_LOCATIONS_DIR/$domain/*.conf; +} EOF - - if [ "$has_ssl" -eq 1 ]; then - cat >> "$tmp_vhost" << EOF - listen 443 ssl; - ssl_certificate $cert_file; - ssl_certificate_key $key_file; - include /etc/letsencrypt/options-ssl-nginx.conf; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; -EOF - fi - echo "}" >> "$tmp_vhost" - # Редирект с 80 на 443 если есть SSL + # Редирект с 80 на HTTPS (только если есть SSL и это не порт 80) if [ "$has_ssl" -eq 1 ] && [ "$ext_port" != "80" ]; then + local redirect_url="https://\$host" + [ "$ext_port" != "443" ] && redirect_url="https://\$host:$ext_port" cat >> "$tmp_vhost" << EOF server { listen 80; server_name "$domain"; - return 301 https://\$host\$request_uri; + return 301 $redirect_url\$request_uri; } EOF fi - - scp_cmd "$tmp_vhost" "$VPS_USER@$VPS_HOST:$REMOTE_NGINX_DIR/rproxy_dom_$domain.conf" - else # Это не должно вызываться для IP-публикаций напрямую через эту функцию # Но на всякий случай оставим заглушку return 1