module Asbestos::Firewall::IPTables

Public Class Methods

chain(name, default_action) click to toggle source
# File lib/asbestos/firewalls/iptables.rb, line 15
def self.chain(name, default_action)
  default_action = '-' if default_action == :none

  ":#{name.upcase} #{default_action.upcase} [0:0]"
end
open_port(interfaces, port, protocol, comment, remote_address = nil) click to toggle source
# File lib/asbestos/firewalls/iptables.rb, line 22
def self.open_port(interfaces, port, protocol, comment, remote_address = nil)
  if interfaces
    interfaces.collect do |interface|
      accept :state     => :new,
             :protocol  => protocol,
             :port      => port,
             :comment   => comment,
             :interface => interface,
             :remote_address => remote_address
    end
  else
    accept :state     => :new,
           :protocol  => protocol,
           :port      => port,
           :comment   => comment,
           :remote_address => remote_address
  end
end
postamble(host) click to toggle source
# File lib/asbestos/firewalls/iptables.rb, line 111
def self.postamble(host)
  Array.new.tap do |rules|
   rules << log(:limit => '5/min',
                :log_level => 7,
                :log_prefix => "iptables dropped: ",
                :comment => "log dropped packets") if host.log_denials?

   rules << drop(:chain => :input,
                 :comment => "drop packets that haven't been explicitly accepted") if host.chains[:input].upcase == :ACCEPT

   rules << 'COMMIT'
   rules << "# Asbestos completed at #{Time.now.utc}"
  end
end
preamble(host) click to toggle source
# File lib/asbestos/firewalls/iptables.rb, line 4
def self.preamble(host)
  [ "# Generated by Asbestos at #{Time.now.utc} for #{host.name}",
    "# #{Asbestos::HOMEPAGE}",
    "*filter"
  ] +
  host.chains.collect do |name, default_action|
    chain name, default_action
  end
end
rule(args) click to toggle source

TODO: Use iptables’ long options here for clarity?

# File lib/asbestos/firewalls/iptables.rb, line 44
def self.rule(args)
  Array.new.tap do |r|
    chain = \
      if args[:chain]
        args[:chain].to_s.upcase
      else
        'INPUT'
      end
    r << "-A #{chain}"

    r << "-j #{args[:action].upcase}" if args[:action]

    if args[:interface]
      direction = \
        if args[:direction]
          case args[:direction]
            when :incoming
              'i'
            when :outgoing
              'o'
            else
              raise "you must provide a :direction flag of either :incoming or :outgoing"
          end
        elsif %w{INPUT PREROUTING}.include? chain
          'i'
        elsif %w{OUTPUT POSTROUTING}.include? chain
          'o'
        else
          raise "you must provide a :direction flag of either :incoming or :outgoing to use :interface with chain #{chain}"
        end
      r << "-#{direction} #{args[:interface]}"
    end

    r << "-p #{args[:protocol]}" if args[:protocol]
    r << "-d #{args[:local_address]}" if args[:local_address]
    r << "-s #{args[:remote_address]}" if args[:remote_address]

    r << "-m state --state #{args[:state].upcase}" if args[:state]
    #r << "-m #{args[:protocol]} --dport #{args[:port]}" if args[:protocol] && args[:port]
    r << "--dport #{args[:port]}" if args[:port]
    r << "-m limit --limit #{args[:limit]}" if args[:limit]

    r << %{--log-prefix "#{args[:log_prefix]}"} if args[:log_prefix]
    r << "--log-level #{args[:log_level]}" if args[:log_level]

    r << "--icmp-type #{args[:icmp_type]}" if args[:icmp_type]

    if args[:comment]
      if args[:interface]
        r << %{-m comment --comment "#{args[:comment]} on #{args[:interface]}"}
      else
        r << %{-m comment --comment "#{args[:comment]}"}
      end
    end
  end.join(' ')
end