Wskazanie hosta wirtualnego Subversion na adres VPN zmienia to, która witryna odpowiada na żądanie, a nie to, kto może je wysłać. Sprawdzenie dostępu odbywa się później, według reguł w sekcji, która pasowała do adresu URL, a nazwa hosta nigdy nie wchodzi do tej decyzji. Jeśli ServerName był jedyną zmianą, repozytorium jest dokładnie tak samo dostępne jak wczoraj. W konfiguracji trzeba odpowiedzieć na dwa osobne pytania: które gniazdo przyjęło połączenie i jaką tożsamość niosło żądanie.

Co ServerName faktycznie rozstrzyga

Hosting wirtualny oparty na nazwie porównuje nagłówek Host z wpisami ServerName i ServerAlias, wybiera jeden host i pozwala mu obsłużyć żądanie. Samo połączenie zostało przyjęte wcześniej przez gniazdo Listen należące do serwera, a nie do hosta. Dlatego nazwa wyglądająca na prywatną nie daje żadnej ochrony: każdy klient, który dotrze do gniazda, może wysłać ten nagłówek Host. Nazwa jest kluczem routingu, a klucze routingu wybiera wywołujący.

Możesz zobaczyć mapowanie bez zgadywania. apachectl -S wypisuje każdy host, jego port i nazwy oraz oznacza, który jest domyślny dla adresu.

RequireAll to kontener, który czyni oba sprawdzenia obowiązkowymi

Apache 2.4 opakowuje dyrektywy Require jednej sekcji w niejawny RequireAny, więc dwie nagie dyrektywy oznaczają, że wystarczy którakolwiek z nich. Dodaj kontener, a znaczenie się odwraca:

<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 wymaga obu warunków: adresu źródłowego w zakresie tunelu i użytkownika, którego repozytorium akceptuje. To powinno oznaczać tylko-VPN dla adresu URL Subversion. Dokumentacja mod_authz_core opisuje reguły kontenera. Zostaw blok w istniejącym Location repozytorium i pozostaw na miejscu działające już dyrektywy DAV, ponieważ ten fragment nie zastępuje ani AuthType, ani pliku haseł, ani autoryzacji na poziomie ścieżki.

Test źródła pochodzi z mod_authz_host, więc potwierdź, że jest załadowany, zanim zaczniesz debugować cokolwiek innego: apachectl -M | grep authz_host.

Adres, który ocenia Apache, to adres gniazda

Require ip porównuje z adresem, który Apache zapisał dla połączenia, a to nie zawsze jest adres, który klient uważa, że ma.

Gdy VPN trasuje swoje adresy bez tłumaczenia, Apache widzi adres tunelu i 10.8.0.0/24 pasuje. Gdy brama tłumaczy, Apache widzi bramę i reguła po cichu do niczego nie pasuje; to samo dzieje się za modułem równoważenia obciążenia, który kończy TLS przed hostem. Dla tego przypadku istnieje mod_remoteip. RemoteIPHeader X-Forwarded-For wraz z RemoteIPTrustedProxy dla balansera zastępuje zapisany adres i dopiero wtedy zakres ma z czym porównywać.

Zaufanie dowolnemu nagłówkowi przekazywania jest gorsze niż brak jakiejkolwiek reguły. Każdy klient może wysłać X-Forwarded-For zawierający 10.8.0.9 i spełnić sprawdzenie zakresu, które nigdy nie było zakotwiczone w zaufanym przeskoku.

Warstwowo ustaw odbiornik i politykę repozytorium

Przypisanie do adresu to osobna kontrola i często prostsza. Listen 10.8.0.1:443 decyduje, które gniazda istnieją, a żądanie nie może wybrać hosta na gnieździe, które nigdy nie zostało otwarte. Ceną jest kolejność startu: jeśli interfejs tunelu jest wyłączony, gdy Apache startuje, przypisanie się nie udaje i usługa nie wstaje. Połącz to z kolejnością jednostek lub przypisz się do adresu istniejącego niezależnie od tunelu.

Uprawnienia ścieżek pozostają w AuthzSVNAccessFile. Ważne konto dla witryny to nie to samo uprawnienie co dostęp do zapisu w ścieżce projektu, a reguła sieciowa tego nie zmienia.

Uważaj na łączenie sekcji, gdy blok znajduje się w dołączonym pliku. Apache scala kontenery autoryzacji w sekcjach zagnieżdżonych i najbardziej szczegółowa pasująca sekcja może zastąpić wymóg, a nie go uzupełnić, więc reguła na /svn może nie dotrzeć do /svn/repo/trunk, gdy węższa sekcja zdefiniuje własną.

Udowodnij oba odmowy, zanim uznasz to za gotowe

Przetestuj cztery żądania, a nie jedno. Wewnątrz VPN z ważnym kontem powinieneś otrzymać listę repozytorium. Wewnątrz VPN z błędnym hasłem powinieneś otrzymać 401 zamiast listy. Z zewnątrz VPN z ważnymi danymi logowania powinieneś otrzymać 403, a to samo publiczne żądanie do alternatywnej nazwy hosta musi zawieść w ten sam sposób.

Jedno polecenie na przypadek wystarczy: curl -sI -u user:pass https://svn.example.com/svn/repo/, następnie odczytaj wiersz statusu. Powtórz działający przypadek także przez prawdziwego klienta, ponieważ svn info ćwiczy metody DAV, których będą używać commity i aktualizacje.

Jeśli którykolwiek z czterech wyników nie zgadza się z zamierzoną polityką, konfiguracja nie jest gotowa, a zmiana nazwy hosta tego nie zmieni.

Powiązane artykuły