Эффективное управление IPtables с помощью Saltstack

Эффективное управление IPtables с помощью Saltstack

Я пытаюсь настроить гибкое решение для управления iptables с помощью SaltStack, но это оказалось сложнее, чем я думал.

Мое главное требование: иметь возможность иметь столб, где я буду хранить список IP-адресов, которые должны быть добавлены в белый список для доступа по SSH на всех миньонах. Этот список IP-адресов, конечно, будет время от времени меняться: некоторые IP-адреса добавляются, некоторые IP-адреса удаляются. Проблема, с которой я сталкиваюсь, связана с удаленными IP-адресами — когда я удаляю их из файла столба, SaltStack не удаляет фактическое добавление в белый список из миньонов.

Единственный обходной путь, который я смог найти, это создать новый ключ с именем "removed-ips", и всякий раз, когда я хотел удалить IP, я добавлял его туда. Второй цикл for затем удалит его. Конечно, это действительно отвратительный обходной путь, есть ли способ сделать это лучше?

/srv/pillar/iptables-default.sls:

iptables-default:
  whitelisted-ips:
    - '55.55.55.55'
    - '66.66.66.66'
    - '77.77.77.77'
  removed-ips:
    - '88.88.88.88'

/srv/salt/iptables-default.sls:

{% for ip in salt['pillar.get']('iptables-default:whitelisted-ips') %}
Whitelist OSF IP {{ip}} for SSH access:
  iptables.append:
    - table: filter
    - family: ipv4
    - chain: INPUT
    - jump: ACCEPT
    - match: state
    - connstate: NEW
    - source: '{{ ip }}'
    - dport: 22
    - proto: tcp
    - save: True
{% endfor %}

{% for ip in salt['pillar.get']('iptables-default:removed-ips') %}
Remove old IPs that are not needed anymore:
  iptables.delete:
    - table: filter
    - family: ipv4
    - chain: INPUT
    - jump: ACCEPT
    - match: state
    - connstate: NEW
    - source: {{ ip }}
    - dport: 22
    - proto: tcp
    - save: True
{% endfor %}

решение1

Я потратил несколько часов, пытаясь найти лучший способ управления различными настройками iptables с помощью Salt, и лучшим решением, похоже, стало сочетание

  1. плоские файлы конфигурации iptables (как шаблоны jinja)
  2. пусть соль сделает сброс iptables + восстановит только в случае изменения файла

вот как это у меня в env и это работает очень хорошо. Я пробовал использовать salt Iptables states, но это становится очень громоздким и неуправляемым, и вам приходится принудительно делать это iptables.flushпри каждом запуске highstate,

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


создайте плоский файл для каждого хоста, используя {{ grains.id }}.j2 в качестве макета,

cat /srv/salt/state/iptables/files/nycweb1.j2


##############################################################
## This file is managed by SALTSTACK - Do not modify manually
##############################################################

*filter
:INPUT ACCEPT
:FORWARD ACCEPT
:OUTPUT ACCEPT

## Allow all loopback (lo0) traffic
-A INPUT -i lo -j ACCEPT

## Drop all traffic to 127/8 that doesn't use lo0
-A INPUT ! -i lo -d 127.0.0.0/8 -j DROP

## Accept inbound traffic for already established connections.
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

## Effectively allow all outbound traffic.
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

## Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

## Blacklist
-A INPUT -s 0.0.0.0/32 -p tcp -m tcp --dport 22 -j REJECT --reject-with icmp-port-unreachable

## Whitelist     
-A INPUT -s 121.236.129.235/32 -p tcp -m tcp --dport 22 -j ACCEPT {# NY office pub #}
-A INPUT -s 192.168.10.0/24 -p tcp -m tcp --dport 22 -j ACCEPT {# NY office priv #}


COMMIT


*nat
:PREROUTING ACCEPT
:INPUT ACCEPT
:OUTPUT ACCEPT
:POSTROUTING ACCEPT
-A PREROUTING -p tcp -m tcp --dport 27015 -j DNAT --to-destination 192.168.38.20
-A OUTPUT -p tcp -m addrtype --src-type LOCAL --dst-type LOCAL -m tcp --dport 1266 -j DNAT --to-destination 169.254.1.1:443
-A POSTROUTING -s 192.168.1.2/32 -d 10.3.4.65/32 -p tcp -m tcp --dport 48854 -j MASQUERADE
-A POSTROUTING -d 10.0.2.15/24 -p tcp -m tcp --dport 27045 -j SNAT --to-source 192.168.99.11 {# description #}

COMMIT
{# EOF #}

создать файл состояния,

cat /srv/salt/state/iptables/init.sls

# STATE - IPTABLES

{% set iptables_file = '/etc/sysconfig/iptables' %}

iptables_pkg:
    pkg.installed:
        - name: iptables

{{ iptables_file }}:
    file.managed:
        - user: root
        - group: root
        - mode: 644
        - source: salt://{{ slspath }}/files/{{ grains.id }}.j2
        - template: jinja

flush_tables:
    iptables.flush:
        - table: filter
        - family: ipv4
        - onchanges:
            - file: "{{ iptables_file }}"

restore_tables: 
    cmd.run:
        - name: "/usr/sbin/iptables-restore < {{ iptables_file }}"
        - onchanges:
            - file: "{{ iptables_file }}"

вот и все, когда вы запускаете highstate на своих целях, они будут делать flush+restore только всякий раз, когда изменяется flat file. Ваша конфигурация также находится в родном формате iptables, а не в формате pillar

теперь примените состояние или добавьте его к своему высокому состоянию

salt nycweb01 state.sls iptables

решение2

Для такого рода вещей, сохраняя список IP-адресов для использования iptables, мы шаблонизируем файл конфигурации "ipset" и используем правила iptables, которые ссылаются на них для списков разрешений или запретов. ipset окупается для больших наборов, и управление ими таким образом устраняет проблему "удаления адреса"; наборы полностью перезагружаются, когда что-либо меняется.

Мы централизованно управляем сетями из тысяч серверов со строгими требованиями к членству и доступу, поэтому использование соли и шаблона jinja для рендеринга /etc/sysconfig/ipset имеет для нас смысл.

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