Commit 4805607d authored by Patrick J Cherry's avatar Patrick J Cherry
Browse files

Fixed up symbiosis-firewall-{white,black}list to work properly.

parent c737c1e0
......@@ -27,7 +27,12 @@ module Symbiosis
def generate
results = do_read
do_parse_results(results)
do_parse(results)
end
def attempts=(a)
raise ArgumentError, "#{a.inspect} must be an integer" unless a.is_a?(Integer)
@attempts = a
end
private
......
......@@ -90,11 +90,7 @@ module Symbiosis
# resolve addresses
#
hostnames.each do |hostname|
if hostname.is_a?(String)
addresses += do_resolve_name(hostname)
else
addresses << hostname
end
end
#
......@@ -131,7 +127,16 @@ module Symbiosis
ips = []
begin
case name
when IPAddr
ips << name
when String
ips << IPAddr.new(name)
when Nilclass
ips << name
else
warn "#{name.inspect} could not be resolved because it is a #{name.class}." if $VERBOSE
end
rescue ArgumentError
%w(A AAAA).each do |type|
begin
......@@ -252,6 +257,10 @@ module Symbiosis
#
class IPListDirectory < Directory
def include?(template, address)
end
private
#
......
......@@ -69,11 +69,15 @@ class IPAddr < ::IPAddr
end
end
#
# Append the CIDR mask if there is more than on IP in the range.
#
def to_s
[super, cidr_mask].join('/')
s = [super]
s << cidr_mask if max.to_i - min.to_i > 0
s.join("/")
end
end
end
......
......@@ -26,8 +26,8 @@
# -e, --expire-after <n> Number of days after which blacklisted IPs should be
# expired. Defaults to 2.
#
# -p, --prefix <dir> Directory where action.d, incoming.d, outgoing.d etc
# are located. Defaults to /etc/symbiosis/firewall.
# -p, --prefix <dir> Directory where incoming.d, outgoing.d etc are
# located. Defaults to /etc/symbiosis/firewall.
#
# -t, --template-d <dir> Additional directory to search for templates.
#
......@@ -85,7 +85,7 @@ base_dir = "/etc/symbiosis/firewall/"
delete = false
execute = false
template_dir = nil
force = true
force = false
attempts = 20
expire_after = 2
......@@ -117,7 +117,7 @@ opts.each do |opt,arg|
when '--no-delete'
delete = false
when '--force'
force = false
force = true
when '--prefix'
base_dir = File.expand_path(arg)
when '--template-d'
......@@ -167,7 +167,9 @@ blacklist_d = File.join(base_dir, "blacklist.d")
# ensure the directory exists.
if ( ! File.directory?( "#{blacklist_d}" ) )
system( "mkdir -p #{blacklist_d}" )
end
if ( File.directory?( blacklist_d ) )
......@@ -189,40 +191,99 @@ puts "Expiring done - removed #{expired} file(s)" if ( $VERBOSE )
#
# Fetch the IP addresses
#
blacklist = Symbiosis::Blacklist.new
blacklist = Symbiosis::Firewall::Blacklist.new
blacklist.attempts = attempts
blacklist.base_dir = base_dir
whitelist = Symbiosis::IPListDirectory.new(File.join(base_dir, "whitelist.d"))
#
# Did we update?
#
updated=false
#
# Iterate over each IP
#
blacklist.generate.each do |ip, ports|
#
# Make sure we can parse stuff
#
begin
ip = IPAddr.new(ip)
rescue ArgumentError => err
warn "Ignoring #{ip.inspect} because of #{err.to_s}"
next
end
#
# Mask IPv6 to /64s.
#
ip = ip.mask(64) if ip.ipv6?
#
# Mask IPv4 to /32s.
#
ip = ip.mask(32) if ip.ipv4?
#
# Only include globally routable IPs.
#
# FIXME: Need better IPv6 conditions.
#
next if ip.ipv4? and (IPAddr.new("127.0.0.1/8").include?(ip) or IPAddr.new("0.0.0.0") == ip )
next if ip.ipv6? and !IPAddr.new("2000::/3").include?(ip)
puts "Found IP address: #{ip}" if ( $VERBOSE )
fn = File.join(blacklist_d,ip.to_s.gsub("/","-")+".auto" )
#
# Check filename without .auto first.
#
fn = File.join(blacklist_d,ip.to_s.gsub("/","-"))
if ( File.exists?(fn) )
puts "\tAlready blacklisted" if ( $VERBOSE )
puts "\tAlready manually blacklisted" if ( $VERBOSE )
else
# create the file
system( "touch #{fn}" )
#
# Automatically blacklist.
#
fn += ".auto"
if ! File.exists?(fn)
updated=true
puts "\tAdding to blacklist" if ( $VERBOSE )
#
# Write the list of ports
#
File.open(fn,"w"){|fh| fh.print ports.join("\n") }
#
# Create a new file.
#
FileUtils.touch(fn, :mtime => at)
else
updated=true
#
# Update the mtime, if this entry is newer.
#
puts "\tUpdating blacklist entry" if ( $VERBOSE )
old_ports = File.readlines(fn).collect{|pt| pt.chomp.strip }
new_ports = (ports + old_ports).collect{|pt| pt.nil? ? "all" : pt.to_s }.uniq
new_ports = %w(all) if new_ports.any{|pt| "all" == pt}
#
# overwrite file.
#
File.open(fn,"w"){|fh| fh.print ports.join("\n") }
end
end
end
#
# Re-generate the blacklist chain
#
if ( updated || expired > 0 || force )
......@@ -233,6 +294,6 @@ if ( updated || expired > 0 || force )
cmd += ["--prefix", base_dir]
cmd += ["--template-d", template_dir] unless template_dir.nil?
cmd << "reload-blacklist"
exec(cmd)
exec(*cmd)
end
......@@ -60,6 +60,7 @@
require 'getoptlong'
require 'tempfile'
require 'fileutils'
require 'symbiosis/utmp'
require 'symbiosis/firewall/directory'
require 'symbiosis/firewall/template'
......@@ -77,7 +78,7 @@ wtmp_file = "/var/log/wtmp"
delete = false
execute = false
template_dir = nil
force = true
force = false
expire_after = 8
opts = GetoptLong.new(
......@@ -108,7 +109,7 @@ opts.each do |opt,arg|
when '--no-delete'
delete = false
when '--force'
force = false
force = true
when '--prefix'
base_dir = File.expand_path(arg)
when '--template-d'
......@@ -153,31 +154,33 @@ end
puts "Expiring old whitelist entries" if ( $VERBOSE )
expired = 0
whitelist_d = File.join($PREFIX, "whitelist.d")
whitelist_d = File.join(base_dir, "whitelist.d")
# ensure the directory exists.
if ( ! File.directory?( "#{whitelist_d}" ) )
system( "mkdir -p #{whitelist_d}" )
unless File.directory?(whitelist_d)
FileUtils.mkdir_p(whitelist_d)
end
if ( File.directory?( whitelist_d ) )
Dir.foreach( whitelist_d ) do |entry|
if ( ( entry =~ /\.auto$/i ) &&
(File.mtime( "#{whitelist_d}/#{entry}" ) < ( Time.now - 8 * 24 * 60 * 60 ) ) )
then
puts "Removing #{whitelist_d}/#{entry}" if ( $VERBOSE )
File.unlink("#{whitelist_d}/#{entry}")
expire_before = Time.now - ( expire_after * 24 * 60 * 60 )
if File.directory?( whitelist_d )
Dir.glob( File.join(whitelist_d,"*.auto" ) ).each do |entry|
if File.mtime(entry) < expire_before
puts "Removing #{entry}" if ( $VERBOSE )
File.unlink(entry)
expired += 1
end
end
end
puts "Expiring done - removed #{expired} file(s)" if ( $VERBOSE )
end
#
# Fetch the IP addresses
#
ip_addresses = Symbiosis::Utmp.read(wtmp_file).collect{|entry| entry["ip"]}
puts "Expiring done - removed #{expired} file(s)" if ( $VERBOSE )
#
# Did we update?
......@@ -185,46 +188,80 @@ ip_addresses = Symbiosis::Utmp.read(wtmp_file).collect{|entry| entry["ip"]}
updated=false
#
# Iterate over each IP
#
ip_addresses.each do |ip|
# Fetch the IP addresses
#
Symbiosis::Utmp.read(wtmp_file).each do |entry|
begin
ip = Symbiosis::Firewall::IPAddr.new(entry['ip'].to_s)
rescue ArgumentError
#
# We only want IP addresses.
# Oops. Can't interpret the IP.
#
next unless ip.is_a?(IPAddr)
next
end
at = entry['time']
#
# FIXME: Need better IPv6 conditions.
# Make sure the record isn't already expired.
#
if ( ( ip.ipv4? and
!( IPAddr.new("127.0.0.1/8").include?(ip) or IPAddr.new("0.0.0.0") == ip )
) or (
ip.ipv6? and IPAddr.new("2000::/3").include?(ip)
)
)
next unless at > expire_before
#
# Mask IPv6 to /64s.
#
ip = ip.mask(64) if ip.ipv6?
#
# Mask IPv4 to /32s.
#
ip = ip.mask(32) if ip.ipv4?
#
# Only include globally routable IPs.
#
# FIXME: Need better IPv6 conditions.
#
next if ip.ipv4? and (IPAddr.new("127.0.0.1/8").include?(ip) or IPAddr.new("0.0.0.0") == ip )
next if ip.ipv6? and !IPAddr.new("2000::/3").include?(ip)
puts "Found IP address: #{ip}" if ( $VERBOSE )
fn = File.join(whitelist_d,ip.to_s.gsub("/","-")+".auto" )
#
# Check filename without .auto first.
#
fn = File.join(whitelist_d,ip.to_s.gsub("/","-"))
if ( File.exists?(fn) )
puts "\tAlready whitelisted" if ( $VERBOSE )
puts "\tAlready manually whitelisted" if ( $VERBOSE )
else
# create the file
system( "touch #{fn}" )
#
# Automatically whitelist.
#
fn += ".auto"
if ! File.exists?(fn)
updated=true
puts "\tAdding to whitelist" if ( $VERBOSE )
#
# Create a new file.
#
FileUtils.touch(fn, :mtime => at)
elsif File.mtime(fn) < at
#
# Update the mtime, if this entry is newer.
#
puts "\tUpdating whitelist entry" if ( $VERBOSE )
FileUtils.touch(fn, :mtime => at)
end
end
end
end
end
#
# Re-generate the whitelist chain
......@@ -237,7 +274,6 @@ if ( updated || expired > 0 || force )
cmd += ["--prefix", base_dir]
cmd += ["--template-d", template_dir] unless template_dir.nil?
cmd << "reload-whitelist"
exec(cmd)
puts "Executing #{cmd.join(" ")}" if $VERBOSE
exec(*cmd)
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment