shutter 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/shutter.rb CHANGED
@@ -3,5 +3,12 @@ require "shutter/content"
3
3
  require "shutter/command_line"
4
4
 
5
5
  module Shutter
6
- # Your code goes here...
6
+ CONFIG_FILES = %w[
7
+ base.ipt
8
+ iface.dmz
9
+ ip.allow
10
+ ip.deny
11
+ ports.private
12
+ ports.public
13
+ ]
7
14
  end
@@ -1,71 +1,105 @@
1
1
  require 'optparse'
2
2
  require 'shutter/iptables'
3
+ require 'shutter/os'
3
4
 
4
5
  module Shutter
5
- class CommandLine
6
- def initialize( path = "/etc/shutter.d")
7
- @config_path = path
8
- # Make sure that we have the proper files
9
- files = %w[
10
- base.ipt
11
- iface.dmz
12
- ip.allow
13
- ip.deny
14
- ports.private
15
- ports.public
16
- ]
17
- files.each do |name|
18
- file = "#{@config_path}/#{name}"
19
- unless File.exists?(file)
20
- # puts "Creating: #{file}"
21
- File.open(file, 'w') do |f|
22
- f.write(Shutter.const_get(name.upcase.gsub(/\./, "_")))
23
- end
24
- end
25
- end
26
- end
6
+ class CommandLine
7
+ def initialize( path = "/etc/shutter.d")
8
+ # Currently only available to RedHat variants
9
+ @os = Shutter::OS.new
10
+ unless @os.redhat?
11
+ puts "Shutter is currently only compatible with RedHat and its variants."
12
+ puts "Help make it compatible with others (github.com/rlyon/shutter)"
13
+ exit
14
+ end
27
15
 
28
- def execute
29
- options = {}
30
- optparse = OptionParser.new do |opts|
31
- opts.banner = "Usage: shutter [options]"
32
- options[:command] = :save
33
- opts.on( '-s', '--save', 'Output the firewall to stdout.') do
34
- options[:command] = :save
35
- end
36
- opts.on( '-r', '--restore', 'Load the firewall through iptables-restore.') do
37
- options[:command] = :restore
38
- end
39
- options[:debug] = false
40
- opts.on( '-d', '--debug', 'Be a bit more chatty') do
41
- options[:debug] = true
42
- end
43
- opts.on_tail( '-h', '--help', 'Display this screen' ) do
44
- puts opts
45
- exit
46
- end
47
- opts.on_tail( '--version', "Show the version") do
48
- puts Shutter::VERSION
49
- exit
50
- end
51
- end
52
- optparse.parse!
53
- puts "* Using config path: #{@config_path}" if options[:debug]
54
- puts "* Running command: #{options[:command].to_s}" if options[:debug]
55
- send(options[:command])
56
- end
16
+ @config_path = path
17
+ @iptables = Shutter::IPTables::Base.new(@config_path)
18
+
19
+ end
57
20
 
58
- def save
59
- @ipt = Shutter::IPTables::Base.new(@config_path).generate
60
- puts @ipt
61
- end
21
+ def execute
22
+ options = {}
23
+ optparse = OptionParser.new do |opts|
24
+ opts.banner = "Usage: shutter [options]"
25
+ options[:command] = :save
26
+ opts.on( '--init', 'Create the initial configuration files' ) do
27
+ options[:command] = :init
28
+ end
29
+ opts.on( '--reinit', 'Rereate the initial configuration files' ) do
30
+ options[:command] = :reinit
31
+ end
32
+ opts.on( '-s', '--save', 'Output the firewall to stdout. (DEFAULT)') do
33
+ options[:command] = :save
34
+ end
35
+ opts.on( '-r', '--restore', 'Load the firewall through iptables-restore.') do
36
+ options[:command] = :restore
37
+ end
38
+ @persist = false
39
+ opts.on( '-p', '--persist', 'Make the changes persistant. (with --restore)') do
40
+ @persist = true
41
+ end
42
+ options[:debug] = false
43
+ opts.on( '-d', '--debug', 'Be a bit more chatty') do
44
+ options[:debug] = true
45
+ end
46
+ opts.on_tail( '-h', '--help', 'Display this screen' ) do
47
+ puts opts
48
+ exit
49
+ end
50
+ opts.on_tail( '--version', "Show the version") do
51
+ puts Shutter::VERSION
52
+ exit
53
+ end
54
+ end
55
+ optparse.parse!
56
+ puts "* Using config path: #{@config_path}" if @debug
57
+ puts "* Running command: #{options[:command].to_s}" if @debug
58
+ send(options[:command])
59
+ end
62
60
 
63
- def restore
64
- @ipt = Shutter::IPTables::Base.new(@config_path).generate
65
- IO.popen("#{Shutter::IPTables::IPTABLES_RESTORE}", "r+") do |iptr|
66
- iptr.puts @ipt ; iptr.close_write
67
- end
68
- end
61
+ def init
62
+ Shutter::CONFIG_FILES.each do |name|
63
+ file = "#{@config_path}/#{name}"
64
+ unless File.exists?(file)
65
+ # puts "Creating: #{file}"
66
+ File.open(file, 'w') do |f|
67
+ f.write(Shutter.const_get(name.upcase.gsub(/\./, "_")))
68
+ end
69
+ end
70
+ end
71
+ end
69
72
 
70
- end
73
+ def reinit
74
+ Shutter::CONFIG_FILES.each do |name|
75
+ file = "#{@config_path}/#{name}"
76
+ File.open(file, 'w') do |f|
77
+ f.write(Shutter.const_get(name.upcase.gsub(/\./, "_")))
78
+ end
79
+ end
80
+ end
81
+
82
+ def save
83
+ init
84
+ @ipt = @iptables.generate
85
+ puts @ipt
86
+ end
87
+
88
+ def restore
89
+ init
90
+ @ipt = @iptables.generate
91
+ IO.popen("#{Shutter::IPTables::IPTABLES_RESTORE}", "r+") do |iptr|
92
+ iptr.puts @ipt ; iptr.close_write
93
+ end
94
+ persist if @persist
95
+ end
96
+
97
+ def persist
98
+ pfile = ENV['SHUTTER_PERSIST_FILE'] ? ENV['SHUTTER_PERSIST_FILE'] : @iptables.persist_file(@os)
99
+ File.open(pfile, "w") do |f|
100
+ f.write(@ipt)
101
+ end
102
+ end
103
+
104
+ end
71
105
  end
@@ -167,12 +167,12 @@ IP_DENY = %q{# Generated by Shutter
167
167
 
168
168
  PORTS_PUBLIC = %q{
169
169
  # proto port
170
- # 80 tcp
171
- # 443 tcp
170
+ # 80 tcp
171
+ # 443 tcp
172
172
  }
173
173
 
174
174
  PORTS_PRIVATE = %q{
175
175
  # proto port
176
- 22 tcp
176
+ 22 tcp
177
177
  }
178
178
  end
@@ -3,9 +3,10 @@ require 'shutter/iptables/eyepee'
3
3
  require 'shutter/iptables/iface'
4
4
  require 'shutter/iptables/jail'
5
5
  require 'shutter/iptables/port'
6
+ require 'shutter/os'
6
7
 
7
8
  module Shutter
8
- module IPTables
9
- IPTABLES_RESTORE="/sbin/iptables-restore"
10
- end
9
+ module IPTables
10
+ IPTABLES_RESTORE="/sbin/iptables-restore"
11
+ end
11
12
  end
@@ -1,45 +1,49 @@
1
1
  module Shutter
2
- module IPTables
3
- class Base
4
- def initialize( path )
5
- @path = path
6
- file = File.open("#{path}/base.ipt", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class Base
4
+ def initialize( path )
5
+ @path = path
6
+ file = File.open("#{path}/base.ipt", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def persist_file(os)
11
+ "/etc/sysconfig/iptables"
12
+ end
13
13
 
14
- def generate
15
- #generate_nat
16
- generate_filter
17
- end
14
+ def to_s
15
+ @content
16
+ end
18
17
 
19
- def generate_filter
20
- @dmz = Iface.new("#{@path}", :dmz).to_ipt
21
- @content = @content.gsub(/#\ \[RULES:DMZ\]/, @dmz)
22
- @bastards = EyePee.new("#{@path}", :deny).to_ipt
23
- @content = @content.gsub(/#\ \[RULES:BASTARDS\]/, @bastards)
24
- @public = Port.new("#{@path}", :public).to_ipt
25
- @content = @content.gsub(/#\ \[RULES:PUBLIC\]/, @public)
26
- @allow = EyePee.new("#{@path}", :allow).to_ipt
27
- @content = @content.gsub(/#\ \[RULES:ALLOWIP\]/, @allow)
28
- @private = Port.new("#{@path}", :private).to_ipt
29
- @content = @content.gsub(/#\ \[RULES:PRIVATE\]/, @private)
18
+ def generate
19
+ #generate_nat
20
+ generate_filter
21
+ end
30
22
 
31
- # Make sure we are restoring what fail2ban has added
32
- @f2b_chains = Jail.new.fail2ban_chains
33
- @content = @content.gsub(/#\ \[CHAIN:FAIL2BAN\]/, @f2b_chains)
34
- @f2b_rules = Jail.new.fail2ban_rules
35
- @content = @content.gsub(/#\ \[RULES:FAIL2BAN\]/, @f2b_rules)
36
- @jail = Jail.new.jail_rules
37
- @content = @content.gsub(/#\ \[RULES:JAIL\]/, @jail)
23
+ def generate_filter
24
+ @dmz = Iface.new("#{@path}", :dmz).to_ipt
25
+ @content = @content.gsub(/#\ \[RULES:DMZ\]/, @dmz)
26
+ @bastards = EyePee.new("#{@path}", :deny).to_ipt
27
+ @content = @content.gsub(/#\ \[RULES:BASTARDS\]/, @bastards)
28
+ @public = Port.new("#{@path}", :public).to_ipt
29
+ @content = @content.gsub(/#\ \[RULES:PUBLIC\]/, @public)
30
+ @allow = EyePee.new("#{@path}", :allow).to_ipt
31
+ @content = @content.gsub(/#\ \[RULES:ALLOWIP\]/, @allow)
32
+ @private = Port.new("#{@path}", :private).to_ipt
33
+ @content = @content.gsub(/#\ \[RULES:PRIVATE\]/, @private)
38
34
 
39
- # Remove the rest of the comments and extra lines
40
- @content = @content.gsub(/^#.*$/, "")
41
- @content = @content.gsub(/^$\n/, "")
42
- end
43
- end
44
- end
35
+ # Make sure we are restoring what fail2ban has added
36
+ @f2b_chains = Jail.new.fail2ban_chains
37
+ @content = @content.gsub(/#\ \[CHAIN:FAIL2BAN\]/, @f2b_chains)
38
+ @f2b_rules = Jail.new.fail2ban_rules
39
+ @content = @content.gsub(/#\ \[RULES:FAIL2BAN\]/, @f2b_rules)
40
+ @jail = Jail.new.jail_rules
41
+ @content = @content.gsub(/#\ \[RULES:JAIL\]/, @jail)
42
+
43
+ # Remove the rest of the comments and extra lines
44
+ @content = @content.gsub(/^#.*$/, "")
45
+ @content = @content.gsub(/^$\n/, "")
46
+ end
47
+ end
48
+ end
45
49
  end
@@ -1,34 +1,34 @@
1
1
  module Shutter
2
- module IPTables
3
- class EyePee
4
- def initialize( path, state )
5
- @state = state
6
- file = File.open("#{path}/ip.#{state.to_s}", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class EyePee
4
+ def initialize( path, state )
5
+ @state = state
6
+ file = File.open("#{path}/ip.#{state.to_s}", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def to_s
11
+ @content
12
+ end
13
13
 
14
- def to_ipt
15
- @rules = ""
16
- @content.each_line do |ip|
17
- ip_clean = ip.strip
18
- if ip_clean =~ /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(\/[0-9]{0,2})*$/
19
- @rules += send(:"#{@state.to_s}_ipt", ip_clean)
20
- end
21
- end
22
- @rules
23
- end
14
+ def to_ipt
15
+ @rules = ""
16
+ @content.each_line do |ip|
17
+ ip_clean = ip.strip
18
+ if ip_clean =~ /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}(\/[0-9]{0,2})*$/
19
+ @rules += send(:"#{@state.to_s}_ipt", ip_clean)
20
+ end
21
+ end
22
+ @rules
23
+ end
24
24
 
25
- def allow_ipt(ip)
26
- "-A AllowIP -m state --state NEW -s #{ip} -j Allowed\n"
27
- end
25
+ def allow_ipt(ip)
26
+ "-A AllowIP -m state --state NEW -s #{ip} -j Allowed\n"
27
+ end
28
28
 
29
- def deny_ipt(ip)
30
- "-A Bastards -s #{ip} -j DropBastards\n"
31
- end
32
- end
33
- end
29
+ def deny_ipt(ip)
30
+ "-A Bastards -s #{ip} -j DropBastards\n"
31
+ end
32
+ end
33
+ end
34
34
  end
@@ -1,30 +1,30 @@
1
1
  module Shutter
2
- module IPTables
3
- class Iface
4
- def initialize( path, type )
5
- @type = type
6
- file = File.open("#{path}/iface.#{type.to_s}", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class Iface
4
+ def initialize( path, type )
5
+ @type = type
6
+ file = File.open("#{path}/iface.#{type.to_s}", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def to_s
11
+ @content
12
+ end
13
13
 
14
- def to_ipt
15
- @rules = ""
16
- @content.each_line do |line|
17
- line = line.strip
18
- if line =~ /^[a-z].+$/
19
- @rules += send(:"#{@type.to_s}_ipt", line)
20
- end
21
- end
22
- @rules
23
- end
14
+ def to_ipt
15
+ @rules = ""
16
+ @content.each_line do |line|
17
+ line = line.strip
18
+ if line =~ /^[a-z].+$/
19
+ @rules += send(:"#{@type.to_s}_ipt", line)
20
+ end
21
+ end
22
+ @rules
23
+ end
24
24
 
25
- def dmz_ipt( iface )
26
- "-A Dmz -i #{iface} -j ACCEPT\n"
27
- end
28
- end
29
- end
25
+ def dmz_ipt( iface )
26
+ "-A Dmz -i #{iface} -j ACCEPT\n"
27
+ end
28
+ end
29
+ end
30
30
  end
@@ -1,26 +1,26 @@
1
1
  module Shutter
2
- module IPTables
3
- class Jail
4
- def initialize( iptables = "/sbin/iptables")
5
- @iptables = iptables
6
- end
2
+ module IPTables
3
+ class Jail
4
+ def initialize( iptables = "/sbin/iptables")
5
+ @iptables = iptables
6
+ end
7
7
 
8
- def fail2ban_chains
9
- `/sbin/iptables-save | grep "^:fail2ban"`
10
- end
8
+ def fail2ban_chains
9
+ `/sbin/iptables-save | grep "^:fail2ban"`
10
+ end
11
11
 
12
- def fail2ban_rules
13
- `/sbin/iptables-save | grep "^-A fail2ban"`
14
- end
12
+ def fail2ban_rules
13
+ `/sbin/iptables-save | grep "^-A fail2ban"`
14
+ end
15
15
 
16
- def jail_rules
17
- jail = `/sbin/iptables-save | grep "^-A Jail"`
18
- lines = jail.split('\n')
19
- unless lines != [] && lines[-1] == "-A Jail -j RETURN\n"
20
- jail += "-A Jail -j RETURN\n"
21
- end
22
- jail
23
- end
24
- end
25
- end
16
+ def jail_rules
17
+ jail = `/sbin/iptables-save | grep "^-A Jail"`
18
+ lines = jail.split('\n')
19
+ unless lines != [] && lines[-1] == "-A Jail -j RETURN\n"
20
+ jail += "-A Jail -j RETURN\n"
21
+ end
22
+ jail
23
+ end
24
+ end
25
+ end
26
26
  end
@@ -1,35 +1,35 @@
1
1
  module Shutter
2
- module IPTables
3
- class Port
4
- def initialize( path, type )
5
- @type = type
6
- file = File.open("#{path}/ports.#{type.to_s}", "r")
7
- @content = file.read
8
- end
2
+ module IPTables
3
+ class Port
4
+ def initialize( path, type )
5
+ @type = type
6
+ file = File.open("#{path}/ports.#{type.to_s}", "r")
7
+ @content = file.read
8
+ end
9
9
 
10
- def to_s
11
- @content
12
- end
10
+ def to_s
11
+ @content
12
+ end
13
13
 
14
- def to_ipt
15
- @rules = ""
16
- @content.each_line do |line|
17
- line = line.strip
18
- if line =~ /^[1-9].+$/
19
- port,proto = line.split
20
- @rules += send(:"#{@type.to_s}_ipt", port, proto)
21
- end
22
- end
23
- @rules
24
- end
14
+ def to_ipt
15
+ @rules = ""
16
+ @content.each_line do |line|
17
+ line = line.strip
18
+ if line =~ /^[1-9].+$/
19
+ port,proto = line.split
20
+ @rules += send(:"#{@type.to_s}_ipt", port, proto)
21
+ end
22
+ end
23
+ @rules
24
+ end
25
25
 
26
- def private_ipt( port, proto )
27
- "-A Private -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j RETURN\n"
28
- end
26
+ def private_ipt( port, proto )
27
+ "-A Private -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j RETURN\n"
28
+ end
29
29
 
30
- def public_ipt( port, proto )
31
- "-A Public -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j ACCEPT\n"
32
- end
33
- end
34
- end
30
+ def public_ipt( port, proto )
31
+ "-A Public -m state --state NEW -p #{proto} -m #{proto} --dport #{port} -j ACCEPT\n"
32
+ end
33
+ end
34
+ end
35
35
  end
data/lib/shutter/os.rb ADDED
@@ -0,0 +1,41 @@
1
+ module Shutter
2
+ class OS
3
+ def initialize
4
+ unless File.exist?('/proc/version')
5
+ @version = "Unknown"
6
+ end
7
+ end
8
+
9
+ def family
10
+ @family ||= ENV['OS'] ? ENV['OS'] : RUBY_PLATFORM.split('-').last
11
+ end
12
+
13
+ def version
14
+ @version ||= IO.read('/proc/version')
15
+ end
16
+
17
+ def linux?
18
+ return family == "linux"
19
+ end
20
+
21
+ def dist
22
+ case version
23
+ when /Red Hat/
24
+ "RedHat"
25
+ when /Debian/
26
+ "Debian"
27
+ when /Ubuntu/
28
+ "Ubuntu"
29
+ else
30
+ "Unknown"
31
+ end
32
+ end
33
+
34
+ def redhat?
35
+ dist == "RedHat"
36
+ end
37
+
38
+ alias :centos? :redhat?
39
+ alias :fedora? :redhat?
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Shutter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -34,6 +34,7 @@ files:
34
34
  - lib/shutter/iptables/iface.rb
35
35
  - lib/shutter/iptables/jail.rb
36
36
  - lib/shutter/iptables/port.rb
37
+ - lib/shutter/os.rb
37
38
  - lib/shutter/version.rb
38
39
  - shutter.gemspec
39
40
  homepage: ''