symbiosis-firewall-whitelist 3.3 KB
Newer Older
Patrick J Cherry's avatar
Patrick J Cherry committed
1
#! /usr/bin/ruby1.8
2
#
Steve Kemp's avatar
Steve Kemp committed
3
4
5
6
7
8
# NAME
#
#   firewall-whitelist -- Automatically whitelist IP addresses.
#
# SYNOPSIS
#
9
10
11
12
#  Options:
#
#   --prefix      The directory to operate upon.
#
Steve Kemp's avatar
Steve Kemp committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#  Help Options:
#
#   --help        Show the help information for this script.
#   --verbose     Show debugging information.
#
# This script is designed to automatically whitelist IP addresses which
# have been used to successfully login via SSH.
#
# It does this by parsing the output of the "last" command, and creating
# entries in /etc/symbiosis/firewall/whitelist.d/
#
# AUTHOR
#
#   Steve Kemp <steve@bytemark.co.uk>
#

#
#  Modules we require
#

require 'getoptlong'
require 'ipaddr'
Patrick J Cherry's avatar
Patrick J Cherry committed
35
require 'symbiosis/utmp'
36
37
38
require 'symbiosis/firewall/directory'
require 'symbiosis/firewall/template'
require 'tempfile'
Steve Kemp's avatar
Steve Kemp committed
39
40
41

opts = GetoptLong.new(
    [ '--help',    '-h', GetoptLong::NO_ARGUMENT ],
42
    [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
43
44
    [ '--prefix',  '-p', GetoptLong::REQUIRED_ARGUMENT ],
    [ '--template-d', '-t', GetoptLong::REQUIRED_ARGUMENT ]
Steve Kemp's avatar
Steve Kemp committed
45
46
47
)


48
49
50
51
#
#  The options set by the command line.
#
$HELP    = false
Steve Kemp's avatar
Steve Kemp committed
52
$VERBOSE = false
53
54
55
56
57
$PREFIX = "/etc/symbiosis/firewall/"
delete   = false
execute  = false
template_dir = nil
force = true
Steve Kemp's avatar
Steve Kemp committed
58
59
60
61

opts.each do |opt,arg|
  case opt
    when '--help'
62
      $HELP = true
Steve Kemp's avatar
Steve Kemp committed
63
64
    when '--verbose'
      $VERBOSE = true
65
66
    when '--prefix'
      $PREFIX = arg
67
68
    when '--template-d'
      template_dir = arg
Steve Kemp's avatar
Steve Kemp committed
69
70
71
  end
end

72

Steve Kemp's avatar
Steve Kemp committed
73
74
75
#
# CAUTION! Here be quality kode.
#
76
if $HELP
Steve Kemp's avatar
Steve Kemp committed
77
78
79
80
81
82
83
84
85
86
87
88
  # Open the file, stripping the shebang line
  lines = File.open(__FILE__){|fh| fh.readlines}[2..-1]

  lines.each do |line|
    line.chomp!
    break if line.empty?
    puts line[2..-1].to_s
  end

  exit 0
end

89
90
91
92
93
94
95

#
#  Expire old entries first of all, then add new ones.
#
puts "Expiring old whitelist entries" if ( $VERBOSE )

expired = 0
96
whitelist_d = File.join($PREFIX, "whitelist.d")
97

98
99
100
101
102
103
104
# ensure the directory exists.
if ( ! File.directory?( "#{whitelist_d}" ) )
  system( "mkdir -p #{whitelist_d}" )
end

if ( File.directory?( whitelist_d ) )
  Dir.foreach( whitelist_d ) do |entry|
105
    if ( ( entry =~ /\.auto$/i ) &&
106
         (File.mtime( "#{whitelist_d}/#{entry}" ) <  ( Time.now - 8 * 24 * 60 * 60 ) ) )
107
    then
108
109
      puts "Removing #{whitelist_d}/#{entry}" if ( $VERBOSE )
      File.unlink("#{whitelist_d}/#{entry}")
110
111
112
113
114
115
116
      expired += 1
    end
  end
end
puts "Expiring done - removed #{expired} file(s)" if ( $VERBOSE )


Steve Kemp's avatar
Steve Kemp committed
117
#
Patrick J Cherry's avatar
Patrick J Cherry committed
118
# Fetch the IP addresses
Steve Kemp's avatar
Steve Kemp committed
119
#
Patrick J Cherry's avatar
Patrick J Cherry committed
120
ip_addresses = Symbiosis::Utmp.read.collect{|entry| entry["ip"]}
Steve Kemp's avatar
Steve Kemp committed
121
122
123
124
125
126
127
128
129

#
#  Did we update?
#
updated=false

#
#  Iterate over each IP
#
Patrick J Cherry's avatar
Patrick J Cherry committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
ip_addresses.each do |ip|
  #
  # We only want IP addresses.
  #
  next unless ip.is_a?(IPAddr)

  #
  # FIXME: Need better IPv6 conditions.
  #
  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)
       ) 
     )
Steve Kemp's avatar
Steve Kemp committed
145
146
147

    puts "Found IP address: #{ip}" if ( $VERBOSE )

148
    if ( File.exists?( "#{whitelist_d}/#{ip}.auto" ) )
Steve Kemp's avatar
Steve Kemp committed
149
150
151
152
      puts "\tAlready whitelisted" if ( $VERBOSE )
    else

      # create the file
153
      system( "touch #{whitelist_d}/#{ip}.auto" )
Steve Kemp's avatar
Steve Kemp committed
154
155
156
157
158
159
160
161
162
163

      updated=true
      puts "\tAdding to whitelist" if ( $VERBOSE )
    end
  end
end



#
164
# Re-generate the whitelist chain
Steve Kemp's avatar
Steve Kemp committed
165
#
166
167
if ( updated || expired > 0 || force )
  system( "symbiosis-firewall reload-whitelist" )
Steve Kemp's avatar
Steve Kemp committed
168
end
169