我正在尝试使用 SaltStack 配置一个灵活的 iptables 管理解决方案,但发现它比我想象的要难。
我的主要要求是:能够有一个支柱,在其中保存 IP 列表,这些 IP 应该被列入白名单,以便在所有 minions 上进行 SSH 访问。这个 IP 列表当然会不时发生变化:一些 IP 被添加,一些 IP 被删除。我面临的问题是删除的 IP - 当我从支柱文件中删除它们时,SaltStack 不会从 minions 中删除实际的白名单。
我能找到的唯一解决方法是创建一个名为“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
我花了几个小时研究使用 Salt 管理各种 iptables 设置的最佳方法,最好的解决方案似乎是结合使用
- 平面 iptables 配置文件(作为 jinja 模板)
- 仅当平面文件发生变化时,才让 salt 执行 iptables flush + restore
这是我在环境中使用的方法,效果很好。我尝试使用 salt Iptables 状态,但它变得非常麻烦和难以管理,你必须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。你的配置也是原生 iptables 格式,而不是 pillar 格式
现在应用该状态,或者将其添加到你的高级状态
salt nycweb01 state.sls iptables
答案2
对于这种需要保留 IP 地址列表以供 iptables 使用的情况,我们会模板化“ipset”配置文件,并使用引用这些 IP 地址的 iptables 规则来设置允许列表或拒绝列表。ipset 适用于大型集合,通过这种方式管理它们可以消除“删除地址”问题;只要有任何变化,这些集合就会完全重新加载。
我们集中管理具有严格成员资格和访问要求的数千台服务器的网络,因此使用 salt 和 jinja 模板来呈现 /etc/sysconfig/ipset 对我们来说很有意义。