IIS как пограничный веб-сервер

в 11:09, , рубрики: iis, web, windows, системное администрирование

В этой статье я хочу описать не самый типичный сценарий, который, тем не менее, имеет право на жизнь.
Дело в том, что мы используем IIS как прокси для других веб-серверов компании. Я расскажу, как это реализовано и с какими трудностями пришлось столкнуться​.

Постановка задачи
Разберём на примере сервера YouTrack. Он представлен неприглядным srv-youtrack-01.local.domain и находится на веб-сервере внутри компании. Задача заключается в том, чтобы обеспечить доступ к нему из интернета по красивому имени yt.company.ru. При этом обязательно должен использоваться https.

Реализация
Для начала работы нам понадобится установить компонент URL Rewrite. Это можно сделать при помощи web platform installer, а также вручную. После его установки мы увидим в диспетчере служб IIS новый ярлык
переопределение URL-адресов".
image

При помощи этого инструмента можно создать правило переопределения адресов «обратный прокси-сервер».

image

При создании правила нужно указать URL сервера (без префикса http:// — его IIS добавит автоматически), на который будет происходить проксирование. В итоге мы получим правило, доступное для редактирования. Оно применяется не ко всем запросам, а только к тем, которые подходят под критерии, которые мы можем настраивать. Для начала проверяется URL на соответствие шаблону, после чего в ход идут проверки по другим критериям.

image

Сразу оговорюсь, что тут есть два пути: первый путь — создать набор правил с разными шаблонами URL-адресов для разных ресурсов на одном IIS-сайте; а второй — создать по сайту для каждого проксируемого ресурса и в каждом из них сделать по одному правилу. Понимая, что первый путь более джедайский, я все-таки избрал путь второй — пусть не такой красивый, зато я не рискую написав неправильное регулярное выражение для одного сайта сломать всю маршрутизацию. Поэтому шаблон URL-адреса у меня везде дефолтный "(.*)".

Итак, я создаю сайт yt.company.ru с биндингами на 80 и 443 порт и обязательным указанием имени узла, чтобы IIS знал, к какому сайту я обращаюсь. Про получение и установку сертификата для 443 позволю себе не упоминать. Обращу лишь внимание, что сам сервис настраивать на использование https не нужно — внутри сети шифроваться не от кого, а внешние запросы будут соединяться по ssl с пограничным сервером, который будет уже по незащищенному каналу проксировать запросы внутри сети.

Покуда обязательным требованием является использование https, будем проксировать только те запросы, которые приходят на 443 порт, для чего создадим простое условие. При его создании предлагается выпадающий список возможных вариантов.

image
image

Отлично, теперь все запросы yt.company.ru проксируются на внутренний сервер с неприглядным именем srv-youtrack-01.local.domain прозрачно для пользователя.

Однако, все запросы yt.company.ru отсекаются с ошибкой 403, что не очень красиво. Для решения этой проблемы можно либо создать index.html с редиректом, либо еще одно правило URL Rewrite, у которого в поле «действие» выберем постоянное перенаправление на нужный нам URL.

image

Следует обратить внимание, что правила для сайта применяются по порядку, поэтому сначала нужно расположить правило с условием, а потом правило без условий. При этом, так как второе правило применяется ко всем URL без исключения, для первого правила необходимо поставить (оставить поставленной) галочку «Остановить обработку последующих правил».

image

После манипуляций с графическим интерфейсом в корне нашего сайта создается web.config, который содержит все созданные правила. Поэтому если требуется проксировать еще какой-то сайт, то эти манипуляции повторять не нужно, можно просто скопировать web.config и изменить в нем требуемый URL или после копирования воспользоваться графическим интерфейсом для изменения правил. Более того, можно вообще не пользоваться интерфейсом, а писать сразу туда — кому как нравится.

Подводные камни
При переходе на вкладку «Agile boards» YouTrack генерит URL-адрес вида yt.company.ru/rest/agile/Overview-0/sprint/Iteration+24. Далее, при переключении между спринтами yt.company.ru/rest/agile/Overview-0/sprint/Iteration%252023?q=. При переходе на эти урлы IIS стал возвращать мне 404 ошибку. Это свидетельствовало о том, что запросы не проксируются. При этом переходы между сохраненными запросами вида yt.company.ru/issues/IT?q=%23{Current+work}+Assigned+to%3A+me+updated%3A+{This+week} вполне корректно отрабатывали.

Эксперименты с добавлением знака вопроса в середину проблемного URL закончились тем, что я стал получать 404 ошибку уже от YouTrack-сервера, а не IIS. Это натолкнуло меня на мысль, что IIS по каким-то своим соображениям (привет, Microsoft) интерпретирует URL и это надо исправить.

Проблема со знаком «плюс» в середине адреса решилась добавлением параметра requestFiltering allowDoubleEscaping=«true»:

<system.webServer>
    <security>
            <requestFiltering allowDoubleEscaping="true" />
    </security>
</system.webServer>

Но после этого все еще не работало переключение между спринтами. Выяснилось, что IIS считает такие запросы небезопасными. Эту проверку тоже пришлось отключить:

<system.web>
    <httpRuntime requestPathInvalidCharacters="" />
</system.web>

Вот какой web.config получился после всех манипуляций:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="ProxyToYouTrack" patternSyntax="ECMAScript" stopProcessing="true">
                    <match url="(.*)" negate="false" />
                    <action type="Rewrite" url="http://srv-youtrack-01.local.domain/{R:1}" appendQueryString="true" logRewrittenUrl="true" />
                    <conditions>
                        <add input="{SERVER_PORT}" pattern="443" />
                    </conditions>
                </rule>
                <rule name="redir to ssl" enabled="true" stopProcessing="true">
                    <match url="(.*)" />
                    <action type="Redirect" url="https://yt.company.ru" />
                </rule>
            </rules>
            <outboundRules>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                    </preCondition>
                </preConditions>
            </outboundRules>
        </rewrite>
        <security>
            <requestFiltering allowDoubleEscaping="true" />
        </security>
    </system.webServer>
    <system.web>
	<httpRuntime requestPathInvalidCharacters="" />
    </system.web>
</configuration>

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

Таким образом у нас в организации проксируются абсолютно все веб-серверы, которым нужен доступ извне, среди которых есть и nginx, и apache, и svn, и gitlab, и exchange web access.

Основная проблема, которая заставляет меня находиться в поиске решения заключается в том, что через прокси не работает NTLM-авторизация, так нужная для многих сервисов компании Microsoft. Мёртвый продукт TMG использовать не хочется, поэтому сейчас пытаюсь разобраться с новой службой Windows Server 2012 R2 под названием Web Application Proxy параллельно поглядывая на nginx и apache, которые, кажется, тоже пока не умеют проксировать NTLM.

Ссылки

http://www.ifinity.com.au/Blog/EntryId/60/404-Error-in-IIS-7-when-using-a-Url-with-a-plus-sign-in-the-path
stackoverflow.com/questions/2831142/asp-net-4-url-limitations-why-url-cannot-contain-any-3f-characters

Автор: Botkin

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js