提出了iptables
使用Puppet 管理规则的想法。我看到augeas
有iptables
镜头,但目前仍处于实验阶段。
有人对如何处理有任何建议吗?理想情况下,我想基于服务器的类构造链。
提出了iptables
使用Puppet 管理规则的想法。我看到augeas
有iptables
镜头,但目前仍处于实验阶段。
有人对如何处理有任何建议吗?理想情况下,我想基于服务器的类构造链。
Answers:
这就是我对Red Hat Enterprise(RHEL)所做的事情。
RHEL的iptables
服务可从中加载规则/etc/sysconfig/iptables
,我正在修改该文件并重新启动iptables服务。许多人喜欢将片段放入iptables.d目录中,并通过make或类似的东西构建一个iptables规则集。我提供了一些用于重建默认规则集的内容,但是通常它什么都不做。如果您的需求很简单,则可以将iptables文件复制到系统中。
尽管这看起来很丑陋,但是已经在RHEL4,RHEL5和RHEL6上进行了全面的测试。
在Augeas支持support之初,我就这样做了。如果今天我又要写的话,在求助之前我会先看augeas iptables镜头exec { "perl ...": }
。
# Ensure that the line "line" exists in "file":
# Usage:
# append_if_no_such_line { dummy_modules:
# file => "/etc/modules",
# line => dummy
# }
#
define append_if_no_such_line($file, $line, $refreshonly = 'false') {
exec { "/bin/echo '$line' >> '$file'":
unless => "/bin/grep -Fxqe '$line' '$file'",
refreshonly => $refreshonly,
}
}
# Ensure that the line "line" exists in "file":
# Usage:
# prepend_if_no_such_line { dummy_modules:
# file => "/etc/modules",
# line => dummy
# }
#
define prepend_if_no_such_line($file, $line, $refreshonly = 'false') {
$line_no_slashes = slash_escape($line)
exec { "/usr/bin/perl -p0i -e 's/^/$line_no_slashes\n/;' '$file'":
unless => "/bin/grep -Fxqe '$line' '$file'",
refreshonly => $refreshonly,
}
}
define insert_line_after_if_no_such_line($file, $line, $after) {
$line_no_slashes = slash_escape($line)
$after_no_slashes = slash_escape($after)
exec { "/usr/bin/perl -p0i -e 's/^($after_no_slashes)\$/\$1\n$line_no_slashes/m' '$file'":
onlyif => "/usr/bin/perl -ne 'BEGIN { \$ret = 0; } \$ret = 1 if /^$line_no_slashes/; END { exit \$ret; }' '$file'",
}
}
define insert_line_before_if_no_such_line($file, $line, $beforeline) {
$line_no_slashes = slash_escape($line)
$before_no_slashes = slash_escape($beforeline)
exec { "/usr/bin/perl -p0i -e 's/^($before_no_slashes)\$/$line_no_slashes\n\$1/m' '$file'":
onlyif => "/usr/bin/perl -ne 'BEGIN { \$ret = 0; } \$ret = 1 if /^$line_no_slashes/; END { exit \$ret; }' '$file'",
}
}
class iptables {
if $lsbmajdistrelease >= '6' {
$primarychain = 'INPUT'
} else {
$primarychain = 'RH-Firewall-1-INPUT'
}
package {
iptables:
ensure => installed # "latest" would be too much
}
service {
iptables:
enable => true, # default on
ensure => running, # start it up if it's stopped
hasstatus => true, # since there's no daemon
}
file {
"/etc/sysconfig/iptables":
ensure => present;
}
##
# Build up a config if it's missing components we expect; should
# automatically repair a config if it's broken for really simple reasons
##
# Very first thing: a comment at the top warning about our evil; add even if
# we're not touching anything else...
prepend_if_no_such_line {
"/etc/sysconfig/iptables comment":
file => "/etc/sysconfig/iptables",
line => "# This file partially managed by puppet; attempts to edit will result in magic reappearances"
}
# start
# *filter
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables *filter":
file => "/etc/sysconfig/iptables",
line => "\\*filter",
after => "#.*",
notify => Service[iptables],
}
# first default chain
# :INPUT ACCEPT [0:0]
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:INPUT":
file => "/etc/sysconfig/iptables",
line => ":INPUT ACCEPT \\[0:0\\]",
after => "\\*filter",
notify => Service[iptables],
}
# second default chain
# :FORWARD ACCEPT [0:0]
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:FORWARD":
file => "/etc/sysconfig/iptables",
line => ":FORWARD ACCEPT \\[0:0\\]",
after => ":INPUT ACCEPT \\[\\d+:\\d+\\]",
notify => Service[iptables],
}
# third default chain
# :OUTPUT ACCEPT [0:0]
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:OUTPUT":
file => "/etc/sysconfig/iptables",
line => ":OUTPUT ACCEPT \\[0:0\\]",
after => ":FORWARD ACCEPT \\[\\d+:\\d+\\]",
notify => Service[iptables],
}
if $lsbmajdistrelease <= 5 {
# Finally, the RH special chain
# :RH-Firewall-1-INPUT - [0:0]
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:RH-Firewall-1-INPUT":
file => "/etc/sysconfig/iptables",
line => ":RH-Firewall-1-INPUT - \\[0:0\\]",
after => ":OUTPUT ACCEPT \\[\\d+:\\d+\\]",
notify => Service[iptables],
}
# redirect INPUT to RH chain
# -A INPUT -j RH-Firewall-1-INPUT
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:INPUT:RH-Firewall-1-INPUT":
file => "/etc/sysconfig/iptables",
line => "-A INPUT -j RH-Firewall-1-INPUT",
after => ":RH-Firewall-1-INPUT - \\[\\d+:\\d+\\]",
notify => Service[iptables],
}
# redirect FORWARD to RH chain
# -A FORWARD -j RH-Firewall-1-INPUT
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:FORWARD:RH-Firewall-1-INPUT":
file => "/etc/sysconfig/iptables",
line => "-A FORWARD -j RH-Firewall-1-INPUT",
after => "-A INPUT -j RH-Firewall-1-INPUT",
notify => Service[iptables],
}
}
# Let anything on localhost work...
# -A $primarychain -i lo -j ACCEPT
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:$primarychain lo":
file => "/etc/sysconfig/iptables",
line => "-A $primarychain -i lo -j ACCEPT",
after => "-A FORWARD -j $primarychain",
notify => Service[iptables],
}
# And let through all the ICMP stuff:
# -A $primarychain -p icmp --icmp-type any -j ACCEPT
if $lsbmajdistrelease >= '6' {
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:$primarychain icmp":
file => "/etc/sysconfig/iptables",
line => "-A $primarychain -p icmp -j ACCEPT",
after => "-A $primarychain -i lo -j ACCEPT",
notify => Service[iptables],
}
} else {
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:$primarychain icmp":
file => "/etc/sysconfig/iptables",
line => "-A $primarychain -p icmp --icmp-type any -j ACCEPT",
after => "-A $primarychain -i lo -j ACCEPT",
notify => Service[iptables],
}
}
# Finally, let anything that's part of an exisiting connection through:
# -A $primarychain -m state --state ESTABLISHED,RELATED -j ACCEPT
insert_line_after_if_no_such_line {
"/etc/sysconfig/iptables:ESTABLISHED":
file => "/etc/sysconfig/iptables",
line => "-A $primarychain -m state --state ESTABLISHED,RELATED -j ACCEPT",
after => "-A $primarychain -p icmp --icmp-type any -j ACCEPT",
notify => Service[iptables],
}
# Very last thing:
# COMMIT
append_if_no_such_line {
"/etc/sysconfig/iptables:COMMIT":
file => "/etc/sysconfig/iptables",
line => "COMMIT",
notify => Service[iptables],
}
# Next to last thing: reject!
# -A $primarychain -j REJECT --reject-with icmp-host-prohibited
insert_line_before_if_no_such_line {
"/etc/sysconfig/iptables:final reject":
file => "/etc/sysconfig/iptables",
line => "-A $primarychain -j REJECT --reject-with icmp-host-prohibited",
beforeline => "COMMIT",
notify => Service[iptables],
}
}
# example:
# iptable_rule { "iptable:ssh":
# rule => "-m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT"
# }
# change your mind about a rule, do this:
# iptable_rule { "iptable:ssh":
# rule => "-m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT",
# ensure => "absent",
# }
define iptable_rule($rule, $ensure = 'present') {
if $lsbmajdistrelease >= '6' {
$primarychain = 'INPUT'
} else {
$primarychain = 'RH-Firewall-1-INPUT'
}
$iptablesline = "-A $primarychain $rule"
case $ensure {
default: { err ( "unknown ensure value $ensure" ) }
present: {
insert_line_before_if_no_such_line {
"/etc/sysconfig/iptables:add $rule":
file => "/etc/sysconfig/iptables",
line => $iptablesline,
beforeline => "-A $primarychain -j REJECT --reject-with icmp-host-prohibited",
notify => Service[iptables],
}
}
absent: {
delete_lines {
"/etc/sysconfig/iptables:remove $rule":
file => "/etc/sysconfig/iptables",
pattern => $iptablesline,
notify => Service[iptables],
}
}
}
}
# Example:
# iptable_tcp_port { "iptable:ssh":
# port => "22",
# }
# Example:
# iptable_tcp_port { "iptable:oracle:130.157.5.0/24":
# port => "1521",
# source => "130.157.5.0/24",
# }
# (add ensure => "absent" to remove)
define iptable_tcp_port($port, $ensure = 'present', $source = 'ANY') {
case $source {
"ANY": {
iptable_rule {
"iptable_tcp_port:$port":
rule => "-m state --state NEW -m tcp -p tcp --dport $port -j ACCEPT",
ensure => $ensure,
}
}
default: {
iptable_rule {
"iptable_tcp_port:$port:$source":
rule => "-m state --state NEW -m tcp -p tcp --source $source --dport $port -j ACCEPT",
ensure => $ensure,
}
}
}
}
# Example:
# iptable_udp_port { "iptable:ntp":
# port => "123",
# }
# (again, ensure => "absent" if needed)
define iptable_udp_port($port, $ensure = 'present', $source = 'ANY') {
case $source {
"ANY": {
iptable_rule {
"iptable_udp_port:$port":
rule => "-p udp -m udp --dport $port -j ACCEPT",
ensure => $ensure,
}
}
default: {
iptable_rule {
"iptable_udp_port:$port":
rule => "-p udp -m udp --source $source --dport $port -j ACCEPT",
ensure => $ensure,
}
}
}
}
class ssh {
include iptables
iptable_tcp_port {
"iptables:ssh":
port => "22",
ensure => "present"
}
}
class ssh_restricted inherits ssh {
Iptable_tcp_port["iptables:ssh"]{ensure => "absent"}
iptable_tcp_port {
"ssh:RESTRICTED":
port => "22",
source => "X.Y.0.0/16",
ensure => "present";
}
}
class apache {
iptable_tcp_port {
"iptables:http":
require => Service["httpd"],
port => "80";
}
}
class apache::secure {
iptable_tcp_port {
"iptables:https":
require => Service["httpd"],
port => "443";
}
}
class snmp {
iptable_udp_port { "iptables:snmp": port => "161" }
}
Puppet Labs在其Wiki中有一个示例:Module Iptables Patterns
简而言之:您可以为每个服务创建片段,然后通过调用ipt_fragment define-type来安装它们:
ipt_fragment {“ filter-ftp”:确保=>存在}
当安装了一个片段时(它们位于/etc/iptables.d/中),它将触发脚本的执行,该脚本将所有片段连接起来并重新启动iptables。
问题是,您打算完成什么?
将iptables放在Puppet上很容易:将脚本放在puppet服务器上,然后将其提供给您需要的任何地方。如果需要自定义,请使其成为模板。
现在,您可能想要类似“如果主机X具有WebServer,则必须打开其端口80和443”。在这种情况下,我建议您使用Common模块的concatenated_file
或concatfilepart
(我希望使用后者,它可以启用排序功能,但并非在所有fork上都可用)从多个文件部分组成脚本。营地的)。
这些文件部分可以使用模板轻松编写。诀窍在于,你出口的concatfilepart
对Apache
类(可能是通过调用一个定义,准备一个concatfilepart
基于参数,如IP地址和端口),并在iptables
类中,你会体会到所有导出concatfilepart
标记iptables
或类似的东西。
如果您这样做,我很乐意在github上看到该模块。我从来没有写过iptables模块。:-)