การจัดการ iptables ด้วย Puppet


10

แนวคิดของการจัดการiptablesกฎของเรากับ Puppet ได้ถูกนำขึ้นมา ฉันเห็นว่าaugeasมีiptablesเลนส์ แต่กำลังทดลองอยู่

ไม่มีใครมีข้อเสนอแนะใด ๆ เกี่ยวกับวิธีการจัดการนี้ โดยหลักการแล้วฉันต้องการสร้างเครือข่ายตามคลาสของเซิร์ฟเวอร์


1
รสชาติของ Linux อะไร? บางคนมีสิ่งที่ iptables เริ่มต้นที่เป็นความคิดที่ดีที่จะทำงานกับ
Freiheit

1
RHEL ในสถานการณ์ของฉัน
Belmin Fernandez

คำตอบ:


6

นี่คือสิ่งที่ฉันทำกับ Red Hat Enterprise (RHEL)

RHEL มีiptablesบริการที่โหลดกฎจาก/etc/sysconfig/iptablesและฉันกำลังทำงานกับการแก้ไขไฟล์นั้นและเริ่มบริการ iptables ใหม่ หลายคนชอบที่จะส่งแฟรกเมนต์ไปยังไดเร็กทอรี iptables.d และสร้าง iptables (ผ่าน make หรืออะไรทำนองนั้น) ruleset จากนั้น ฉันมีสิ่งต่าง ๆ สำหรับการสร้างชุดกฎเริ่มต้นใหม่ แต่ก็ไม่เคยทำอะไรเลย หากความต้องการของคุณง่ายคุณก็สามารถคัดลอกไฟล์ iptables ไปยังระบบ

แม้จะดูเหมือนว่าสิ่งนี้น่าเกลียด แต่ก็มีการทดสอบอย่างละเอียดเกี่ยวกับ RHEL4, RHEL5 และ RHEL6

ฉันทำสิ่งนี้ก่อนที่การสนับสนุนของ augeas จะเป็นหุ่นเชิด ถ้าฉันเขียนมันอีกครั้งวันนี้ฉันจะดูเลนส์ augeas iptables ก่อนหันไปexec { "perl ...": }ใช้

ทั่วโลกบางแห่งกำหนดสำหรับการแก้ไขไฟล์ในสถานที่

อ้างอิงจากสิ่งที่มาจากhttp://reductivelabs.com/trac/puppet/wiki/SimpleTextRecipes

# 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'",
    }
}

คลาส iptables ของฉัน:

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" }
}

6

Puppet Labs มีตัวอย่างใน wiki ของพวกเขานั่นคือModule Iptables Patterns

กล่าวโดยย่อ: คุณสร้างแฟรกเมนต์สำหรับแต่ละเซอร์วิสจากนั้นติดตั้งโดยการเรียกใช้ ipt_fragment ที่กำหนดประเภท:

ipt_fragment {"filter-ftp": sure => present}

เมื่อติดตั้งแฟรกเมนต์ (อยู่ใน /etc/iptables.d/) มันจะทริกเกอร์การทำงานของสคริปต์ที่เชื่อมต่อแฟรกเมนต์ทั้งหมดและรีสตาร์ท iptables


4

คำถามคือคุณตั้งใจจะทำอะไร

การวาง iptables บน Puppet นั้นง่าย: วางสคริปต์ไว้บนเซิร์ฟเวอร์ puppet และให้บริการกับทุกที่ที่คุณต้องการ หากต้องการการปรับแต่งบางอย่างให้ทำเป็นเทมเพลต

ตอนนี้บางทีคุณอาจต้องการบางสิ่งเช่น "ถ้าโฮสต์ X มี WebServer ดังนั้นพอร์ต 80 และ 443 จะต้องเปิดอยู่" ในกรณีนั้นสิ่งที่ฉันแนะนำให้คุณทำคือการเขียนสคริปต์จากหลาย ๆ ส่วนของไฟล์โดยใช้โมดูลทั่วไปconcatenated_fileหรือconcatfilepart(ฉันชอบอันหลังซึ่งเปิดใช้งานการสั่งซื้อ แต่มันไม่พร้อมใช้งานสำหรับส้อมทั้งหมด - ฉันขอให้คุณ ของ camptocamp ซึ่งมี)

ส่วนของไฟล์เหล่านี้สามารถเขียนได้อย่างง่ายดายโดยใช้แม่แบบ เคล็ดลับคือการที่คุณส่งออกconcatfilepartบนApacheชั้น (อาจจะโทรกำหนดที่เตรียมconcatfilepartตามพารามิเตอร์เช่นที่อยู่ IP และพอร์ต) และในiptablesระดับที่คุณจะตระหนักถึงทั้งหมดที่ส่งออกconcatfilepartที่มีแท็กiptablesหรือสิ่งที่ต้องการ

ถ้าคุณทำอย่างนั้นฉันชอบที่จะเห็นโมดูลที่บน GitHub ฉันไม่เคยเขียนโมดูล iptables :-)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.