Изменить все правила в iptables при смене IP-адреса

Изменить все правила в iptables при смене IP-адреса

У меня есть система сетевого шлюза, использующая iptables для разрешения/запрета трафика во внутреннюю сеть/из нее. Мне приходится вручную добавлять и удалять правила в iptablesзависимости от требований сущностей во внутренней сети, включая NAT-преобразование их трафика. Доверенные сущности во внутренней сети могут запрашивать добавление и удаление правил по мере необходимости. Конечный результат — это набор правил в таблицах natи filter, включая POSTROUTINGправила с SNATцелями, устанавливающие исходный IP-адрес на IP-адрес шлюзовой системы и правила в других таблицах с внешним IP-адресом шлюза как dst.

Я хочу иметь возможность устанавливать IP-адрес шлюзовой системы «на лету». Конечно, это будет иметь разрушительные последствия для сеансов TCP и т. д., но давайте не будем это учитывать. Система решает эти проблемы с помощью других механизмов.

Проблема в том, что неизвестное количество правил в таблицах брандмауэра все еще ссылаются на этот старый исходный IP-адрес.

Есть ли способ легко изменить все эти правила, чтобы использовать новый IP-адрес вместо старого?Конечно, я также могу принять какой-нибудь причудливый скрипт с использованием sed/awk или чего-то подобного, если вы более продвинутый мастер bash, чем я...

решение1

Если трафик, который SNATируется, всегда использует IP-адрес исходящего интерфейса, замените -j SNATна -j MASQUERADE. Это будет использовать тот же SNAT на основе conntrack, но автоматически выберет заменяющий исходный адрес.

Вы можете массово редактировать правила iptables, используя iptables-saveи iptables-restore:

  • Например, чтобы редактировать набор правил в интерактивном режиме (особенно если в вашем редакторе есть хорошая функция поиска и замены):

    iptables-save > /tmp/rules
    vim /tmp/rules
    iptables-restore < /tmp/rules
    

    Используем «vipe» из moreutils:

    iptables-save | vipe | iptables-restore
    
  • Для массовой замены одного точного IP-адреса на другой (помните, что .это подстановочный символ в регулярных выражениях, а также используйте его \bдля гарантии того, что «12.34» случайно не совпадет с «112.34»):

    iptables-save | sed 's/\b12\.34\.56\.78\b/12.34.56.99/g' | iptables-restore
    

Но по моему мнению,любойРедактирование правил iptables (включая скриптовую настройку "iptables -A") — плохой подход. Вместо этого, сохранитеiptables.rules файл(в формате iptables-save) в качестве "источника" и всегда загружать набор правил из этого файла. Затем вы можете начать использовать какую-либо форму языка макросов/шаблонов, чтобы определить IP-адрес один раз и ссылаться на него везде – аналогично тому, как это делается при развертывании файлов конфигурации через Salt/Ansible (если кто-то еще их использует).

  • Например (не делайте этого на самом деле, иначе ситуация слишком быстро станет неуправляемой):

    cat /etc/iptables.rules | sed 's/%CUST_IP%/12.34.56.78/g' | iptables-restore
    
  • Я бы также посоветовал взглянуть на Ferm, который реализует альтернативный синтаксис для правил iptables — в целом он немного более удобочитаем, но также имеет встроенные макросы, так что вы можете @def $cust_ipссылаться на него один раз и использовать его везде.

    domain (ip ip6) {
        @def dns_host4 = 10.10.0.53;
        @def ntp_host4 = 10.10.0.123;
    
        table filter {
            chain FORWARD {
                daddr ($dns_host4 $ntp_host4) accept;
            }
        }
    
        table nat {
            chain PREROUTING {
                proto (tcp udp) dport 53 DNAT to-destination $dns_host4;
                proto udp dport 123 DNAT to-destination $ntp_host4;
            }
        }
    }
    

    Это работает аналогично iptables-restore – вместо того, чтобы вносить изменения в реальном времени, вы редактируете /etc/ferm.confи запускаете fermдля перезагрузки всего набора правил, когда закончите. Если IP-адрес изменится, просто отредактируйте макрос @def в ferm.conf и перезагрузите.

    (Кроме того, к этому полезно привыкнуть, если вы в конечном итоге перейдете на nftables, так как он работает примерно так же, как Ferm — конечно, синтаксис немного отличается, но в нем также есть $macros, и вы редактируете /etc/nftables.conf и перезагружаете все сразу.)

решение2

Я бы рекомендовал iptables в сочетании с ipset.

В iptables у вас должно быть свое правило, но затем добавьте --match-set setname src

iptables -I PREROUTING -s whatever ... --match-set setname src
iptables -I PREROUTING -s whatever ... --match-set setname dst

Затем, чтобы отключить правило, вам нужно удалить IP-адрес из набора с именем «setname». Чтобы включить его, вам нужно просто добавить IP-адрес в setname.

Тогда iptables останется прежним, и вы просто добавите и вычтете записи из setname

При необходимости каждое правило будет иметь другое название.

Связанный контент