
Estou tentando configurar uma solução flexível de gerenciamento de iptables com SaltStack, mas acho mais difícil do que pensei que seria.
Meu principal requisito: poder ter um pilar onde guardo uma lista de IPs, que deveriam estar na lista de permissões para acesso SSH em todos os minions. É claro que esta lista de IPs mudará de vez em quando: alguns IPs são adicionados, alguns IPs são removidos. O problema que estou enfrentando são os IPs removidos - quando eu os removo do arquivo pilar, o SaltStack não remove a lista de permissões real dos minions.
A única solução alternativa que consegui encontrar foi criar uma nova chave chamada "removed-ips" e sempre que eu quiser remover um IP, eu o adicionaria lá. O segundo loop for irá removê-lo. Claro, esta é uma solução alternativa realmente desagradável. Existe uma maneira melhor de fazer isso?
/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 %}
Responder1
Passei algumas horas descobrindo a melhor maneira de gerenciar várias configurações do iptables com Salt, e a melhor solução parece ser fazer uma combinação de
- arquivos de configuração flat iptables (como modelos jinja)
- faça com que o salt faça um iptables flush + restaure apenas se o arquivo simples for alterado
é assim que tenho no meu ambiente e funciona muito bem. Eu tentei usar estados salt Iptables, mas fica muito complicado e incontrolável e você tem que fazer isso com força iptables.flush
em cada execução de estado alto,
A seguir está uma abordagem mais simples e gerenciável que evita completamente o uso de pilares,
crie um arquivo simples para cada host usando {{grains.id}}.j2 como layout,
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 #}
crie um arquivo de estado,
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 }}"
é isso, quando você executa highstate em seus alvos, eles só farão flush+restore sempre que o arquivo simples for modificado. Sua configuração também está no formato iptables nativo, não no formato pilar
agora aplique o estado ou adicione-o ao seu estado mais alto
salt nycweb01 state.sls iptables
Responder2
Para esse tipo de coisa, mantendo uma lista de endereços IP para uso pelo iptables, modelamos o arquivo de configuração "ipset" e usamos regras de iptables que os referenciam para listas de permissão ou negação. Um ipset compensa para conjuntos grandes, e gerenciá-los dessa forma elimina o problema de “remover um endereço”; os conjuntos são completamente recarregados sempre que algo muda.
Estamos gerenciando centralmente redes de milhares de servidores com requisitos rígidos de adesão e acesso, portanto, usar salt e um modelo jinja para renderizar /etc/sysconfig/ipset faz sentido para nós.