Представьте себе следующую распространенную ситуацию. Есть сеть, положим 10.0.0.0/24, в ней — веб-сервер 10.0.0.100 и рабочая станция 10.0.0.200. Есть маршрутизатор с внешним адресом 203.0.113.1. Порты 80/443 проброшены внутрь на 10.0.0.100.
Если создать запись вроде www.example.com. IN A 203.0.113.1, то запросы из внешних сетей на https://www.example.com будут отлично работать. Увы, без дополнительных мероприятий не будут работать запросы на этот адрес из внутренней сети.
Чаще всего эту проблему решают с помощью так называемого hairpin NAT. Об этом я уже когда-то писал. Решение с hairpin — приемлемое, но не идеальное. Трафик с этом случае идет через маршрутизатор, даже если оба хоста находятся в одном сегменте канального уровня и могли бы общаться напрямую.
РЕКОМЕНДУЕМ:
Настройка отказоустойчивой сети в Linux с keepalived
Популярность решения с hairpin объяснима. Многие сети вообще не имеют своих серверов DNS, в этом случае других решений и нет. Даже если свои сервера есть, правило для hairpin сетевой администратор может настроить без взаимодействия с администратором сервера DNS. Тем не менее правильное решение этой задачи — использовать split DNS, то есть выдавать разный ответ в зависимости от того, кто спрашивает.
Split DNS в BIND
Рассмотрим пример настройки. Для простоты тестирования в пределах одной машины мы используем адрес 127.0.0.10 в качестве условной «внутренней сети» — под localhost отведена вся сеть 127.0.0.0/8, а не только общеизвестный 127.0.0.1.
Чтобы выдавать разные ответы, нужно создать несколько «представлений» (view) в /etc/named.conf. У каждого view должна быть прописана опция match-clients, которая принимает либо имя ACL, либо ключевое слово any.
Важный момент: если вы используете split DNS, то все зоны нужно поместить в какое-то представление, даже если они используются только в одном представлении. Иначе демон откажется загружать настройки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
acl internal-network { 127.0.0.10/32; }; view "internal" { match-clients { internal-network; }; zone "example.com" { type master; file "/var/named/data/example.com-internal"; }; }; view "external" { match-clients { any; }; zone "example.com" { type master; file "/var/named/data/example.com"; }; }; |
Для тестирования воспользуемся утилитой dig, опять же из пакета BIND. Она позволяет указать адрес источника опцией -b. Убедимся, что записи для www.example.com в файлах example.com и example.com-internal разные, и выполним запросы сначала с 127.0.0.1, затем с 127.0.0.10.
$ cat /var/named/data/example.com | grep www www IN A 203.0.113.1
$ cat /var/named/data/example.com-internal | grep www www IN A 10.0.0.100
$ dig @127.0.0.1 www.example.com a ;; ANSWER SECTION: www.example.com. 86400 IN A 203.0.113.1
$ dig -b127.0.0.10 @127.0.0.1 www.example.com a ;; ANSWER SECTION: www.example.com. 86400 IN A 10.0.0.100
Как видим, во втором случае нам выдали в ответ внутренний адрес, что нам и нужно.
РЕКОМЕНДУЕМ:
Генерация записей для диапазонов адресов BIND
Кто-то скажет, что свой сервер DNS больше не нужен и все можно сделать через админку регистратора. Но если у вас сколько-нибудь сложная внутренняя сеть, это совершенно не так. Свой сервер может сделать сеть более удобной и управляемой, и BIND поможет вам в этом.