Рейтинг:0

Синтаксис операторов обратного прокси-сервера NGINX «если нет»?

флаг us

У меня есть обратный прокси-сервер nginx, который я хочу в основном перенаправить любой запрос URL-адреса, который не является моим конкретным доменом верхнего уровня, на 404.

До сих пор я думаю, что хочу что-то вроде этого в нижней части моего /etc/nginx/sites-enabled/site.conf:

сервер {
        слушать 80;
        если ($ хост != *domain.com) {
                вернуть 404 http://$host$request_uri;
        }
}

но я не знаю точного синтаксиса здесь. У меня уже есть другие блоки перенаправления выше этого, я просто хочу, чтобы любые запросы URL-адресов для имен хостов только для IP или других доменов немедленно получали 404 и не передавались на внутренние серверы.

Кроме того, у меня также есть сквозной канал TLS, на котором я хотел бы сделать то же самое, но я совершенно не понимаю, как реализовать оператор if в блоке потока. Мой блок потока выглядит следующим образом: /etc/nginx/nginx.conf:

транслировать {
        карта $ ssl_preread_server_name $ имя {
                сервер server.domain.com;
                www.домен.com www;
        }
        восходящий сервер {
                серверная часть: 443;
        }
        вверх по течению www {
                серверная часть2:443;
        }
        сервер {
                слушать 443;
                прокси_пароль $имя;
                ssl_preread включен;
        }
}

Для этого я реализовал бы что-то подобное прямо под первым блоком сервера?

        сервер {
                слушать 443;
                если ($ ssl_preread_server_name != *domain.com) {
                        вернуть 404 https://$host$request_uri;
                }
        }

Я думаю, что в целях безопасности я также должен включить default_server в строку прослушивания для обоих этих блоков с операторами if, или это имеет значение?

Я просто предполагаю, что здесь много синтаксиса, поэтому любая помощь будет очень признательна.

Ivan Shatsky avatar
флаг gr
Вы можете либо проверить точное соответствие/несоответствие строк, либо выполнить сопоставление с учетом регистра/нечувствительного к шаблону регулярного выражения. Похоже, вы ищете `if ($var !~ (.*\.)?domain\.com$) { ... }`. Недавно я дал подробный ответ о блокировке всего доступа по IP-адресу, а не по имени хоста [здесь] (https://stackoverflow.com/questions/69824838/block-access-with-https-ipaddress-on-nginx/69825652# 69825652).
ehammer avatar
флаг us
Я проверил ваш другой пост, который помогает моим блокам http. Все еще не знаете, как это сделать с помощью nginx TLS passthrough (возврат 444, если SNI не является определенным доменом)
Ivan Shatsky avatar
флаг gr
Ну, я не так хорошо разбираюсь в потоковом модуле, как в http. Вы не можете использовать что-либо из модуля перезаписи (включая `if`). Вы не можете использовать `return 444`, так как модуль потока имеет свою собственную директиву [`return`](http://nginx.org/en/docs/stream/ngx_stream_return_module.html), отличную от директивы http.
Рейтинг:1
флаг gr

Я не знал, как изящно закрыть соединение с потоковым модулем, поэтому я не уверен, что это будет правильное решение, но попробовать стоит (вы можете использовать любой свободный порт для фиктивного сервера/восходящего потока):

транслировать {
    карта $ ssl_preread_server_name $ имя {
        сервер server.domain.com;
        www.домен.com www;
        манекен по умолчанию;
    }
    восходящий сервер {
        серверная часть: 443;
    }
    вверх по течению www {
        серверная часть2:443;
    }
    манекен вверх по течению {
        серверная часть 127.0.0.1:4343;
    }
    сервер {
        слушать 443;
        прокси_пароль $имя;
        ssl_preread включен;
    }
    сервер {
        слушать 4343;
        возвращаться "";
    }
}

Обновлять

Проверив приведенное выше решение, я могу подтвердить, что оно работоспособно. Однако он создает запись в журнале ошибок, например

Ошибка WSARecv() (10053: установленное соединение было прервано программным обеспечением на вашем хост-компьютере) при проксировании и чтении из восходящего потока, клиент: 127.0.0.1, сервер: 127.0.0.1:443, восходящий поток: «127.0.0.1:4343» , байт от/к клиенту: 517/0, байт от/к восходящему потоку: 0/517

Итак, немного подумав, я попробовал это:

http {
    сервер {
        слушать 4343 ssl;
        ssl_certificate /путь/к/selfsigned.crt;
        ssl_certificate_key /path/to/selfsigned.key;
        вернуть 444;
    }
}
транслировать {
    карта $ ssl_preread_server_name $ имя {
        сервер server.domain.com;
        www.домен.com www;
        манекен по умолчанию;
    }
    восходящий сервер {
        серверная часть: 443;
    }
    вверх по течению www {
        серверная часть2:443;
    }
    манекен вверх по течению {
        серверная часть 127.0.0.1:4343;
    }
    сервер {
        слушать 443;
        прокси_пароль $имя;
        ssl_preread включен;
    }
}

Самоподписанный сертификат и ключ можно создать с помощью следующей команды:

openssl req -nodes -new -x509 -subj "/CN=localhost" -keyout /path/to/selfsigned.key -out /path/to/selfsigned.crt

Этот правильно закрывает соединение.

Более того, даже это сработало:

http {
    сервер {
        слушать 80 default_server;
        вернуть 444;
    }
}
транслировать {
    карта $ ssl_preread_server_name $ имя {
        сервер server.domain.com;
        www.домен.com www;
        манекен по умолчанию;
    }
    восходящий сервер {
        серверная часть: 443;
    }
    вверх по течению www {
        серверная часть2:443;
    }
    манекен вверх по течению {
        серверная часть 127.0.0.1:80;
    }
    сервер {
        слушать 443;
        прокси_пароль $имя;
        ssl_preread включен;
    }
}

Конечно, завиток жалуется на попытку рукопожатия для неверного номера версии SSL и в журнале доступа есть забавные записи типа

127.0.0.1 - - [05/ноября/2021:01:04:34 +0200] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03L\xF9[\xB2\x7F \x99\xB1(\xAC\xB4\x91}\xE2N\xC6H\xE3\xB3_\xD1\xEA\xA3C\x1D\xE5\xE5\xB6\x02\xDB\x04h\xB6 *\xCB\x0E\xC0\ xF5\xB7\xAF[y|\x1B\x14_\xC2g\xEA\xA2\x1E\xB4\xC4Bj3t\xE8d\xE72vm\xF2\x1B\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 163 "- ""-"

но журнал ошибок чист.

ehammer avatar
флаг us
Кажется, это работает.Я никогда не хотел изящно закрывать соединение. Я хотел больше функциональности типа http444. Тихо проваливается.
Ivan Shatsky avatar
флаг gr
@ehammer Проверьте обновление.
ehammer avatar
флаг us
Мне это нравится. У меня уже был блок HTTP по умолчанию, указывающий 127.0.0.1:80 на HTTP444, так что это очень хорошо интегрируется с этим. Параметр ```default``` под блоком карты на самом деле означает default_server или это просто имя-заполнитель?
Ivan Shatsky avatar
флаг gr
Это специальное ключевое слово для блока карты, означающее, что это значение будет возвращено, если другие варианты не совпадут. Если это не указано явно, значением по умолчанию является пустая строка.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.