Насочването на виртуален хост на Subversion към VPN адрес променя кой сайт отговаря на заявката, а не кой има право да я изпрати. Проверката на достъпа се извършва по-късно, според правилата в секцията, която съответства на URL, и името на хоста никога не участва в това решение. Ако ServerName беше единствената ви промяна, хранилището е точно толкова достъпно, колкото беше вчера. В конфигурацията трябва да се отговори на два отделни въпроса: кой сокет е приел връзката и каква самоличност е носила заявката.

Какво всъщност решава ServerName

Виртуалният хостинг по име сравнява заглавката Host със записите ServerName и ServerAlias, избира един хост и оставя той да обработва заявката. Самата връзка е приета по-рано от сокет Listen, който принадлежи на сървъра, а не на хоста. Затова име, което изглежда частно, не дава защита: всеки клиент, който достига до сокета, може да изпрати тази заглавка Host. Името е ключ за маршрутизиране, а ключовете за маршрутизиране се избират от извикващия.

Можете да видите съответствието без догадки. apachectl -S отпечатва всеки хост, неговия порт и имената му и отбелязва кой е по подразбиране за адреса.

RequireAll е контейнерът, който прави двете проверки задължителни

Apache 2.4 обвива директивите Require на една секция в неявен RequireAny, така че две голи директиви означават, че една от тях е достатъчна. Добавете контейнера и значението се обръща:

<Location /svn/repo>
    AuthType Basic
    AuthName "Subversion"
    AuthBasicProvider file
    AuthUserFile /etc/apache2/svn.htpasswd
    <RequireAll>
        Require ip 10.8.0.0/24
        Require valid-user
    </RequireAll>
</Location>

RequireAll изисква и двете условия: адрес на източника в обхвата на тунела и потребител, който хранилището приема. Това трябва да означава само-VPN за Subversion URL. Справката за mod_authz_core документира правилата на контейнера. Оставете блока в съществуващия Location за хранилището и запазете работещите DAV директиви, защото този фрагмент не заменя нито AuthType, нито файла с пароли, нито оторизацията на ниво път.

Проверката на източника идва от mod_authz_host, затова потвърдете, че е зареден, преди да отстранявате други проблеми: apachectl -M | grep authz_host.

Адресът, който Apache оценява, е адресът на сокета

Require ip сравнява с адреса, който Apache е записал за връзката, а той не винаги е адресът, който клиентът смята, че има.

Когато VPN маршрутизира адресите си без транслация, Apache вижда адреса на тунела и 10.8.0.0/24 съвпада. Когато шлюз прави транслация, Apache вижда шлюза и правилото тихо не съвпада с нищо; същото се случва зад балансьор, който завършва TLS пред хоста. За този случай съществува mod_remoteip. RemoteIPHeader X-Forwarded-For заедно с RemoteIPTrustedProxy за балансьора замества записания адрес и само тогава диапазонът има с какво да се сравнява.

Да се довериш на произволна заглавка за препращане е по-лошо от това да нямаш никакво правило. Всеки клиент може да изпрати X-Forwarded-For със 10.8.0.9 и да удовлетвори проверка на диапазон, която никога не е била закотвена към доверен хоп.

Наслоете слушателя и политиката на хранилището

Обвързването е отделна контрола и често по-простата. Listen 10.8.0.1:443 решава кои сокети съществуват и заявка не може да избере хост на сокет, който никога не е отварян. Цената е редът на стартиране: ако интерфейсът на тунела не работи при старта на Apache, обвързването се проваля и услугата не се вдига. Свържете го с подредба на unit-ите или се обвържете към адрес, който съществува независимо от тунела.

Правата за пътища остават в AuthzSVNAccessFile. Валиден акаунт за сайта не е същото разрешение като право на запис в път на проект и мрежовото правило не променя това.

Внимавайте със сливането на секции, когато блокът е във включен файл. Apache слива контейнерите за оторизация през вложени секции и най-конкретната съвпадаща секция може да замени изискването, вместо да го допълни, така че правило върху /svn може да не достигне /svn/repo/trunk, след като по-тясна секция дефинира своето.

Докажете и двата отказа, преди да го обявите за готово

Тествайте четири заявки, не една. Във VPN с валиден акаунт трябва да получите списък на хранилището. Във VPN с грешна парола трябва да получите 401, а не списък. Отвън VPN с валидни данни за вход трябва да получите 403 и същата публична заявка към алтернативно име на хост трябва да се провали по същия начин.

Една команда на случай е достатъчна: curl -sI -u user:pass https://svn.example.com/svn/repo/, после прочетете реда със статуса. Повторете работещия случай и през реалния клиент, защото svn info упражнява DAV методите, които ще използват commit и обновяванията.

Ако някой от четирите резултата не съответства на политиката, която искате, конфигурацията не е завършена и преименуването на хоста няма да промени това.

Подобни статии