module Construqt::Flavour::Ubuntu::Firewall

Public Class Methods

create(host, ifname, iface) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 439
def self.create(host, ifname, iface)
  throw 'interface must set' unless ifname
  writer = iface.host.result.etc_network_iptables
  create_from_iface(ifname, iface, writer)
  create_from_iface(ifname, iface.delegate.vrrp.delegate, writer) if iface.delegate.vrrp
  writer_local = host.result.etc_network_interfaces.get(iface)
  writer_local.lines.up("iptables-restore < /etc/network/iptables.cfg")
  writer_local.lines.up("ip6tables-restore < /etc/network/ip6tables.cfg")
end
create_from_iface(ifname, iface, writer) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 430
def self.create_from_iface(ifname, iface, writer)
  iface.firewalls && iface.firewalls.each do |firewall|
    firewall.get_raw && Firewall.write_raw(firewall, firewall.get_raw, ifname, iface, writer.raw)
    firewall.get_nat && Firewall.write_nat(firewall, firewall.get_nat, ifname, iface, writer.nat)
    firewall.get_forward && Firewall.write_forward(firewall, firewall.get_forward, ifname, iface, writer.filter)
    firewall.get_host && Firewall.write_host(firewall, firewall.get_host, ifname, iface, writer.filter)
  end
end
filter_routes(routes, family) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 129
def self.filter_routes(routes, family)
  routes.map{|i| i.dst }.select{|i| family == Construqt::Addresses::IPV6 ? i.ipv6? : i.ipv4? }
end
icmp_type(family, type) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 283
def self.icmp_type(family, type)
  {
    Construqt::Firewalls::ICMP::PingRequest => {
        :v4 => "-m icmp --icmp-type 8/0",
        :v6 => "--icmpv6-type 128"
    }
  }[type][family]
end
protocol_loop(rule) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 268
def self.protocol_loop(rule)
  protocol_loop = []
  {
    'tcp' => rule.tcp?,
    'udp' => rule.udp?,
    'esp' => rule.esp?,
    'ah' => rule.ah?,
    'icmp' => rule.icmp?
  }.each do |proto, enabled|
    protocol_loop << "-p #{proto}" if enabled
  end
  protocol_loop = [''] if protocol_loop.empty?
  protocol_loop
end
write_forward(fw, forward, ifname, iface, writer) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 292
def self.write_forward(fw, forward, ifname, iface, writer)
  forward.rules.each do |rule|
    throw "ACTION must set #{ifname}" unless rule.get_action
    #puts "write_forward #{rule.inspect} #{rule.input_only?} #{rule.output_only?}"
    if rule.get_log
      to_from = ToFrom.new.bind_interface(ifname, iface, rule).assign_in_out(rule)
        .end_to("--nflog-prefix o:#{rule.get_log}:#{ifname}")
        .end_from("--nflog-prefix i:#{rule.get_log}:#{ifname}")
      fw.ipv4? && write_table("iptables", rule.clone.action("NFLOG"), to_from.factory(writer.ipv4.forward))
      fw.ipv6? && write_table("ip6tables", rule.clone.action("NFLOG"), to_from.factory(writer.ipv6.forward))
    end

    protocol_loop(rule).each do |protocol|
      {:v4 => { :enabled => fw.ipv4?, :table => "iptables", :writer => writer.ipv4.forward },
       :v6 => { :enabled => fw.ipv6?, :table => "ip6tables", :writer => writer.ipv6.forward }}.each do |family, cfg|
        next unless cfg[:enabled]
        to_from = ToFrom.new.bind_interface(ifname, iface, rule).assign_in_out(rule)
        if protocol == "-p icmp" && family == :v6
          my_protocol = "-p icmpv6"
        else
          my_protocol = protocol
        end
        to_from.push_begin_to(my_protocol)
        to_from.push_begin_from(my_protocol)

        if rule.get_ports && !rule.get_ports.empty?
          to_from.push_middle_from("-m multiport --dports #{rule.get_ports.join(",")}")
          to_from.push_middle_to("-m multiport --sports #{rule.get_ports.join(",")}")
        end
        if rule.icmp? && rule.get_type
          to_from.push_middle_from(icmp_type(family, rule.get_type))
        end

        if rule.connection?
          to_from.push_middle_from("-m state --state NEW,ESTABLISHED")
          to_from.push_middle_to("-m state --state RELATED,ESTABLISHED")
        end
        write_table(cfg[:table], rule, to_from.factory(cfg[:writer]))
      end
    end
  end
end
write_host(fw, host, ifname, iface, writer) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 373
def self.write_host(fw, host, ifname, iface, writer)
  host.rules.each do |rule|
    if rule.get_log
      nflog_rule = rule.clone.action("NFLOG")
      l_in_to_from = ToFrom.new.bind_interface(ifname, iface, nflog_rule).input_only
        .end_from("--nflog-prefix o:#{rule.get_log}:#{ifname}")
      l_out_to_from = ToFrom.new.bind_interface(ifname, iface, nflog_rule).output_only
        .end_to("--nflog-prefix i:#{rule.get_log}:#{ifname}")
      fw.ipv4? && write_table("iptables", nflog_rule, l_in_to_from.factory(writer.ipv4.input))
      fw.ipv4? && write_table("iptables", nflog_rule, l_out_to_from.factory(writer.ipv4.output))
      fw.ipv6? && write_table("ip6tables", nflog_rule, l_in_to_from.factory(writer.ipv6.input))
      fw.ipv6? && write_table("ip6tables", nflog_rule, l_out_to_from.factory(writer.ipv6.output))
    end
    next create_link_local(fw, ifname, iface, rule, writer) if rule.link_local?

    protocol_loop(rule).each do |protocol|
      [{
        :doit    => rule.input_only?,
        :from_to => lambda { ToFrom.new.bind_interface(ifname, iface, rule).input_only },
        :writer4 => !rule.from_is_inbound? ? writer.ipv4.input : writer.ipv4.output,
        :writer6 => !rule.from_is_inbound? ? writer.ipv6.input : writer.ipv6.output
      },{
        :doit    => rule.output_only?,
        :from_to => lambda { ToFrom.new.bind_interface(ifname, iface, rule).output_only },
        :writer4 => rule.from_is_inbound? ? writer.ipv4.input : writer.ipv4.output,
        :writer6 => rule.from_is_inbound? ? writer.ipv6.input : writer.ipv6.output
      }].each do |to_from_writer|
        next unless to_from_writer[:doit]
        {:v4 => { :enabled => fw.ipv4?, :table => "iptables", :writer => to_from_writer[:writer4]},
         :v6 => { :enabled => fw.ipv6?, :table => "ip6tables", :writer => to_from_writer[:writer6] }}.each do |family, cfg|
          to_from = to_from_writer[:from_to].call
          next unless cfg[:enabled]
          if protocol == "-p icmp" && family == :v6
            my_protocol = "-p icmpv6"
          else
            my_protocol = protocol
          end
          to_from.push_begin_to(my_protocol)
          to_from.push_begin_from(my_protocol)
          if rule.get_ports && !rule.get_ports.empty?
            to_from.push_middle_from("-m multiport --dports #{rule.get_ports.join(",")}")
            to_from.push_middle_to("-m multiport --sports #{rule.get_ports.join(",")}")
          end
          if rule.icmp? && rule.get_type
            to_from.push_middle_from(icmp_type(family, rule.get_type))
          end
          if rule.connection?
            to_from.push_middle_from("-m state --state NEW,ESTABLISHED")
            to_from.push_middle_to("-m state --state RELATED,ESTABLISHED")
          end
          write_table(cfg[:table], rule, to_from.factory(cfg[:writer]))
        end
      end
    end
  end
end
write_nat(fw, nat, ifname, iface, writer) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 254
def self.write_nat(fw, nat, ifname, iface, writer)
  nat.rules.each do |rule|
    throw "ACTION must set #{ifname}" unless rule.get_action
    throw "TO_SOURCE must set #{ifname}" unless rule.to_source?
    if rule.to_source? && rule.postrouting?
      src = iface.address.ips.select{|ip| ip.ipv4?}.first
      throw "missing ipv4 address and postrouting and to_source is used #{ifname}" unless src
      to_from = ToFrom.new.bind_interface(ifname, iface, rule).assign_in_out(rule).end_to("--to-source #{src}")
        .ifname(ifname).factory(writer.ipv4.postrouting)
      fw.ipv4? && write_table("iptables", rule, to_from)
    end
  end
end
write_raw(fw, raw, ifname, iface, writer) click to toggle source
# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 235
def self.write_raw(fw, raw, ifname, iface, writer)
  #        puts ">>>RAW #{iface.name} #{raw.firewall.name}"
  raw.rules.each do |rule|
    throw "ACTION must set #{ifname}" unless rule.get_action
    if rule.prerouting?
      to_from = ToFrom.new.bind_interface(ifname, iface, rule).assign_in_out(rule)
      #puts "PREROUTING #{to_from.inspect}"
      fw.ipv4? && write_table("iptables", rule, to_from.factory(writer.ipv4.prerouting))
      fw.ipv6? && write_table("ip6tables", rule, to_from.factory(writer.ipv6.prerouting))
    end

    if rule.output?
      to_from = ToFrom.new.bind_interface(ifname, iface, rule).assign_in_out(rule)
      fw.ipv4? && write_table("iptables", rule, to_from.factory(writer.ipv4.output))
      fw.ipv6? && write_table("ip6tables", rule, to_from.factory(writer.ipv6.output))
    end
  end
end
write_table(iptables, rule, to_from) click to toggle source

def self.try_tags_as_ipaddress(list, family, *possible_addrs)

return list unless list.empty?
ret = possible_addrs.map do |addr|
  next nil unless addr
  begin
    addr = IPAddress.parse(addr)
    next addr if (addr.ipv4? && family == Construqt::Addresses::IPV4) || (addr.ipv6? && family == Construqt::Addresses::IPV6)
    nil
  rescue Exception => e
    nil
  end
end.compact
binding.pry unless ret.empty?
ret

end

# File lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb, line 149
        def self.write_table(iptables, rule, to_from)
          family = iptables=="ip6tables" ? Construqt::Addresses::IPV6 : Construqt::Addresses::IPV4
          if rule.from_my_net?
            networks = iptables=="ip6tables" ? to_from.get_interface.address.v6s : to_from.get_interface.address.v4s
            if rule.from_route?
              networks += self.filter_routes(to_from.get_interface.address.routes, family)
            end
            from_list = IPAddress.summarize(networks)
          else
            from_list = Construqt::Tags.ips_net(rule.get_from_net, family)
#            from_list = try_tags_as_ipaddress(from_list, family, rule.get_from_net)
          end

          if rule.to_my_net?
            networks = iptables=="ip6tables" ? to_from.get_interface.address.v6s : to_from.get_interface.address.v4s
            if rule.from_route?
              networks += self.filter_routes(to_from.get_interface.address.routes, family)
            end
            to_list = IPAddress.summarize(networks)
          else
            if rule.get_to_host
              to_list = Construqt::Tags.ips_hosts(rule.get_to_host, family)
            else
              to_list = Construqt::Tags.ips_net(rule.get_to_net, family)
            end
#           to_list = try_tags_as_ipaddress(to_list, family, rule.get_to_net, rule.get_to_host)
          end
          unless rule.get_to_net_addr.empty?
            #binding.pry
            addrs = rule.get_to_net_addr.map { |i| IPAddress.parse(i) }.select { |i|
              (i.ipv6? && family == Construqt::Addresses::IPV6) || (i.ipv4? && family == Construqt::Addresses::IPV4)
            }
            to_list = IPAddress.summarize(to_list + addrs)
          end
          unless rule.get_from_net_addr.empty?
            addrs = rule.get_from_net_addr.map { |i| IPAddress.parse(i) }.select { |i|
              (i.ipv6? && family == Construqt::Addresses::IPV6) || (i.ipv4? && family == Construqt::Addresses::IPV4)
            }
            from_list = IPAddress.summarize(from_list + addrs)
          end
          #puts ">>>>>#{from_list.inspect}"
          #puts ">>>>>#{state.inspect} end_to:#{state.end_to}:#{state.end_from}:#{state.middle_to}#{state.middle_from}"
          action_i = action_o = rule.get_action
          if to_list.empty? && from_list.empty?
            #puts "write_table=>o:#{to_from.output_only?}:#{to_from.output_ifname} i:#{to_from.input_only?}:#{to_from.input_ifname}"
            if to_from.output_only?
              to_from.factory!.row("#{to_from.output_ifname}#{to_from.get_begin_from}#{to_from.get_middle_to} -j #{rule.get_action}#{to_from.get_end_to}")
            end

            if to_from.input_only?
              to_from.factory!.row("#{to_from.input_ifname}#{to_from.get_begin_to}#{to_from.get_middle_from} -j #{rule.get_action}#{to_from.get_end_from}")
            end
          end

          if to_list.length > 1
            # work on these do a better hashing
            action_o = "I.#{to_from.get_ifname}.#{rule.object_id.to_s(32)}"
            action_i = "O.#{to_from.get_ifname}.#{rule.object_id.to_s(32)}"
            to_list.each do |ip|
              if to_from.output_only?
                to_from.factory!.table(action_o).row("#{to_from.output_ifname} -d #{ip.to_string} -j #{rule.get_action}")
              end

              if to_from.input_only?
                to_from.factory!.table(action_i).row("#{to_from.input_ifname} -s #{ip.to_string} -j #{rule.get_action}")
              end
            end

          elsif to_list.length == 1
            from_dst = " -d #{to_list.first.to_string}"
            to_src = " -s #{to_list.first.to_string}"
          else
            from_dst = to_src =""
          end

          from_list.each do |ip|
            if to_from.output_only?
              to_from.factory!.row("#{to_from.output_ifname}#{to_from.get_begin_from} -s #{ip.to_string}#{from_dst}#{to_from.get_middle_from} -j #{action_o}#{to_from.get_end_to}")
            end

            if to_from.input_only?
              to_from.factory!.row("#{to_from.input_ifname}#{to_from.get_begin_to}#{to_src} -d #{ip.to_string}#{to_from.get_middle_to} -j #{action_i}#{to_from.get_end_from}")
            end
          end
        end