Спрямування віртуального хоста 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 для URL Subversion. Довідка 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, прив'язка не вдається і служба не піднімається. Поєднайте її з порядком юнітів або прив'яжіть до адреси, що існує незалежно від тунелю.

Права на шляхи залишаються в 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, які використовуватимуть коміти й оновлення.

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

Схожі статті