محدودکردن میزبان Subversion به کاربران VPN با Apache 2.4
ServerName یک میزبان مجازی انتخاب میکند و محدود نمیکند چه کسی متصل میشود. محدوده VPN و کاربر واقعی مخزن را الزامی کنید و سپس هر دو رد را اثبات کنید.
هدایت یک میزبان مجازی 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 را تمرین میکند که commitها و بهروزرسانیها از آنها استفاده خواهند کرد.
اگر هر یک از چهار نتیجه با سیاستی که در نظر داشتید مخالف باشد، پیکربندی تمام نشده است و تغییر نام میزبان آن را عوض نمیکند.