Ogranicz host Subversion do użytkowników VPN za pomocą Apache 2.4
ServerName wybiera host wirtualny, ale nie ogranicza, kto się łączy. Wymagaj zakresu VPN i prawdziwego użytkownika repozytorium, a następnie udowodnij oba odmowy.
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.