CentOS и ARP резолвинг

В некоторых сетевых конфигурациях (например при использовании виртуализации, NAT), можно столкнуться с проблемой доступа в глобальную сеть хостов, которые маскируются маршрутизатором.

Допустим у нас есть сервер под управлением CentOS, который предоставляет доступ в глобальную сеть хостам из локальной сети.



На внешнем интерфейсе нашего маршрутизатора прописаны 2 IP. 10.0.0.2 - основной адрес, выданный провайдером.
172.16.0.1 - дополнительный адрес. Сеть 172.16.0.0/29 маршрутизируется провайдером на наш основной адрес 10.0.0.2.
192.168.0.0/24 - локальная сеть на внутреннем интерфейсе. Основной шлюз (default gateway) - 10.0.0.1
Дополнительный адрес мы используем для маскирования локальной сети, а так же для проброса портов на внутренние сервисы.

В такой конфигурации обнаруживается следующая проблема:  если в таблице арп кеша маршрутизатора нет записи для 10.0.0.1, то
при инициировании соединения со стороны локального клиента ARP request посылается от IP адреса, которым мы его маскируем:
arp who-has 10.0.0.1 tell 172.16.0.1
В зависимости от настроек шлюза провайдера, он в большинстве случаев не ответит на такой  запрос, поскольку адрес, анонсированный в запросе, не принадлежит к сети шлюза провайдера.

Не получив ответа, маршрутизатор не знает на какой мак-адрес отправлять пакет и отвечает клиенту о недоступности сети.

Для того, чтобы наш сервер всегда посылал арп запрос от правильного адреса, в CentOS (справедливо для linux систем c версией ядра начиная с 2.6.4 и 2.4.26), существует настройка ядра arp_announce, которая может принимать 3 значения: 0,1,2 (подробнее можно прочитать здесь: http://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt).

По умолчанию на всех интерфейсах стоит 0 - можно использовать любой IP адрес настроенный на интерфейсе для ARP request.
Рекомендуемое значение 2 - в этом случае система будет игнорировать source IP в исходящем пакете и для арп запроса будет всегда использовать "правильный" адрес. Данную опцию можно поменять как для каждого отдельного интерфейса так и для всех сразу.

Для включения без перезагрузки:
#sysctl -w net.ipv4.conf.all.arp_announce=2
Не забудьте добавить в /etc/sysctl.conf